与Arduino通信的QSerial错误 [英] QSerial error communicating with Arduino

查看:80
本文介绍了与Arduino通信的QSerial错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我根据本指南,编写了一个简单的程序来使用Qt(从Visual Studio 2013的源代码构建的5.5版))与Arduino通信.

I wrote a simple program to use Qt (version 5.5 built from source for Visual Studio 2013 following this guide) to comunicate with Arduino.

这是一个简单的固件,可以从序列中读取,并在10秒钟后将"1"回打印:

Here is a simple firmware which read from the serial and after 10 seconds prints "1" back:

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');
    }
}

这里是Qt程序,当我按下开始按钮并连续收听消息以进行读取时,该程序会串行发送"1":

Here is the Qt program which send "1" on serial when I press the start button and keeps listening for messages to read:

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

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

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

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

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);
}

问题出现在writeOnSerial方法(SerialHandler.cpp)中.调用serial.write()会引发此错误:

the problem appears in writeOnSerial method (SerialHandler.cpp). The call to serial.write() fires this error:

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

"1"以串行方式写入并由arduino读取,但是计算机在10秒后再也没有收到任何东西,readyRead()信号永远不会触发!

the "1" is written on serial and read by the arduino, but the computer never receives anything back after 10 seconds, the readyRead() signal is never fired!

我在此帖子中看到了相同的错误,但就我而言,exec循环在那里!

I saw the same error in this post, but in my case the exec loop is there!

有什么建议吗?

推荐答案

这个最小的测试用例适用于Windows和OS X上的Arduino,并使用最新的Qt 5.5.

This minimal test case works for me on an Arduino on both Windows and OS X, using latest Qt 5.5.

这种最小化就是您所要解决的问题.无需多个文件(以及缺少的.ui)即可证明这种简单的失败.

This kind of minimization is what belongs in your question. Multiple files (and a missing .ui) aren't necessary to demonstrate such simple failures.

// 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();
}

这篇关于与Arduino通信的QSerial错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