Unsolved Raspbbery Pi 3 Serial Port Performance Problem
-
I tried to add the data to MySQL. But the same thing happens again.Some data do not come as characters, they come as strings.
QT App CPU= %6.0, Memory usage: Regular increase. Avarege %14.5
Mysql CPU=1.0, Memory usage : Regular increase. Avarage % 4I think that an arrangement should be made in software.
Are there any idea that you can suggest me for getting data as more efficient?Thanks.
-
@aktay said in Raspbbery Pi 3 Serial Port Performance Problem:
QT App CPU= %6.0, Memory usage: Regular increase. Avarege %14.5
Mysql CPU=1.0, Memory usage : Regular increase. Avarage % 4That is good. There seem to be enough cpu available.
@aktay said in Raspbbery Pi 3 Serial Port Performance Problem:
I tried to add the data to MySQL. But the same thing happens again.Some data do not come as characters, they come as strings.
Where do you see the problem here?
A string is just a sequence of characters. Very often there are more just one byte/character in the buffer when you got the signal readyRead().
WithQByteArray portData; portData=serial->readAll();
You are reading all bytes at once from the buffer associated with the serial into portData. Then you loop over the different bytes and seem to handle them correctly. It is not clear to me where you have a problem.
-
You may see correct data format below:
"[" "1" "0" "0" "0" "," "2" "1" "," "3" "6" "7" "8" "," "3" "6" "8" //etc.
When I put on extra work (ex. write data to excel, write data to mysql etc.) data format changes.
"0" "]" "0" "6" "9" "*" "\r\n\x00\x00\x00" **"[1000,25,+00"** // Normally I should get this as one charecter. "0" "0" "0" "," "2" "]" "0" "7" "7" "*" "\r" "\n" "[" "1"
Thanks.
-
Please show the code you are using to print this stuff.
-
I am read port after write console. I just using qDebug().
void MainWindow::portRead(){ QByteArray portData; portData=serial->readAll(); qDebug()<<portData; // I am writing the console here. Also I am sending data mysql and qwidget. (Via another Class and another function) if(portData==QChar('[')){ tempList.append(portData); arrayFirst=1; }else if(portData==QChar('*') && arrayFirst!=0){ emit arraySplit(tempList); tempList.clear(); arrayFirst=0; }else if(arrayFirst==1){ tempList.append(portData); } }
-
You are reading all bytes in the buffer with readAll() and you are outputting all those bytes with the next statement. Actually you are always reading a complete string and youare always outputting a complete string. Only the first case the loop trigger, you are probably using, is faster and readAll reads only one byte to the buffer.
Anything you add as processing will ultimately slow down you all other processing. In your case the loop reading the data is slowed by this additional code and suddenly your are reading more than one byte/character into your string. That's it.However, what you need to check is that this code sample has a significant difference
@aktay said in Raspbbery Pi 3 Serial Port Performance Problem:
void MainWindow::portRead(){ QByteArray portData; portData=serial->readAll(); qDebug()<<portData; // I am writing the console here. Also I am sending data mysql and qwidget. (Via another Class and another function) if(portData==QChar('[')){ tempList.append(portData); arrayFirst=1; }else if(portData==QChar('*') && arrayFirst!=0){ emit arraySplit(tempList); tempList.clear(); arrayFirst=0; }else if(arrayFirst==1){ tempList.append(portData); } }
to the initial code sample which is probably causing your confusion:
@aktay said in Raspbbery Pi 3 Serial Port Performance Problem:void MainWindow::portRead(){ QByteArray portData; portData=serial->readAll(); for(int i=0;i<portData.size();i++){ if(portData.at(i)==QChar('[')){ tempList.append(portData.at(i)); arrayFirst=1; }else if(portData.at(i)==QChar('*') && arrayFirst!=0){ emit arraySplit(tempList); tempList.clear(); arrayFirst=0; }else if(arrayFirst==1){ tempList.append(portData.at(i)); } } }
Sometime obviously you have changed the code.
In your initial code you have this construct:
QByteArray portData; portData=serial->readAll(); // you read all bytes into a "string" for(int i=0;i<portData.size();i++){ // you loop over all individual bytes if(portData.at(i)==QChar('[')){ // you access byte by byte and compare with another byte a QChar tempList.append(portData.at(i)); // you are pushing byte by byte into a container
In the code of your last post:
QByteArray portData; portData=serial->readAll(); // you read all bytes into a "string" as above qDebug()<<portData; // I am writing the console here. Also I am sending data mysql and qwidget. (Via another Class and another function) // you print all bytes to qDebug if(portData==QChar('[')){ // you compare all bytes in portData with one byte (usually the compiler should give a warning) tempList.append(portData); // you push all bytes of portData into the container
-
As I said at the beginning, if I use the loop, the data comes out late. For this reason I do not use that code. Because I have to take the data instantaneously without delay.
I am using code below in my program.void MainWindow::portRead(){ QByteArray portData; portData=serial->readAll(); if(portData==QChar('[')){ tempList.append(portData); arrayFirst=1; }else if(portData==QChar('*') && arrayFirst!=0){ emit arraySplit(tempList); tempList.clear(); arrayFirst=0; }else if(arrayFirst==1){ tempList.append(portData);
-
@aktay
Restructuring your code to make more readable:void MainWindow::portRead() { QByteArray portData; portData=serial->readAll(); // this statements whatever is in the buffer of QSerialPort may be 0 to almost infinity // you are compring a string with a character. Will work only when character is casted autmatically to string // since the comparison is for strings you may compare "[100" with "[" which gives false. // Only the when you have read one byte and it happens to be "[" you will have true. if(portData==QChar('[')) { tempList.append(portData); arrayFirst=1; } // The same here as explained for "[" but for "*" else if(portData==QChar('*') && arrayFirst!=0) { emit arraySplit(tempList); tempList.clear(); arrayFirst=0; } else if(arrayFirst==1) { tempList.append(portData);
As already written above readAll reads everything in the buffer into a string. If you do so, you need to loop for checking your chars, but you cannot as you do at the moment. You do not compare as you expect.
BTW there are many other means to scan QByteArray e.g. http://doc.qt.io/qt-5/qbytearray.html#indexOf-1 for locating a character.Most likely you have another issue. How do you trigger portRead?
Typically this is done with the signal readyRead from QSerialPort. However, it is not triggered for every byte, but may be triggered when several bytes are in the buffer. This is dependent on comm speed.
-
Thank you for your replies. I understand what you mean. You can see my serial port configuration below.
QSerialPort *serial;
serial = new QSerialPort(this); serial->setPortName("ttyS0"); serial->setBaudRate(QSerialPort::Baud9600); serial->setDataBits(QSerialPort::Data8); serial->setParity(QSerialPort::NoParity); serial->setStopBits(QSerialPort::OneStop); serial->setFlowControl(QSerialPort::NoFlowControl); serial->open(QIODevice::ReadOnly); connect(serial,SIGNAL(readyRead()),this, SLOT(portRead()));
As you say, I use the typical method of triggering. As you know, the PortRead function is as follows.
void MainWindow::portRead(){ QByteArray portData; portData=serial->readAll(); if(portData==QChar('[')){ tempList.append(portData); arrayFirst=1; }else if(portData==QChar('*') && arrayFirst!=0){ emit arraySplit(tempList); tempList.clear(); arrayFirst=0; }else if(arrayFirst==1){ tempList.append(portData);
- How should I trigger portRead for read the data from the serial port as char? (Without delay.)
2.How can I clean the buffer? I tried the Clear & flush methods but it did not work.
Thanks.
- How should I trigger portRead for read the data from the serial port as char? (Without delay.)
-
@aktay said in Raspbbery Pi 3 Serial Port Performance Problem:
How should I trigger portRead for read the data from the serial port as char
I think you can't. Just use the loop in portRead().
-
OK, you are triggering portRead through readyRead signal and this is correct. The question was more that you are triggering with the right method.
Now some people assume that readyRead() is triggered in regularly e.g. on a byte basis or record basis. However, just to ensure that is not the case. Triggering on a byte basis would probably overflow the event loop for fast connections and recordwise is not possible either, since how should any device decide on a binary level when a record ends.
Without knowing the exact details of triggering a signal readyRead, you may assume that it is triggered when new data arrives and you are not in a slot and subsequent routines triggered by readyRead signal.You started to see "problems" when you suddenly did not receive at each call of readyRead one byte. This is completely normal when your additional functionality pick up cpu resources.
In your case you are seeing more than one byte in the string returned by readAll after you have added functionality.
As already written before
@koahnig said in Raspbbery Pi 3 Serial Port Performance Problem:
You are reading all bytes in the buffer with readAll() and you are outputting all those bytes with the next statement. Actually you are always reading a complete string and youare always outputting a complete string. Only the first case the loop trigger, you are probably using, is faster and readAll reads only one byte to the buffer.
Now you have two choices:
- emptying the QSerialPort buffer at once with readAll as you do. This implies that you are required to some looping afterwards and handling individual bytes as you had done in your initial post.
- Looping around reading the QSerialPort buffer and use read and read byte by byte
Just neglecting a loop will not get you anywhere you like to be. Read also the comments I had added to your code here
@koahnig said in Raspbbery Pi 3 Serial Port Performance Problem:
void MainWindow::portRead()
{
QByteArray portData;
portData=serial->readAll(); // this statements whatever is in the buffer of QSerialPort may be 0 to almost infinity// you are compring a string with a character. Will work only when character is casted autmatically to string
// since the comparison is for strings you may compare "[100" with "[" which gives false.
// Only the when you have read one byte and it happens to be "[" you will have true.
if(portData==QChar('['))
{
tempList.append(portData);
arrayFirst=1;
}
// The same here as explained for "[" but for ""
else if(portData==QChar('') && arrayFirst!=0)
{
emit arraySplit(tempList);
tempList.clear();
arrayFirst=0;
}
else if(arrayFirst==1)
{
tempList.append(portData);One last thing you need to understand also is that when you use readAll at the beginning of the routine, the buffer is completely emptied at that point of time. Your processing in the routine and subsequent routines may take a while. Any byte stored into the buffer during your processing will most likely not create a new readyRead signal. Therefore, it is advisable to check the buffer's size with bytesAvailable at the end in order to make that you are not missing information which will pop up with the next signal readyRead.