serial Communication using Threading
-
@Christian-Ehrlicher I have done a sample threading example creating 2 separate classes,called the thread in main class. But, it is not using mainWindow.cpp members and functions.
But,here,in this case I want to access the port which is in use by mainWindow.cpp..
There's where I find the bottle neck
Hi,
As is usual with serial ports, do you have a proper protocol in place to know when you have received a full frame of your data ? Size is no such protocol, time as well.
The proper way do handle data is to cumulate what you read until you have a frame and then process it.
Don't involve threads in there until it is proven by a real benchmark that you need it. As my fellow already wrote, Qt is asynchronous and does not need threading for most tasks such as serial port handling.
-
Hi,
As is usual with serial ports, do you have a proper protocol in place to know when you have received a full frame of your data ? Size is no such protocol, time as well.
The proper way do handle data is to cumulate what you read until you have a frame and then process it.
Don't involve threads in there until it is proven by a real benchmark that you need it. As my fellow already wrote, Qt is asynchronous and does not need threading for most tasks such as serial port handling.
@SGaist Yes.. It's the universal Mavlink message format. By implementing the above mentioned method. It is correctly sending and receiving the data. This is different from other format of receiving data. We could only have the required data based upon the the reading of the pre determined size as it is sending continously and we dont know when will that magic number 253..it could appear from anywhere but after the pack of data.That's why it is reading the stream based upon the size
-
@JonB When using ready read() signal..it throws the error like this:
Port opened
50.66 20.77 17.89
-4.21704e+37 9.11138e-41 1.95399e-13
-4.21704e+37 9.11138e-41 1.56319e-13
50.66 20.77 17.89
-4.21704e+37 -1.99953e+18 3.76588e-13That's Why i choose timer for receiving data
@Vijaykarthikeyan said in serial Communication using Threading:
@JonB When using ready read() signal..it throws the error like this:
readyRead()
will not throw an error or be in an error case. Your code will be incorrect. I explained what you need to do for correct code for asynchronous serial port reading.Anyway, we cannot convince you of this. If you are determined to use threading then go ahead.
-
@Vijaykarthikeyan said in serial Communication using Threading:
@JonB When using ready read() signal..it throws the error like this:
readyRead()
will not throw an error or be in an error case. Your code will be incorrect. I explained what you need to do for correct code for asynchronous serial port reading.Anyway, we cannot convince you of this. If you are determined to use threading then go ahead.
@JonB No..I'm with the side of Qt community.I seek the community for a small doubt?that's all. If you clarify me or telling me the solution, Ill gladly accept it
-
The proper way do handle data is to cumulate what you read until you have a frame and then process it.
plus whatsapp -
The proper way do handle data is to cumulate what you read until you have a frame and then process it.
plus whatsapp@vrooktreat yes..That's why I have read a struct size of data
-
@vrooktreat yes..That's why I have read a struct size of data
@Vijaykarthikeyan
No, you do not accumulate the data received as you should. I have previously said that you just assumereceivedData = serial->read(sizeof(MyStruct)-1);
will work, you don't bother checking and you don't care. And it assumesread()
will always immediately return the rest of the "packet" after the initial byte of 253 arrives, which is just not what Qt/serial port guarantees. @vrooktreat is saying the same.I am not saying that correcting that will necessarily resolve whatever your issue is (though it likely will for whatever your implementation of
readyRead()
slot was which went wrong), but it's not correct/makes an unnecessary assumption. -
@Vijaykarthikeyan
No, you do not accumulate the data received as you should. I have previously said that you just assumereceivedData = serial->read(sizeof(MyStruct)-1);
will work, you don't bother checking and you don't care. And it assumesread()
will always immediately return the rest of the "packet" after the initial byte of 253 arrives, which is just not what Qt/serial port guarantees. @vrooktreat is saying the same.I am not saying that correcting that will necessarily resolve whatever your issue is (though it likely will for whatever your implementation of
readyRead()
slot was which went wrong), but it's not correct/makes an unnecessary assumption.@JonB Ok. I agree with you. I'm doing the wrong way. But,replacing timer with readyRead() signal throws the garbage..this is my 1st issue.If my code implementation is wrong..please correct me.
My aim is to send mavlink like struct data from one device to my device.For that,the 1st byte should be the magic number(in this case, I have used 253(0xFD in hexadecimal)).If and only if matches, it reads through the remaining bytes which is the size of my struct. We can't send/receive struct data type through serial port.That's Why Im using QByteArray.
So,as far as your suggestion, How to cumulate the data? I know this issue is out of text thing which I have asked . Im ready to receive your coorrections
-
@JonB Ok. I agree with you. I'm doing the wrong way. But,replacing timer with readyRead() signal throws the garbage..this is my 1st issue.If my code implementation is wrong..please correct me.
My aim is to send mavlink like struct data from one device to my device.For that,the 1st byte should be the magic number(in this case, I have used 253(0xFD in hexadecimal)).If and only if matches, it reads through the remaining bytes which is the size of my struct. We can't send/receive struct data type through serial port.That's Why Im using QByteArray.
So,as far as your suggestion, How to cumulate the data? I know this issue is out of text thing which I have asked . Im ready to receive your coorrections
@Vijaykarthikeyan said in serial Communication using Threading:
But,replacing timer with readyRead() signal throws the garbage
What does this mean? How does your code using readyRead() look like now? Do you accumulate the data?
You need to accumulate data you get every time readyRead() is emitted until you get a whole frame of data. Just like @SGaist and @JonB suggested. -
@JonB When using ready read() signal..it throws the error like this:
Port opened
50.66 20.77 17.89
-4.21704e+37 9.11138e-41 1.95399e-13
-4.21704e+37 9.11138e-41 1.56319e-13
50.66 20.77 17.89
-4.21704e+37 -1.99953e+18 3.76588e-13That's Why i choose timer for receiving data
@Vijaykarthikeyan said in serial Communication using Threading:
@jsulm When using ready read() signal..it throws the error like this:
Port opened
50.66 20.77 17.89
-4.21704e+37 9.11138e-41 1.95399e-13
-4.21704e+37 9.11138e-41 1.56319e-13
50.66 20.77 17.89
-4.21704e+37 -1.99953e+18 3.76588e-13That's Why i choose timer for receiving data
Already said that corrections are welcomed.. thank you
-
@Vijaykarthikeyan said in serial Communication using Threading:
@jsulm When using ready read() signal..it throws the error like this:
Port opened
50.66 20.77 17.89
-4.21704e+37 9.11138e-41 1.95399e-13
-4.21704e+37 9.11138e-41 1.56319e-13
50.66 20.77 17.89
-4.21704e+37 -1.99953e+18 3.76588e-13That's Why i choose timer for receiving data
Already said that corrections are welcomed.. thank you
@Vijaykarthikeyan said in serial Communication using Threading:
Already said that corrections are welcomed
Corrections? Do you expect somebody to write correct code for you?
You got the suggestion to use readyRead(), accumulate the data and parse it according to the protocol - did you do that? You do not even answer questions... -
@Vijaykarthikeyan said in serial Communication using Threading:
Already said that corrections are welcomed
Corrections? Do you expect somebody to write correct code for you?
You got the suggestion to use readyRead(), accumulate the data and parse it according to the protocol - did you do that? You do not even answer questions...@jsulm on using readyRead() it throws the garbage values in the middle of incoming serial port values,,that's what im mentioning in every thread.
I didn't tell anyone to write the code for me.. and why I should? I have implemented the method without seeing into any examples and it worked for me? My Question is now gone nowhere. The topic is changed? The actual defintion of correction is not writing the code behalf of me.
-
@jsulm on using readyRead() it throws the garbage values in the middle of incoming serial port values,,that's what im mentioning in every thread.
I didn't tell anyone to write the code for me.. and why I should? I have implemented the method without seeing into any examples and it worked for me? My Question is now gone nowhere. The topic is changed? The actual defintion of correction is not writing the code behalf of me.
@Vijaykarthikeyan said in serial Communication using Threading:
on using readyRead() it throws the garbage values in the middle of incoming serial port values
It was already asked before: show your current implementation. How else should anybody know why it does not work? We do not know whether you're accumulating the data correctly and we do not know whether you're parsing accumulated data correctly.
-
@Vijaykarthikeyan said in serial Communication using Threading:
on using readyRead() it throws the garbage values in the middle of incoming serial port values
It was already asked before: show your current implementation. How else should anybody know why it does not work? We do not know whether you're accumulating the data correctly and we do not know whether you're parsing accumulated data correctly.
@jsulm @Vijaykarthikeyan and wether you're printing it correctly, simply dumping it into qDebug() will probably lead to "chunk" data interpretation.
also
memcpy(&receivedStruct, receivedData2+receivedData.constData(), sizeof(MyStruct));
I somehow doubt you're familiar with packing rules and restrictions. I would suggest ditching
C
and giving your Struct an constructor overload that accepts a QByteArray or a QDataStream implementation or simply overload<<
-
@jsulm @Vijaykarthikeyan and wether you're printing it correctly, simply dumping it into qDebug() will probably lead to "chunk" data interpretation.
also
memcpy(&receivedStruct, receivedData2+receivedData.constData(), sizeof(MyStruct));
I somehow doubt you're familiar with packing rules and restrictions. I would suggest ditching
C
and giving your Struct an constructor overload that accepts a QByteArray or a QDataStream implementation or simply overload<<
@J-Hilk Thank you,Sir you are correct. it has to be correctly packed to avoid those conditions. I Pre-determinely know the Struct size.And that helped me to pack the struct from extracting the stream input based on the size.
-
@Vijaykarthikeyan said in serial Communication using Threading:
on using readyRead() it throws the garbage values in the middle of incoming serial port values
It was already asked before: show your current implementation. How else should anybody know why it does not work? We do not know whether you're accumulating the data correctly and we do not know whether you're parsing accumulated data correctly.
@jsulm ```
#include "mainwindow.h"
#include <QThread>
#include <thread>MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
serial = new QSerialPort(this);
serial->setPortName("COM7");
serial->setBaudRate(QSerialPort::Baud115200);
serial->setDataBits(QSerialPort::Data8);
serial->setParity(QSerialPort::NoParity);
serial->setStopBits(QSerialPort::OneStop);
serial->setFlowControl(QSerialPort::NoFlowControl);if (serial->open(QIODevice::ReadWrite)) { qDebug() << "Port opened"; QThread::msleep(1000); timer = new QTimer(this); connect(timer, &QTimer::timeout, this, &MainWindow::send_data); connect(serial, &QSerialPort::readyRead, this, &MainWindow::read_data); timer->start(500); } else { qDebug() << "Port not opened"; }
}
MainWindow::~MainWindow()
{}
void MainWindow::send_data()
{//QByteArray *sendData = new QByteArray(); MyStruct sendStruct ; AHRS ahrs_data; ahrs_data.yaw =50.66; ahrs_data.pitch=20.77; ahrs_data.roll=17.89; memcpy(sendStruct.payload, &ahrs_data, sizeof(AHRS)); sendStruct.magic=0xFD; sendStruct.length=sizeof(AHRS); sendStruct.sequence=1; sendStruct.sysId=1; sendStruct.compId=2; sendStruct.msgId=1; //sendData->append(reinterpret_cast<const char*>(&sendStruct), sizeof(MyStruct)); serial->write(reinterpret_cast<const char*>(&sendStruct), sizeof(MyStruct)); //delete sendData;
}
void MainWindow::read_data()
{
if(serial->bytesAvailable())
{
QByteArray receivedData,receivedData2;
MyStruct receivedStruct ;
receivedData2 = serial->read(1);if(receivedData2.contains(253)) { receivedData = serial->read(sizeof(MyStruct)-1); memcpy(&receivedStruct, receivedData2+receivedData.constData(), sizeof(MyStruct)); AHRS ahrs_data; memcpy(&ahrs_data,receivedStruct.payload,sizeof(AHRS)); qDebug()<<ahrs_data.yaw<<"\t"<<ahrs_data.pitch<<"\t"<<ahrs_data.roll; } else { } }
}
-
@jsulm ```
#include "mainwindow.h"
#include <QThread>
#include <thread>MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
serial = new QSerialPort(this);
serial->setPortName("COM7");
serial->setBaudRate(QSerialPort::Baud115200);
serial->setDataBits(QSerialPort::Data8);
serial->setParity(QSerialPort::NoParity);
serial->setStopBits(QSerialPort::OneStop);
serial->setFlowControl(QSerialPort::NoFlowControl);if (serial->open(QIODevice::ReadWrite)) { qDebug() << "Port opened"; QThread::msleep(1000); timer = new QTimer(this); connect(timer, &QTimer::timeout, this, &MainWindow::send_data); connect(serial, &QSerialPort::readyRead, this, &MainWindow::read_data); timer->start(500); } else { qDebug() << "Port not opened"; }
}
MainWindow::~MainWindow()
{}
void MainWindow::send_data()
{//QByteArray *sendData = new QByteArray(); MyStruct sendStruct ; AHRS ahrs_data; ahrs_data.yaw =50.66; ahrs_data.pitch=20.77; ahrs_data.roll=17.89; memcpy(sendStruct.payload, &ahrs_data, sizeof(AHRS)); sendStruct.magic=0xFD; sendStruct.length=sizeof(AHRS); sendStruct.sequence=1; sendStruct.sysId=1; sendStruct.compId=2; sendStruct.msgId=1; //sendData->append(reinterpret_cast<const char*>(&sendStruct), sizeof(MyStruct)); serial->write(reinterpret_cast<const char*>(&sendStruct), sizeof(MyStruct)); //delete sendData;
}
void MainWindow::read_data()
{
if(serial->bytesAvailable())
{
QByteArray receivedData,receivedData2;
MyStruct receivedStruct ;
receivedData2 = serial->read(1);if(receivedData2.contains(253)) { receivedData = serial->read(sizeof(MyStruct)-1); memcpy(&receivedStruct, receivedData2+receivedData.constData(), sizeof(MyStruct)); AHRS ahrs_data; memcpy(&ahrs_data,receivedStruct.payload,sizeof(AHRS)); qDebug()<<ahrs_data.yaw<<"\t"<<ahrs_data.pitch<<"\t"<<ahrs_data.roll; } else { } }
}
@Vijaykarthikeyan said in serial Communication using Threading:
receivedData = serial->read(sizeof(MyStruct)-1);
I think the problem here is that it can happen that you will not receive the whole struct at once. That's why it was suggested to accumulate received data until you have enough data to extract the whole struct.
-
@Vijaykarthikeyan said in serial Communication using Threading:
receivedData = serial->read(sizeof(MyStruct)-1);
I think the problem here is that it can happen that you will not receive the whole struct at once. That's why it was suggested to accumulate received data until you have enough data to extract the whole struct.
@jsulm ok..I understand. I'll try. If any issue occurs..I'll post that error. Thank you
-