【发布时间】:2020-05-08 19:07:26
【问题描述】:
我遇到了一个非常简单的问题。
我正在尝试制作一个 Qt GUI 应用程序来从 GUI 控制我的 Arduino(而不是从 Arduino IDE 的串行监视器控制它)。我能够使用 QSerialPort write() 方法成功写入 Arduino,但我无法从 Arduino 读取任何内容。我可以从串行端口读取的唯一方法是在我的 Qt 代码中的 waitForBytesWritten() 中的 write() 函数之后使用 waitForReadyRead(5000) 。但是我必须使用5000毫秒的时间间隔才能成功读取,这很耗时。如果在我的 Qt GUI 应用程序中有更快的读取 Arduino 串口的方法,请告诉我。
我正在发布我的 Qt 和 Arduino 代码。
Qt 代码
#include "GuiApp.h"
#include <QSerialPort>
#include <QSerialPortInfo>
#include <QDebug>
#include <QMessageBox>
GuiApp::GuiApp(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
ui.lcdNumber_temp->display("--------");
arduino = new QSerialPort(this);
bool arduino_available = false;
QString arduino_portName;
foreach(const QSerialPortInfo &serialPortInfo, QSerialPortInfo::availablePorts()) {
if (serialPortInfo.hasVendorIdentifier() && serialPortInfo.hasProductIdentifier()) {
if ((serialPortInfo.productIdentifier() == arduino_pid) && (serialPortInfo.vendorIdentifier() == arduino_vid)) {
arduino_available = true;
arduino_portName = serialPortInfo.portName();
}
}
}
//qDebug() << "Number of ports" << QSerialPortInfo::availablePorts().length() << "\n";
//foreach(const QSerialPortInfo &serialPortInfo, QSerialPortInfo::availablePorts()) {
// qDebug() << "Description" << serialPortInfo.description() << "\n";
// qDebug() << "Has Vendor Id?" << serialPortInfo.hasVendorIdentifier() << "\n";
// qDebug() << "Vendor Id" << serialPortInfo.vendorIdentifier() << "\n";
// qDebug() << "Has Product Id?" << serialPortInfo.hasProductIdentifier() << "\n";
// qDebug() << "Product Id" << serialPortInfo.productIdentifier() << "\n";
//}
if (arduino_available) {
arduino->setPortName(arduino_portName);
arduino->setBaudRate(QSerialPort::Baud9600);
arduino->setDataBits(QSerialPort::Data8);
arduino->setParity(QSerialPort::NoParity);
arduino->setStopBits(QSerialPort::OneStop);
arduino->setFlowControl(QSerialPort::NoFlowControl);
arduino->open(QIODevice::ReadWrite);
if (!arduino->isOpen()) {
qDebug() << "Arduino Not Opening";
}
QObject::connect(ui.pushButton_connect,SIGNAL(clicked()),this,SLOT(button_pressed()));
QObject::connect(arduino,SIGNAL(readyRead()),this,SLOT(readSerial()));
//serial.write("OK ---");
} else {
qDebug() << "Couldn't find correct arduino port.\n";
QMessageBox::information(this,"Serial Port Error","Couldn't open serial port to arduino.");
}
}
GuiApp::~GuiApp()
{
//serial.close();
if (arduino->isOpen()) {
qDebug() << "Arduino Closed!\n";
arduino->close();
}
}
void GuiApp::button_pressed() {
if (arduino->isWritable()) {
arduino->write("255");
arduino->waitForBytesWritten(5000);
//QByteArray s = arduino->readAll();
//arduino->waitForReadyRead(1000);
//std::string str = s.toStdString();
//qDebug("My String %s", str);
}
else {
QMessageBox::information(this, "Serial Port Error", "Couldn't write to Serial port.");
}
}
void GuiApp::readSerial() {
qDebug() << "Serial Port Works!!\n";
QMessageBox::information(this, "Serial Port Works", "Opened serial port to arduino.");
QByteArray serialData = arduino->readAll();
QString temp = QString::fromStdString(serialData.toStdString());
qDebug() << temp;
}
Arduino 代码
#include <SPI.h>
#include <Controllino.h>
int led = CONTROLLINO_D1;
int led2 = CONTROLLINO_D2;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
pinMode(led,OUTPUT);
pinMode(led2,OUTPUT);
digitalWrite(led,LOW);
digitalWrite(led2,LOW);
}
void loop() {
// put your main code here, to run repeatedly:
if(Serial.available()) {
const int val = Serial.parseInt();
if(val == 255) {
digitalWrite(led,HIGH);
delay(1000);
Serial.write("Ok");
} else {
digitalWrite(led2,HIGH);
Serial.write("Not Ok");
}
}
}
【问题讨论】:
-
您是否尝试过使用QSerialPort::onReadyRead()?创建 GuiApp 类的成员槽函数并将串行端口对象的信号连接到它。
-
@markus-nm 我已经有一个插槽 GuiApp::readSerial()
-
我的错,没看到。您是否有机会使用 Qt 5.13.1?除非您显式调用 waitForReadyRead(),否则存在一个关于不会触发 readyRead() 信号的错误。在这种情况下,您可以重复调用 waitForReadyRead(0) 来解决此问题,或者升级到 Qt 5.14。
-
@markus-nm 感谢您的回复。我的 Qt 版本是 5.12.5。在写入串行端口后,我实际上做了同样的事情来使我的代码工作。但我想让“读取”更快,我也想先从串口读取而不写入串口,就像 TCP CLient 服务器系统考虑 Arduino 作为服务器一样。
标签: c++ qt interface arduino serial-port