I have to pilot a Laser at work, to do that I need to communicate with a serial port in RS232. As you must be cautious when you use a laser, you need to constantly read the laser status (temperature, power, etc...) and to do that you have to send a lot of commands (~20) each 1 or 2 seconds.
I use the Qt Class QserialPort and my problem is that when I send all my commands I block the GUI and the program becomes unusable. I read a lot about QSerialPort and how to use it, the examples : Blocking Master, Blocking Slave, Async reader, Terminal, etc..; and I still cannot figure it out.
First I wanted to use threads but this guy's answer says it's a bad idea. Then, I tried without threads but got the same result.
What I would like is a way to communicate with the laser which does not make the whole program wait for an answer to be sent and its corresponding answer to be treated. I send my first command, the laser answers, I process the answer, then I send a 2nd command, etc... all of that in the background.
My current implementation is thread based, but I have an other without thread.
I have the MainWindow class for the GUI, a Laser class which knows how to compose a message for the laser to understand and can understand the laser's answer, and a LaserThread class opening the connexion with the serial port, wrinting and reading.
To send a command, I do :
void LaserThread::writeData(const QByteArray &data)
{
while(m_serialPort->waitForReadyRead(200)){} //Timeout is 200ms
m_serialPort->write(data);
}
which means I wait for an answer to be received before sending a new command. I tried to use waitForBytesWritten but could not get the expected result. I have to call this function 20 times in a row.
To read an answer :
void LaserThread::readFromFPGA()
{
if (m_serialPort->bytesAvailable()>0) {
if (m_serialPort->waitForReadyRead(20)){
QByteArray response = m_serialPort->readAll();
if(response.size()==0)
return;
qDebug() << "response" << toDebug(response); //transforms bytes to QString
if(m_laser->checkMessage(response)) //check msg conformity
m_laser->handleMessage(response); //process it
}
}
}
Right now my two problems are :
- Or, I wait too much to send a new command and the UI is freezed
- Or, I do not wait too much, send 25 messages and only get one answer back.
What is the proper way to communicate (async or sync) constantly with a serial port without freezing the program ?