【问题标题】:Communication between Raspberry pi (QT C++) and Arduino (Arduino IDE)Raspberry pi (QT C++) 和 Arduino (Arduino IDE) 之间的通信
【发布时间】:2017-04-22 06:02:59
【问题描述】:

一个多星期以来,我一直在尝试通过串行端口从树莓派 (QT C++) 与 Arduino (Arduino IDE c++) 进行通信,但一直失败。

我在谷歌上进行了一些搜索,阅读了示例......但我仍然没有成功。好的,所以基本的事情是我需要不断地通信从 Raspberry pi 到 Arduino 的串行端口发送命令。我试图让代码尽可能简单。

最初,我将“J”字符从树莓派 (QT C++) 发送到 Arduino (Arduino IDE c++) 并等待该 J,以使 Arduino 上的 LED 闪烁。但它不起作用..即使我没有得到任何用于连接&通信&发送数据树莓派 (QT C++) 到 Arduino (Arduino IDE c++) 的样本。我不知道到底是什么问题。请帮我解决问题。

在监视器中,9600 波特率

我已经附上了我在两边都试过的程序。

main.cpp

#include <iostream>
#include <QIODevice>

#include <QtSerialPort/QSerialPort>
#include <QtSerialPort/QSerialPortInfo>
#include <QString>

using namespace std;

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Dialog w;
    w.show();

    QSerialPort serialPort;
    serialPort.setBaudRate(QSerialPort::Baud9600);

    QSerialPortInfo info("ttyUSB0");
        qDebug() << "Name        : "     << info.portName();
        qDebug() << "Description : "     << info.description();
        qDebug() << "Busy:"              << info.isBusy();

        QSerialPort serial;
        serial.setPortName("ttyUSB0");

        serial.open(QIODevice::ReadWrite);
        serial.setBaudRate(QSerialPort::Baud9600);
        serial.setDataBits(QSerialPort::Data8);
        serial.setParity(QSerialPort::NoParity);
        serial.setStopBits(QSerialPort::OneStop);
        serial.setFlowControl(QSerialPort::NoFlowControl);

        serial.open(QSerialPort::ReadWrite);
        cout<<"Readable    :"<<serial.isReadable()<<endl;
        cout<<"Writable    :"<<serial.isWritable()<<endl<<endl;

        if (serial.isOpen() && serial.isWritable())
        {
            qDebug() << "Is open : " << serial.isOpen() << endl;
            qDebug() << "Is writable : " << serial.isWritable() << endl;

            qDebug() << "Ready..." << endl;
            serial.write("J");

            QByteArray ba("J\n");

            serial.write(ba);
            {
                QByteArray ba("J");
                serial.write(ba);
                serial.flush();
                qDebug() << "data has been send" << endl;
                serial.close();
            }
            if (serial.bytesToWrite() > 0)
            {
                serial.flush();
                if(serial.waitForBytesWritten(1000))
                {
                    qDebug() << "data has been send" << endl;
                }
            }
            if(serial.flush())
                {
                    qDebug() << "ok" << endl;
                }
                qDebug() <<"value sent "<< endl;
                serial.close();
        }
        else
        {
            qDebug() << "An error occured" << endl;
        }
    return a.exec();
}

Arduino 代码:

int led = 13, avlb = 0;

void setup() 
{ 
Serial.begin(9600); 
pinMode(led, OUTPUT); 
Serial.println("started");
}

void loop() 
{ 

 if (Serial.available() > 0)
{
    Serial.println("available");
    Serial.println(Serial.available());  
    delay(2000); 
    digitalWrite(led, HIGH);  
    delay(5000);           

  if(Serial.read() == 'J')
 {
   Serial.println("read");
   Serial.println(Serial.read());
   delay(2000);
   digitalWrite(led, LOW);   
   delay(1000);  
 }  
}

else
 {
   Serial.println("not available");
   delay(1000);
 }
}

输出显示:

