read data from serial port
-
@mrjj said in read data from serial port:
qDebug() << values;
return :
\n191", "2018/8/3", "23:28:55 \r\n187", "2018/8/3", "23:28:55 \r\n185", "2018/8/3", "23:28:55 \r\n164", "2018/8/3", "23:28:55 \r\n131", "2018/8/3", "23:28:55 \r\n103", "2018/8/3", "23:28:55 \r\n.................................... -
Ok so when we only split at ","
We get \n\r on some/all of the values.
Using something Like ReadLine might be easier.
but you seem to use native serial comm and not Qt version?
but you can try
for ( const QString& valline : values ) {
qDebug() << "val =" << valline.trimmed().toInt();
}
Trimmed() should remove the \n\r
http://doc.qt.io/qt-5/qstring.html#trimmedah. wait.
it looks like some of the values are in same index as timestamp
"23:28:55 \r\n187" -
Hi
Im not really sure what is happening.
Seems to not to be structured as we think/needs more splittingQString input{"85,2018/8/3,17:21:3\\n\\r85,2018/8/3,17:21:3\\n\\r95,2018/8/3,17:21:3"}; QStringList lines = input.split("\\n\\r"); for ( const QString& line : lines) { QStringList values = line.split(","); for ( const QString& valline : values ) { qDebug() << "val =" << valline.trimmed().toInt(); } }
val = 85
val = 0
val = 0
val = 85
val = 0
val = 0
val = 95
val = 0
val = 0when do you start processing the input ?
After it all have been read or how do u know that input is ready ? -
@mrjj it's return zero and sometimes 2018
when do you start processing the input ?
After it all have been read or how do u know that input is ready ?I'm not sure what you mean?
read from serial port in thread and thread start in other class constructor.
so it's start when program run!
data send from arduino that connected to raspberry pi with USB port -
@isan
Looking at the code, it seems to me you
send al data and thread will read it all. and then close serial.
sowhile (serialDataAvail(fd) > -2) { //-------value format is int------- value = serialGetchar (fd) ; //--------vs format is QString------ vs.push_back(value); } serialClose(fd); // here u should have complete data and can use to get the values if data is complete input would be vs QStringList lines = input.split("\\n\\r"); for ( const QString& line : lines) { QStringList values = line.split(","); for ( const QString& valline : values ) { qDebug() << "val =" << valline.trimmed().toInt(); } } }
-
@mrjj
I have no idea of the implications, but you have pasted code for OP as:QStringList lines = input.split("\\n\\r");
If he is supposed to be copying this, shouldn't he be using
QStringList lines = input.split("\r\n");
Or, from his
qDebug()
, does it mean that the input literally has the 4-character sequence\r\n
in it, and not CR-LF? In which case he would wantQStringList lines = input.split("\\r\\n");
-
Now, going back to where @isan wrote:
return : \n191", "2018/8/3", "23:28:55 \r\n187", "2018/8/3", "23:28:55 \r\n185", "2018/8/3", "23:28:55 \r\n164", "2018/8/3", "23:28:55 \r\n131", "2018/8/3", "23:28:55 \r\n103", "2018/8/3", "23:28:55 \r\n....................................
So if that's really right, after first splitting on
"\r\n"
(not even certain about that if the input really starts as shown with just\n
and not\r\n
, I'll just assume it's really\r\n
), he then needs to split on"\",\""
, not just plain,
. Then at the end of that you have 3 clean tokens per line.I have to say the input looks a bit oddly tokenized/quoted, but that's what corresponds to the input he shows. If you're not careful and leave
"
characters in, you'll gettoInt()
returning0
where you don't expect. -
@JonB
Hi
I think the "s comes from qDebug and is not in the input. (looking at the sending code higher up)
It seems he reads the entire load in one go and closes port so that means he should be able to
read complete string and then split it. ( i hope ) -
@mrjj said in read data from serial port:
@isan
Looking at the code, it seems to me you
send al data and thread will read it all. and then close serial.
sowhile (serialDataAvail(fd) > -2) { //-------value format is int------- value = serialGetchar (fd) ; //--------vs format is QString------ vs.push_back(value); } serialClose(fd); // here u should have complete data and can use to get the values if data is complete input would be vs QStringList lines = input.split("\\n\\r"); for ( const QString& line : lines) { QStringList values = line.split(","); for ( const QString& valline : values ) { qDebug() << "val =" << valline.trimmed().toInt(); } } }
Data is always sent and It does not go out of while() and I can not wait for complete data
Upon receive, I must use the data in other classes
I should not miss any data, if I close the port, the data will be lost -
@isan
ok so it must be on the fly.Then you need to use 2 buffers as not to parse already received data over and over.
so in pseudo codeRead char from serial
tempbuffer += char
if char is \n then
split tempbuffer
emit value
clear tempbuffer//i assume u want to store all ?
Mainbuffer +=char -
@mrjj so the code is like:
void MyThread::run() { qDebug("Thread id inside run %d",(int)QThread::currentThreadId()); int fd ,x; if ((fd = serialOpen ("/dev/ttyACM0",230400)) < 0) { fprintf (stderr, "Unable to open serial device: %s\n", strerror (errno)) ; } while (serialDataAvail(fd)>-2) { //-------value format is int -------// value=serialGetchar (fd) ; //--------vs format is QString------// vs.push_back(value); //--------tempbuffer format is QString------// tempbuffer .append( vs); if (vs=="\n") //-------- values format is QStringList------// values = tempbuffer.split(","); x= values[0].toInt(); msleep(1); emit signalValueUpdated(x); tempbuffer.clear(); } serialClose(fd); }
is it true?
-
@isan
Hi
Almost, you need to clear tempbuffer as soon as you have used it.
And u need to check last read char (value) being the \nvoid MyThread::run() { qDebug("Thread id inside run %d", (int)QThread::currentThreadId()); int fd, x=0; if ((fd = serialOpen ("/dev/ttyACM0", 230400)) < 0) { fprintf (stderr, "Unable to open serial device: %s\n", strerror (errno)) ; } while (serialDataAvail(fd) > -2) { value = serialGetchar (fd) ; vs.push_back(value); tempbuffer += value; if (value == '\n') { values = tempbuffer.split(","); x = values[0].toInt(); tempbuffer.clear(); } msleep(1); emit signalValueUpdated(x); } serialClose(fd); }
-
@mrjj , @isan
This code looks wrong. It doesn't help that we don't see the declarations ofvs
ortempbuffer
. Comment://--------tempbuffer format is QStringList------//
No, it isn't, because later you go
tempbuffer.split(",");
. So it's probably aQString
.Then: you read 1 char, you append it to
vs
. Then you appendvs
totempbuffer
. Ifvalue
is not\n
, you pick up the next char, append that tovs
(now 2 chars long), append that totempBuffer
(now 3 chars long)...Hmm,
vs
must be a single char, not aQString
like the comment says it is? Who knows....Separate issue:
while (serialDataAvail(fd)>-2)
Nope.
serialDataAvail(fd)
returns-1
on error. The code accepts that as a legal. It also should therefore never exit thewhile
loop. Further, if 0 bytes are available code goes into thevalue=serialGetchar (fd)
call. After 10 seconds of no data that will return-1
. At which point accepts that as the legal char received. Finally, if error opening device in the first place, the code writes a message and then continues into the loop, which makes no sense.All this code really needs correcting....
Finally, have a think about the fact that sometimes you are using Qt & C++ functions, sometimes you are doing lowest-level C library calls. Do you really need to mix them?
-
+@JonB
Thx, yes value should be added to tempbuffer.
Then i can learn not to edit code in forum directly :)
So something like this + all than @JonB saidwhile (serialDataAvail(fd) > -2) { // fix condition! value = serialGetchar (fd) ;// read char vs.push_back(value); // store in ful buffer tempbuffer += value; // add to tempbuffer if (value == '\n') { // if we just read \n values = tempbuffer.split(","); // split on , to QStringList x = values[0].toInt(); // take first index and convert to int tempbuffer.clear(); // clear it for next } ......
-
I‘ve been following this thread for a while now, and you guy‘s doing a great job :-)
Just one thing that‘s been buging me from the beginning.
The call off split on the string. It‘s used for nothing but temporary storage to than turn the first entry into an INT.
I would highly recommand to at least use splitref.
-
@J.Hilk
Yes i agree. but in this case we wanted to split very small sample so
i decided not to introduce new classes. (QVector/QStringRef)
as to focus on getting it running. But yes, much better to use normally as the speed gain is huge for large dataset. (more than i did imagine)