重新连接USB后Arduino收不到数据

Arduino doesn't receive data after reconnecting to USB

因此,我构建了一个基本的 QT GUI,我想在其中通过 USB 与 Arduino Nano 建立通信。我通过 GUI 发送一个数字,Arduino 接收该数字并对其进行处理。

当我将代码上传到 Arduino 并随后打开 GUI 并开始该过程时,通信工作正常。但是,当我断开 Arduino 与 USB 的连接(或重新启动我的 PC - 我都尝试过)并重新连接它以将其与 GUI 一起使用时,Arduino 的行为就像它没有收到任何东西一样。

更具体地说,在第一种情况下 Serial.available() returns "1" 因为它正确接收了数字,但在后一种情况下它 returns "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 保持低电平,因为它永远不会进入 "if".

这是我使用的代码:

int incomingByte = 0;   

void setup() {
    Serial.begin(9600); 
}

void loop() {
    if (Serial.available() > 0) {
        digitalWrite(13, HIGH);
        incomingByte = Serial.read();
    }
}

~~~~~~~~~~~~~~~~~~~~~~编辑3~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~

所以我有以下3种情况:

使用场景A:

  1. 上传代码
  2. 运行 界面
  3. 发送数据 - 正确接收
  4. 断开并重新连接
  5. 运行 GUI
  6. 发送数据 - RX 闪烁但 Serial.available returns 0

使用场景B:

  1. 上传代码
  2. 运行布雷斯
  3. 发送数据 - 正确接收
  4. 断开并重新连接
  5. 运行又叫一声
  6. 发送数据 - 正确接收

使用场景C(最有趣):

  1. 上传代码
  2. 运行 界面
  3. 发送数据 - 正确接收
  4. 断开并重新连接
  5. 运行这次叫声
  6. 发送数据 - 正确接收
  7. 运行 Brays
  8. 之后的 GUI
  9. 发送数据 - 正确接收

我也把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"发送字符后,LED闪烁了几毫秒(可能表示一些错误??),然后在 1 秒延迟后,Rx 闪烁指示接收到数据并且 LED 保持低电平,因为 Serial.available 保持为 0.

因此,我接下来尝试的是一次删除一行代码,以查看导致问题的原因。我最终得到了 完全空白的 Arduino 代码 ,只有空的设置和循环方法,以及以下 QT GUI 代码:

void myThread::run()
{
    QSerialPort *serial1 = new QSerialPort();
    serial1->setPortName("COM5");
    serial1->open(QIODevice::WriteOnly);
    serial1->close();
}

总而言之,现在发生的事情是:

  1. 上传代码到Arduino
  2. 运行 界面
  3. 发送数据
  4. 没有任何反应(正常行为)
  5. 断开 Arduino 并重新连接到 USB
  6. 运行 界面
  7. 发送数据
  8. Arduino LED 瞬间闪烁一次(可能表示某种错误)

根据我的经验,问题不在于 Arduino 中的代码。这是因为串口在重新插入时得到了不同的名称。

例如在Linux中,最初的端口是/dev/ARD0,但是当它断开连接并重新插入并连接到ARD0时,新插件被命名为/dev/ARD1。 (在 Windows 中,可能是 COM17 然后是 COM18。)

我知道让它成为原始端口名称的唯一方法是在再次插入之前关闭所有连接到它的东西:关闭 Arduino IDE,关闭所有打开端口的程序,等等

如果您将此示例用于 Arduino 串行文档,您会收到发送的字符吗?

int incomingByte = 0;   // for incoming serial data

void setup() {
    Serial.begin(9600); // opens serial port, sets data rate to 9600 bps
}

void loop() {

    // send data only when you receive data:
    if (Serial.available() > 0) {
        // read the incoming byte:
        incomingByte = Serial.read();

        // say what you got:
        Serial.print("I received: ");
        Serial.println(incomingByte, DEC);
    }
}

在这里抓住救命稻草,延迟一秒替换我下面的评论。在 iPhone 上编辑时格式有点混乱,但我相信你能看出我的意图。

编辑:另外,我认为您不应该在循环内执行 serial->close。我也会尝试重复发送一个字符,直到我们成功为止。

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("x");
            delay 1 second here
    serial->flush();
            delay 1 second here
}

serial->close();
            delay 1 second here
delete serial;
}

好的,经过几个小时的调试,我找到了导致问题的原因。

其根源在于,在重新连接 Arduino 之后,每次我在 QT 中调用 serial.open 时,Arduino 都会进行重置(由 LED 闪烁表示),并且在引导加载程序之后阶段是运行代码,主程序已经通过了serial.writeQT命令,还没有收到数据。

所以,我解决这个问题的方法是在serial.open之后添加一个Sleep(uint(2000));,让Arduino完成启动,然后开始发送数据。

感谢大家的帮助和及时的答复!