2016-04-05 1 views
1

J'ai écrit un programme simple pour utiliser Qt (version 5.5 construit à partir de la source pour Visual Studio 2013 suite à this guide) pour communiquer avec Arduino.Erreur QSerial communiquant avec Arduino

est ici simple firmware qui se lit de la série et au bout de 10 secondes impressions « 1 » Retour:

void setup() { 
    Serial.begin(9600); //Open Serial connection for debugging 
} 

void loop() { 
if (Serial.available()) { 
    char user_input = Serial.read(); 
    if (user_input == '1') { 
     delay(10000); 
     Serial.print('1'); 
    } 
} 

Voici le programme Qt qui envoient « 1 » série lorsque j'appuie sur le bouton de démarrage et continue d'écouter des messages à lire:

main.cpp

#include "mainwindow.h" 
#include <QApplication> 

#pragma comment(lib, "advapi32") 

int main(int argc, char *argv[]) { 
    QApplication a(argc, argv); 
    MainWindow w; 
    w.show(); 
    return a.exec(); 
} 

mainwindow.h

#pragma once 

#include <QMainWindow> 
#include "SerialHandler.h" 

namespace Ui { 
    class MainWindow; 
} 

class MainWindow : public QMainWindow { 
    Q_OBJECT 

public: 
    explicit MainWindow(QWidget *parent = 0); 
    ~MainWindow(); 

private: 
    Ui::MainWindow* ui; 
    SerialHandler serialHandler; 
public slots: 
    void onStart(); 
}; 

mainwindow.cpp

#include "mainwindow.h" 
#include "ui_mainwindow.h" 

MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent), ui(new Ui::MainWindow), serialHandler(QString("COM6")) { 
    ui->setupUi(this); 
    QObject::connect(ui->startButton, SIGNAL(released()), this, SLOT(onStart())); 
} 

MainWindow::~MainWindow() { 
    delete ui; 
} 

void MainWindow::onStart() { 
    serialHandler.moveForward(); 
} 

SerialHandler.h

#pragma once 

#include <QString> 
#include <QtSerialPort> 
#include <QtSerialPort/QSerialPort> 


class SerialHandler { 
public: 
    SerialHandler(QString& serialName); 
    ~SerialHandler(); 
    void moveForward(); 

private: 
    QSerialPort serial; 
    void writeOnSerial(QByteArray& msg); 

private slots: 
    void handleReadyRead(); 
}; 

SerialHandler.cpp

#include "SerialHandler.h" 
#include <QDebug> 
#include <QObject> 


SerialHandler::SerialHandler(QString& serialName){ 
    connect(&serial, SIGNAL(readyRead()), this, SLOT(handleReadyRead())); 

    // Initialize Serial 
    serial.setPortName(serialName); 

    if (!serial.setBaudRate(QSerialPort::Baud9600)) { 
     throw std::runtime_error(QObject::tr("Can't set rate 9600 baud to port %1, error code %2") 
      .arg(serial.portName()).arg(serial.error()).toStdString()); 
    } 

    if (!serial.open(QIODevice::ReadWrite)) { 
     throw std::runtime_error(QObject::tr("Can't open %1, error code %2") 
      .arg(serial.portName()).arg(serial.error()).toStdString()); 
    } 

    if (!serial.setDataBits(QSerialPort::Data8)) { 
     throw std::runtime_error(QObject::tr("Can't set 8 data bits to port %1, error code %2") 
      .arg(serial.portName()).arg(serial.error()).toStdString()); 
    } 

    if (!serial.setParity(QSerialPort::NoParity)) { 
     throw std::runtime_error(QObject::tr("Can't set no patity to port %1, error code %2") 
      .arg(serial.portName()).arg(serial.error()).toStdString()); 
    } 

    if (!serial.setStopBits(QSerialPort::OneStop)) { 
     throw std::runtime_error(QObject::tr("Can't set 1 stop bit to port %1, error code %2") 
      .arg(serial.portName()).arg(serial.error()).toStdString()); 
    } 

    if (!serial.setFlowControl(QSerialPort::NoFlowControl)) { 
     throw std::runtime_error(QObject::tr("Can't set no flow control to port %1, error code %2") 
      .arg(serial.portName()).arg(serial.error()).toStdString()); 
    } 
} 

