QSerialPort emitting of readyRead()
I am currently working with a device that is controlled via a serial Port. I am using Qt for GUI purposes and want to use it for the serial Port functions as well. Point is I got trouble noticing when data is being resceived by the computer.
I got something like the following. Where serialPort is a QSerialPort and member of ComPortControl
connect(&serialPort, SIGNAL(readyRead()), this, SLOT(someReadFunction()));
QByteArray arrivedMsg = serialPort.readAll();
//fancy stuff I do with the message
This does not work as intended. The readyRead() signal is emitted only after a certain amount of data has been resceived at the Serial Port. I have pretty short individual messages and must request data multiple times until the signal is emitted. At this point I get all the data from all the requests at the same time.
Is there a way, to tell the Port to emit the signal as soon as there is something in the read buffer. Preferably without polling.
I had some issues with this as well.
In my case I ended up not depending on this signal. I check a modified 'bytesAvailable()' function periodically in a separate thread (polling, not what you wanted). The waitForReadyRead(1) was necessary to have it 'update' itself or whatever.
It is possible that calling waitForReadyRead(1) might also do the trick without having to poll but you would have to call this regularly.
bq. The readyRead() signal is emitted only after a certain amount of data has been resceived at the Serial Port.
This is the OS && the driver && the port speed dependent thing.
bq. Is there a way, to tell the Port to emit the signal as soon as there is something in the read buffer.
Currently it is so works. The readyRead() emits when at least one byte were received. But in practice about 5-10 bytes during this time manage to come (I mean a time until the system Rx event was triggered up to data will be read into internal buffer of class). Therefore in each of readyRead() about 5-10 bytes are available to reading. This behavior is a driver && OS && speed specific (as I wrote above).
bq. The waitForReadyRead(1) was necessary to have it ‘update’ itself or whatever.
The waitForReadyRead() just "override" the Qt event loop. Internally - it is works similar with Qt event loop, but, maybe a little quicker than Qt event-loop. But in this case, maybe too you will receive about 5-10 bytes after every waitForReadyRead() call (need to check it).
bq. I have pretty short individual messages and must request data multiple times until the signal is emitted.
In common case this is impossible to implement as you want (if I understand correctly). In case your short messages follow one after another with small delay, then the serial port will interpret it as continuous data stream; in case your messages has a long delay, then, maybe, in each readyRead() will be located a whole message.
But there is a small trick: to reconfigure serial port on the blocking reception of data with a desired timeout, using QSerialPort::handle() method. In this case you can specify desired count of bytes (or timeout) to receive.
For this purpose you should to use:
- on Windows, try to reconfigure the
COMMTIMEOUTS structure: https://msdn.microsoft.com/en-us/library/windows/desktop/aa363190(v=vs.85).aspx
using SetCommTimeouts function: https://msdn.microsoft.com/en-us/library/windows/desktop/aa363437(v=vs.85).aspx
- on Linux/Mac/BSD and other, try to reconfigure the termios structure
using VMIN/VTIME fields.
maybe this will helps for you, but in this case you should to move whole of QSerialPort instance into separate thread, since now the I/O will be blocking and can freeze Qt event-loop.
You don't require to increase the emission frequency of readyRead() signal, I believe.