如何通过usb -串口读取传感器



我被迫在Qt中为传感器编写一些代码,以便与现有的Qt代码集成。另外,我已经使用pyserial库测试了用非常简单的Python代码读取的传感器数据,它的工作效果非常好。不幸的是,我不由自主地陷入了Qt框架的复杂泥潭。

硬件:传感器通过USB转串口适配器插入树莓派4的USB端口。

传感器配置为每1秒输出一行RS-232数据,以'r' (CR, ASCII 13)结尾的ASCII字符,而不是'n' (LF, ASCII 10)。

这是我的代码:

#include <QCoreApplication>
#include <QThread>
#include <QtSerialPort/QSerialPort>
#include <QtSerialPort/qserialportinfo.h>
#include <QList>
#include <QString>
#include <stdio.h>
#include <iostream>
#include <QtCore/QDataStream>
static QString sensor = "";
static QList<QSerialPortInfo> portList;
static QSerialPortInfo sensorport;
static QSerialPort s_sensor;
int main(int argc, char** argv)
{
QCoreApplication app(argc, argv);

portList = QSerialPortInfo::availablePorts();
int size = portList.size();
const auto portnames = portList[1];
std::cout << "Number of ports: " << size << "n";
for(int i=0;i<size;i++)
{
std::cout << portList[i].portName().toStdString() << " " << portList[i].description().toStdString() << "n";
if(portList[i].portName().toStdString()=="ttyUSB0"&&portList[i].description().toStdString()=="USB-Serial Controller D")
{
sensor.append(portList[i].portName());
sensorport = portList[i];
}
}
std::cout << sensor.toStdString() << "n";
std::cout << sensorport.manufacturer().toStdString() << "n";
s_sensor.setPort(sensorport);
std::cout << s_sensor.open(QIODevice::ReadOnly) << "n";
std::cout << s_sensor.portName().toStdString() << "n";
std::cout << s_sensor.parity() << "n";
std::cout << s_sensor.baudRate() << "n";
std::cout << s_sensor.dataBits() << "n";
std::cout << s_sensor.stopBits() << "n";
std::cout << s_sensor.isOpen() << "n";
//std::cout << s_sensor.canReadLine() << "n";
//char buf[1024];
//QString buff;
static QByteArray byteArray;
while(s_sensor.isOpen())
{
//QByteArray byteArray;
if(s_sensor.waitForReadyRead())
{
byteArray += s_sensor.readAll();
}
if(QString(byteArray).contains('r'))
{
QString data = QString(byteArray);//.remove("*");
byteArray.clear();
std::cout << "End of linen";
std::cout << data.toStdString() << "n";
}
else
{
//std::cout << "Nonen";
}
//            if(s_sensor.waitForReadyRead() && s_sensor.bytesAvailable()>=18)
//            {
//                //std::string ll = s_sensor.readAll().toStdString();
//                //std::cout << ll << "n";
//                qint64 len = s_sensor.readLine(buf,1024);
//                //QString bb = s_sensor.readAll();
//                std::cout << "Num of bytes: " << len << "n";
//                //std::cout << "Num of bytes: " << sizeof(bb) << "n";
//                std::cout << buf << "n";
//                //std::cout << bb.toStdString() << "n";
//                std::cout << "inner Yes" << "n";
//                //break;
//            }
//buff = buf;
//std::cout << buff.toStdString() << "n";
//std::cout << "outer Yes" << "n";
//qint64 windline = s_sensor.readLine(buf, sizeof(buf));
}
//std::cout << buff.toStdString() << "n";
return app.exec();
}

代码显示了许多连续试验的层,如许多不同的注释行代码所示。

当前的代码不运行。项目构建完成后,"应用程序输出"窗口显示"开始(…)…";直到永远。这是添加这些的结果:

int main(int argc, char** argv)
{
QCoreApplication app(argc, argv)
return app.exec();
}
添加这些行是为了消除一个奇怪的警告"QSocketNotifier:只能用于以qthread开始的线程"。经过广泛的在线搜索,我在SO上找到了一个答案,上面说包含QCoreApplication来创建事件循环。嗯,添加这些行当然可以消除奇怪的警告,但现在我的程序甚至无法启动。

在上述步骤之前,我只有以下内容:

int main()
{
//QCoreApplication app(argc, argv)
//return app.exec();
}

我一直收到奇怪的警告,但我只是一直忽略它。但另一方面,我的程序运行成功。

然而,在我得到任何输出之前,仍然有很长时间的延迟。构建后的典型等待时间大约是2-3分钟!

然而,对于使用pyserial的简单Python代码,我在编译后立即获得输出,并且每行输出都与传感器的1秒输出间隔完美同步。这是理想的工作方式。

我尝试了readLine()readAll()的所有组合。没有指定行结束符的选项。默认值是'n'。我终于找到了两种读取每行数据的方法。您可以在上面看到两种方式的代码。第一种方法是我不断地将新的传入字符添加到byteArray并检查'r'字符。第二种方法是指定一行数据的字节大小并读取它。

我不知道我是否在这里做了一些根本性的错误,导致了执行的长时间延迟。在最初的3分钟延迟之后,一大堆数据被吐出,然后它继续吐出数据,但不会以任何方式以1秒的间隔同步。

我认为您可能遇到的问题是事件循环没有运行。您可以尝试查看阻塞从机或从机的串行端口示例,以获得一些灵感。

另一种方法是尝试将信号连接到串行端口的就绪读取,并使用它来处理响应。

所以不用while循环,用这样的代码:

if (!s_sensor.open(QIODevice::ReadWrite)) {
std::cout << s_sensor.portName().toStdString() << s_sensor.error();
} else {
std::cout << "port is open";
}
QObject::connect(&s_sensor, &QSerialPort::readyRead, [] () {
std::cout << "ready read";
static QByteArray byteArray;
byteArray += s_sensor.readAll();
if(QString(byteArray).contains('r'))
{
QString data = QString(byteArray);//.remove("*");
byteArray.clear();
std::cout << "End of linen";
std::cout << data.toStdString() << "n";
}
else
{
std::cout << "Nonen";
}
});

,并确保下列行也被启用:

QCoreApplication app(argc, argv)
return app.exec();

最新更新