QSerialPort read and write in the same QThread
-
-
@aha_1980 hey so after a few try i am a bit lost here.
So firstly I know I must use a thread for my use case (I use this thread to transfer complete files via xbee module using serial port so it takes some time)
But I ran in some issues.
Since my thread must run indefinitly, I put a while(1){} in it and I am doing all my stuff in this loop. But unfortunatly, it always use 100% of the cpu. Do you have any idea on how to put the thread in sleep mode and wake it when I make a write request or when a QSerialPort::readyRead occurs?
thanks for your help
-
@romain-donze look this code.
I hope you find it useful.m_serial->clear(QSerialPort::AllDirections); // write a request const QByteArray requestData = QString("your request\r\n").toUtf8(); m_serial->write(requestData); if (m_serial->waitForBytesWritten(m_waitTimeout)) { // wait and read the response if (m_serial->waitForReadyRead(m_waitTimeout)) { QByteArray responseData = m_serial->readAll(); while (m_serial->waitForReadyRead(100)) responseData += m_serial->readAll(); } }
-
So firstly I know I must use a thread for my use case (I use this thread to transfer complete files via xbee module using serial port so it takes some time)
As said multiple times, that is no reason to need a thread.
Regards
-
@romain-donze said in QSerialPort read and write in the same QThread:
How would I use waitForBytesWritten() to not block my code
You would not use it at all. You would use the bytesWritten() signal.
Do note however, that this does not mean the bytes are actually transmitted. It only means, the bytes are transferred from Qt's buffer to the operating system buffer.
Serial devices are slow. You can calculate the needed time approximately with the baud rate the device is set to.
Regards
-
@romain-donze you can swap the code, before you wait to receive data with a specific timeout and after you can send a reply.
You can manage your other asyncronous write in the main loop with a Semaphor or Event for example. -
Hi,
Use the "readyRead" SIGNAL to receive the data.
In your write method you could write the data into chunks (N bytes). After write a chunk, call QApplication::processEvents() that forces the calling thread to process the events and so it will receive the data if it is there. -
@romain-donze said in QSerialPort read and write in the same QThread:
so is there some examples on how to use it?
-
@aha_1980 just so you know, I did some test with my uart device plugged to my board and I am receiving data evry 2ms (I am receiving a string that looks like that "#Z%d,%.2f\r")
In my readData() function, I do this (this function is connected to the readyRead signal)
void mUart::readData() { QByteArray singleData = mSerial->readAll(); mBufferData = mBufferData + QString::fromUtf8(singleData); QStringList dataList; if(mBufferData.contains('\r')) { dataList = mBufferData.split('\r'); foreach (mTrame, dataList) { emit this->dataReceived(mTrame); qDebug() << mTrame; } } }
the mUart class is move to a thread and even so, I am using more than 100% of my cpu... Is ther something I do wrong?
-
@romain-donze said in QSerialPort read and write in the same QThread:
the mUart class is move to a thread and even so, I am using more than 100% of my cpu... Is ther something I do wrong?
of course, just because you moved the invite loop into a thread, doesn't mean it uses less CPU!
-
This post is deleted!
-
@J-Hilk yes I know, but as you see, as I explained, I receive a lot of data and I think that is why my readData function is constantly called... so I don't think it's a good thing to let it in the main thread
P.S. sometimes my app crashes. Maybe because I have to many data to read? ):
-
@romain-donze
Hi
Do you clear your buffer once you processed it ?
You do
mBufferData = mBufferData + QString::fromUtf8(singleData);so it will grow until you run out of memory unless you clear it at some point.
You could move your processing to a worker thread so it will do the split and
emit to the objects.