所以,我已经构建了一个基本的QT GUI,我希望通过USB与Arduino Nano Build 通信 . 我通过GUI发送一个号码,Arduino接收号码并处理它 .
当我将代码上传到Arduino时,通信工作正常,然后打开GUI并开始进程 . 但是,当我从USB断开Arduino(或重新启动我的PC - 我已经尝试过两者)并重新连接它以使用GUI时,Arduino的行为就像没有收到任何东西 .
更具体地说,在第一种情况下 Serial.available()
返回"1",因为它正确地接收了数字,但在后一种情况下它返回"0",所以它什么都不做 .
我使代码变得简单,我可以尝试追踪问题,问题仍在继续 .
所以这是主要的QT GUI代码:
depth_ = insertDepthEdit->text().toInt(); // user input from GUI
myThread *mThread;
mThread = new myThread(this, depth_);
connect(mThread, SIGNAL(valueRead(QString)), this, SLOT(onTextChange(QString)));
//valueRead is the signal emitted from Arduino
//onTextChange the function that processes the received string
mThread->start();
mThread->wait(100);
mThread->quit();
Arduino线程代码(也是QT):
void myThread::run() {
QSerialPort serial;
serial.setPortName("COM3");
serial.setBaudRate(QSerialPort::Baud9600);
serial.setDataBits(QSerialPort::Data8);
serial.setParity(QSerialPort::NoParity);
serial.setStopBits(QSerialPort::OneStop);
serial.setFlowControl(QSerialPort::NoFlowControl);
serial.open(QIODevice::ReadWrite);
if (serial.isOpen() && serial.isWritable()) {
qDebug() << "Ready to write..." << endl;
QByteArray ba(QString::number(depth_).toStdString().c_str());
qDebug() << ba << endl;
serial.write(ba);
if (serial.bytesToWrite() > 0) {
serial.flush();
if (serial.waitForBytesWritten(1000)) {
qDebug() << "data has been sent" << endl;
}
}
if (serial.flush()) {
qDebug() << "ok" << endl;
}
}
else {
qDebug() << "Error";
}
if (serial.isOpen() && serial.isReadable()) {
qDebug() << "Ready to read..." <<endl;
while (serial.waitForReadyRead(5000)) {
QByteArray inByteArray = serial.readLine();
input_ = QString(inByteArray);
qDebug() << input_;
qDebug() << "ok" << endl;
emit valueRead(input_);
}
}
serial.close();
}
最后是Arduino代码:
int c = 0;
const int ledPin = 13;
void setup() {
Serial.begin(9600);
}
void loop() {
Serial.print(Serial.available());
while (Serial.available() > 0) {
digitalWrite(ledPin, HIGH);
delay(5);
c = Serial.read() - '0';
Serial.flush();
}
delay(1000);
digitalWrite(ledPin, LOW);
delay(500);
}
当我将代码上传到Arduino时,无论我关闭GUI并重新启动它,它都能正常运行 . 只有当Arduino断电时才会出现问题,例如:当我断开USB连接或重启PC时 .
~~~~~~~~~~~~~~~~~~~~~~~~~~编辑~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~
重新连接后,COM端口保持不变,当我通过GUI发送数据时,Arduino Rx LED正常闪烁 .
~~~~~~~~~~~~~~~~~~~~~~~~~~编辑2 ~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~
好吧,所以,我尝试使用Arduino Serial文档中的代码,问题仍然存在 . 当我上传代码时,Arduino正确接收字符并打开LED,但是一旦我断开它然后将其连接回来,它什么都不做,LED保持低电平,因为它永远不会进入“如果” .
这是我使用的代码:
int incomingByte = 0;
void setup() {
Serial.begin(9600);
}
void loop() {
if (Serial.available() > 0) {
digitalWrite(13, HIGH);
incomingByte = Serial.read();
}
}
编辑~~~~~~~~~~~ ~~~~~~~~~~~~
所以我有以下三种情况:
使用场景A:
-
上传代码
-
运行GUI
-
发送数据 - 正确接收
-
断开并重新连接
-
再次运行GUI
-
发送数据 - RX闪烁但Serial.available返回0
使用场景B:
-
上传代码
-
运行Brays
-
发送数据 - 正确接收
-
断开并重新连接
-
再次运行Brays
-
发送数据 - 正确接收
使用场景C(最有趣的):
-
上传代码
-
运行GUI
-
发送数据 - 正确接收
-
断开并重新连接
-
这次运行Brays
-
发送数据 - 正确接收
-
在Brays之后再次运行GUI
-
发送数据 - 正确接收
我也使QT GUI代码简单,但问题仍然存在:
void myThread::run()
{
QSerialPort *serial = new QSerialPort();
serial->setPortName("COM3");
serial->setBaudRate(QSerialPort::Baud9600);
serial->setDataBits(QSerialPort::Data8);
serial->open(QIODevice::WriteOnly);
if (serial->isOpen() && serial->isWritable())
{
QByteArray ba(QString::number(depth_).toStdString().c_str());
serial->write(ba);
serial->flush();
serial->close();
}
delete serial;
}
~~~~~~~~~~~~~~~~~~~~~~编辑4 ~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~
经过多方努力和好奇,我意识到问题的根源不是Arduino代码,而是与QT或Windows相关的东西 . 我添加了Jeff推荐的延迟,并注意到每次正常运行时Rx闪烁,LED变为高电平,如代码所示 . 但是,重新连接后,问题仍然存在,但我注意到,这次,在点击"Send"发送字符后立即 the LED blinked for some milliseconds (可能表示有些错误?)然后在1秒延迟后Rx闪烁表示收到数据并且LED保持低电平,因为Serial.available仍为0 .
所以,我接下来尝试的是一次删除一行代码以查看导致问题的原因 . 我最后得到 literally blank Arduino code ,只是空的设置和循环方法,以及以下QT GUI代码:
void myThread::run()
{
QSerialPort *serial1 = new QSerialPort();
serial1->setPortName("COM5");
serial1->open(QIODevice::WriteOnly);
serial1->close();
}
总而言之,现在发生的事情是:
-
将代码上传到Arduino
-
运行GUI
-
发送数据
-
什么都没发生(正常行为)
-
断开连接并将Arduino重新连接到USB
-
运行GUI
-
发送数据
-
Arduino LED暂时闪烁一次(可能表示某种错误)
4 回答
好的,经过几个小时的调试后我发现了导致问题的原因 .
它的根源在于重新连接Arduino之后,每次我在QT中调用serial.open时,Arduino都会进行重置(由LED指示灯闪烁表示),并且在引导加载程序阶段之后运行代码时,主程序已经传递了serial.write QT命令而没有接收到数据 .
所以,我为解决这个问题所做的就是在serial.open之后添加一个
Sleep(uint(2000));
,以便让Arduino完成启动,然后开始发送数据 .谢谢大家的帮助和即时答案!
根据我的经验,问题不在于Arduino中的代码 . 这是因为串口重新插入时,串口会有不同的名称 .
例如在Linux中,最初端口是
/dev/ARD0
,但是当它断开连接并用ARD0上的连接重新插入时,新插件名为/dev/ARD1
. (在Windows中,它可能是COM17
然后COM18
. )我知道使其成为原始端口名称的唯一方法是在再次插入之前关闭连接到它的所有内容:关闭Arduino IDE,关闭所有打开端口的程序,等等 .
如果你在Arduino Serial文档中使用这个例子你收到你发送的字符吗?
在这里 grab 稻草,在一秒钟之后将我的评论替换下来 . 在iPhone上编辑时格式有点乱,但我相信你可以看到我的意图 .
编辑:另外,我认为你不应该在你的循环中执行serial-> close . 我也会尝试重复发送一个字符,直到我们有效 .