SerialHandler::~SerialHandler(){ 
    if (serial.isOpen()) { 
     serial.close(); 
    } 
} 

void SerialHandler::handleReadyRead() { 
    qDebug() << serial.readAll(); 
} 

void SerialHandler::writeOnSerial(QByteArray& msg) { 
    if (serial.isOpen() && serial.isWritable()) { 
     serial.write(msg); 
     serial.flush(); 
    } 
} 

void SerialHandler::moveForward(){ 
    QByteArray msg("1"); 
    writeOnSerial(msg); 
} 

le problème apparaît dans la méthode writeOnSerial (SerialHandler.cpp). L'appel à serial.write() déclenche cette erreur:

QObject::startTimer: Timers can only be used with threads started with QThread 

le « 1 » est écrit sur série et lu par le arduino, mais l'ordinateur ne reçoit jamais rien de nouveau au bout de 10 secondes, le signal readyRead() est jamais viré!

J'ai vu la même erreur dans this post, mais dans mon cas, la boucle exec est là!

Des suggestions?

+0

Je pense que votre construction est également demi-cassé: vous ne devriez pas avoir besoin d'inclure '', ni le commentaire '#pragma (lib, "advapi32")' nécessaire. Incluez simplement '' (* ou * '' mais pas les deux!). Si cela ne fonctionne pas, votre fichier '.pro' ne contient pas la ligne' QT + = serialport' (et/ou vous n'avez pas relancé qmake). –

+1

Notez que si vous définissez les paramètres du port avant son ouverture, les méthodes renverront toutes true par conception. Les paramètres seront définis lors de l'ouverture du port, et s'ils échouent, 'open' échouera et retournera faux. C'est tout à fait suffisant pour détecter les échecs, peu importe exactement * où * il a échoué - un port de travail n'échouera pas, un périphérique mourant pourrait mais le lieu des pannes ne sera pas utile. Cela réduit également le nombre de chaînes traduisibles, ce qui réduit le fardeau de vos traducteurs. –

Répondre

1

Ce cas de test minimal fonctionne pour un Arduino sur Windows et OS X, en utilisant le dernier Qt 5.5.

Ce type de minimisation est ce qui appartient à votre question. Plusieurs fichiers (et un .ui) manquant ne sont pas nécessaires pour démontrer de telles défaillances simples.

// https://github.com/KubaO/stackoverflown/tree/master/questions/miniserial-36431493 
#include <QtWidgets> 
#include <QtSerialPort> 

int main(int argc, char ** argv) { 
    QApplication app(argc, argv); 
    QWidget w; 
    QFormLayout layout(&w); 
    QPushButton ping("Send"); 
    QTextBrowser output; 
    layout.addRow(&ping); 
    layout.addRow(&output); 
    w.show(); 

    QSerialPort port("COM6"); 
    port.setBaudRate(QSerialPort::Baud9600); // these are guaranteed to return true 
    port.setDataBits(QSerialPort::Data8); 
    port.setParity(QSerialPort::NoParity); 
    port.setStopBits(QSerialPort::OneStop); 
    port.setFlowControl(QSerialPort::NoFlowControl); 
    if (!port.open(QIODevice::ReadWrite)) 
     output.append("! Can't open the port :(<br/>"); 

    QObject::connect(&ping, &QPushButton::clicked, &port, [&]{ 
     if (port.isOpen()) { 
     port.write("1"); 
     output.append("> 1<br/>"); 
     } else 
     output.append("! Write failed :(<br/>"); 
    }); 
    QObject::connect(&port, &QIODevice::readyRead, &output, [&]{ 
     auto data = port.readAll(); 
     output.append(QStringLiteral("< %1<br/>") 
        .arg(QString::fromLatin1(data).toHtmlEscaped())); 
    }); 

    return app.exec(); 
} 
+0

Merci pour la réponse! Demain matin je vais le tester et je vais essayer de comprendre ce que j'ai fait de mal! – Jiloc

+0

Comme vous l'avez dit dans les commentaires sur ma question, j'ai eu des problèmes avec la construction. Je suis revenu à qtCreator et tout a fonctionné parfaitement, merci pour votre aide! – Jiloc