【问题标题】:Arduino doesn't receive data after reconnecting to USB重新连接到 USB 后,Arduino 不接收数据
【发布时间】:2016-03-20 16:32:52
【问题描述】:

所以,我已经构建了一个基本的 QT GUI,我想通过 USB 与 Arduino Nano 建立通信。我通过 GUI 发送一个数字,Arduino 接收该数字并处理它。

当我将代码上传到 Arduino 并立即打开 GUI 并开始进程时,通信工作正常。但是,当我将 Arduino 与 USB 断开连接(或重新启动我的 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 串行文档中的代码,但问题仍然存在。当我上传代码时,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 返回 0

使用场景 B:

  1. 上传代码
  2. 跑布雷斯
  3. 发送数据 - 正确接收
  4. 断开并重新连接
  5. 再次运行 Brays
  6. 发送数据 - 正确接收

使用场景C(最有趣的):

  1. 上传代码
  2. 运行图形界面
  3. 发送数据 - 正确接收
  4. 断开并重新连接
  5. 这次跑布雷斯
  6. 发送数据 - 正确接收
  7. 在 Brays 之后再次运行 GUI
  8. 发送数据 - 正确接收

我也把 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 变高,如代码所示。但是,重新连接后,问题仍然存在,但我注意到,这一次,在单击“发送”发送字符后,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 LED 是否闪烁表示正在接收数据?
  • 是的,它正常闪烁,即使在重新连接后也是如此。只有 serial.available() 返回 0。
  • 你从 Arduino 得到什么输出?
  • 对不起,当我说LED闪烁时,我的意思是Rx LED闪烁,当我发送数据时。正确的 LED,连接在数字引脚 13 上的那个,我在上面的代码中定义为“ledpin”不会闪烁,因为它永远不会变成高电平,因为它永远不会进入 while 循环,变量 c 保持为零。关于您建议的答案,我会尝试您发布的代码并尽快发布有关情况的更新。
  • 为什么从“COM3:”变成了“COM5:”?另外,我注意到只有您的第一个示例设置了 Data8、OneStop 和 NoParity。您需要在打开端口时设置所有参数,否则它们可能会停留在最后的设置或随机设置。如果字符的长度或奇偶校验不正确,Arduino 可能会忽略它。

标签: c++ qt arduino serial-port


【解决方案1】:

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

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

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

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

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

    • 我已经检查过了,每次我连接 Arduino 时端口都保持不变,只要 USB 端口相同。在我的代码中,我将端口声明为“COM3”,每次连接 Arduino 时,我都会检查设备管理器并连接到那里。正如我所说,即使我重新启动 PC,问题仍然存在,这意味着所有程序和连接都已关闭。
    【解决方案3】:

    如果您将此示例用于 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);
        }
    }
    

    【讨论】:

    • 请参阅问题的“编辑 2”部分。我在那里总结了结果。
    • 如果您在 Arduino Nano 上临时将 TX1 和 RX0 跳线在一起,您是否会收到您使用 PC 程序发送的字符?如果没有,请尝试使用“Brays”sites.google.com/site/terminalbpp 之类的终端程序来确认端口选择、USB 驱动程序、接线等。
    • 好的,这是一个有趣的线索。我用“Brays”终端尝试了相同的过程,即使在重新连接后它也能正确接收数据。有关主要问题“EDIT 3”的更多信息。
    • serial.open 失败了吗?
    • 我真的不知道这里发生了什么。每当我发送新数据并且 Rx LED 闪烁时,如果 serial.open 之后的 GUI 条件为真,但 Arduino 上的 Serial.available 返回 0。这仅在重新连接后发生,并且仅在我使用 GUI 时发生。 Brays 或 Arduino IDE 串行监视器不会发生这种情况。
    【解决方案4】:

    在这里抓住最后一根稻草,将我的 cmets 替换为一秒以下的延迟。在 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;
    }
    

    【讨论】:

    • 我尝试了您推荐的所有方法,发现问题的根源在其他地方,但我仍然不知道如何解决它。请参阅 EDIT 4,非常感谢您的帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多