Raspberry qt creator ide o/p:

Name        :  "ttyUSB0"
Description :  "FT232R USB UART"
Busy: false

Readable    :1
Writable    :1

Is open :  true 

Is writable :  true 

Ready... 

data has been send 

bool QSerialPort::flush(): device not open
value sent

Arduino Ide 输出显示:

started

not available
not available
not available
not available
not available
not available
not available
not available
not available

【问题讨论】:

    标签: c++ serial-port qt-creator raspberry-pi3 arduino-ide


    【解决方案1】:

    我建议您阅读 Qt 事件系统的工作原理。所有 Qt IODevice 派生类都是异步工作的。您需要使用 QApplication 来托管其对象系统。之后,您需要更改代码,使其不会阻塞 QSerialPort 的 io 线程。

    我通常使用readyRead 信号或者我使用waitForBytesWritten 和waitForReadReady 组合。你应该看看QtSerialPort examples。根据您的应用需求,您会发现有几种可能的实现方式。

    你可以试试这个,效果很好。

    #include <QCoreApplication>
    #include <iostream>
    #include <QSerialPort>
    #include <QDebug>
    #include <Windows.h>
    #include <QElapsedTimer>
    
    using namespace std;
    QSerialPort serial;
    QElapsedTimer timer;
    
    int main(int argc, char *argv[])
    {
        QCoreApplication a(argc, argv);
        serial.setPortName("ttyUSB0");
        serial.open(QIODevice::ReadWrite);
    
           serial.setBaudRate(QSerialPort::Baud9600);
           serial.setDataBits(QSerialPort::Data8);
           serial.setParity(QSerialPort::NoParity);
           serial.setStopBits(QSerialPort::OneStop);
           serial.setFlowControl(QSerialPort::NoFlowControl);
    
           while(!serial.isOpen()) serial.open(QIODevice::ReadWrite);
    
           if (serial.isOpen() && serial.isWritable())
           {
           qDebug() << "Serial is open";
    
           QByteArray output;
           QByteArray input;
    
           while(true)
           {
             output = "a";
             serial.write(output);
            serial.flush();
            timer.start();
           // Sleep(80);
            qDebug() << timer.elapsed();
    
             serial.waitForBytesWritten(100);
             serial.waitForReadyRead(100);
    
            if(serial.bytesAvailable()>=18)
             input = serial.read(18);
            qDebug()<<input;
             }
           }
        return a.exec();
    }
    

    【讨论】:

    • 无论他们在他们的网站上提供的文件是什么,在我看来他们都相当复杂且解释不清。
    • IMO 2 选项: QSerialPort::readData() - 让您的程序读取给定长度的数据 doc.qt.io/qt-5/qserialport.html#readData QSerialPort::bytesAvailable() - 检查是否有预期的可用字节数 doc.qt.io/qt-5/qserialport.html#bytesAvailable
    • 如何修改我的代码以获得相同的输出?
    • 您已经打开了串口,如果由于任何原因无法打开,您将陷入该循环。在第一次打开时进行检查并采取相应的行动。然后在您的 GUI 中添加一个“再试一次”按钮。会更干净。
    【解决方案2】:

    您的问题的答案在以下代码中:

    QByteArray ba("J");
    serial.write(ba);
    serial.flush();
    qDebug() << "data has been send" << endl;
    serial.close();
    

    serial.flush () 后,立即关闭端口。需要等到数据真正发送完毕。例如,使用bool QSerialPort :: waitForBytesWritten (int msecs)

    【讨论】:

    • 我可以添加延迟吗?
    • 是的。你需要延迟。例如,使用bool QSerialPort :: waitForBytesWritten (int msecs)
    • 好的。我会先试试这个。如果我想阅读我必须做的更改?例如,我已将一个传感器与 Arduino 连接,我想将该读数发送到 raspberry,现在我想将这些读数用于决策。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-27
    • 1970-01-01
    相关资源
    最近更新 更多