0

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 :

  1. Or, I wait too much to send a new command and the UI is freezed
  2. 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 ?

Community
  • 1
  • 1
ElevenJune
  • 423
  • 1
  • 4
  • 21
  • 1
    The link answer shows exactly what you need to do: Use the signals `bytesWritten` and `readyRead` and even provide link to asynchronous serial reader/writter. What is blocking you from trying these? – Holt Jun 29 '16 at 13:26
  • I don't understand how to use the bytesWritten signal. I was doing in my write function : serialPort->write(data); serialPort->waitForBytesWritten(200); and it sends all the command in once before i have the time to receive the answers – ElevenJune Jun 29 '16 at 13:31
  • 1
    `bytesWritten` is a signal, you connect it to a slot and the slot will be called each time the `bytesWritten` signal is emitted automatically. – Holt Jun 29 '16 at 13:33
  • in my case what should the slot do ? – ElevenJune Jun 29 '16 at 13:36

0 Answers0