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?
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). –
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. –