重新连接到USB

时间:2016-03-20 16:32:53

标签: c++ qt arduino serial-port

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

当我将代码上传到Arduino并且之后打开GUI并开始进程时,通信正常。但是,当我断开Arduino与USB的连接(或重新启动我的电脑 - 我已经尝试过两者)并重新连接它以使用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时。

~~~~~~~~~~~~~~~~~~~~~~~~~~ EDIT ~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~

重新连接后,COM端口保持不变,当我通过GUI发送数据时,Arduino Rx LED正常闪烁。

~~~~~~~~~~~~~~~~~~~~~~~~~编辑2 ~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~

好的,所以,我尝试使用Arduino Serial文档中的代码,问题仍然存在。当我上传代码时,Arduino正确接收字符并打开LED,但是一旦我将其断开然后将其连接回来,它什么都不做,LED保持低电平,因为它永远不会进入&#34;如果&#34;。< / p>

这是我使用的代码:

int incomingByte = 0;   

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

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

所以我有以下三种情况:

使用场景A:

  1. 上传代码
  2. 运行GUI
  3. 发送数据 - 收到正确的
  4. 断开并重新连接
  5. 再次运行GUI
  6. 发送数据 - RX闪烁,但Serial.available返回0
  7. 使用场景B:

    1. 上传代码
    2. Run Brays
    3. 发送数据 - 收到正确的
    4. 断开并重新连接
    5. 再次运行Brays
    6. 发送数据 - 收到正确的
    7. 使用场景C(最有趣的):

      1. 上传代码
      2. 运行GUI
      3. 发送数据 - 收到正确的
      4. 断开并重新连接
      5. 这次运行Brays
      6. 发送数据 - 收到正确的
      7. 在Brays
      8. 之后再次运行GUI
      9. 发送数据 - 收到正确的
      10. 我也让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变为高电平,如代码所示。然而,在重新连接后,问题仍然存在,但我注意到,这次,在点击&#34;发送&#34;发送字符, 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. 运行GUI
        3. 发送数据
        4. 没有任何事情发生(正常行为)
        5. 断开并重新连接Arduino至USB
        6. 运行GUI
        7. 发送数据
        8. Arduino LED暂时闪烁一次(可能表示某种错误)

4 个答案:

答案 0 :(得分:1)

好的,经过数小时的调试后,我发现了导致问题的原因。

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

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

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

答案 1 :(得分:0)

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

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

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

答案 2 :(得分:0)

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

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

答案 3 :(得分:0)

在这里抓住稻草,在一秒钟之后将我的评论替换下来。在iPhone上编辑的格式有点乱,但我相信你可以看到我的意图。

编辑:另外,我认为你不应该在你的循环内进行serial-&gt;关闭。我也会尝试重复发送一个字符,直到我们有效。

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