QSerialPort, randomly missing bytes
-
Hello, i'm a bit at a loss.
Recently I've been having some problems with our software.
We use it to communicate with our hardware using USB-TTL cables using a WCH chip. The driver is the last version available, either installed automatically by windows or manually.
The affected PCs are running Windows 10 and 11.The problem is, sometimes, at random, communication fails because of a missing byte: apparently the PC doesn't get the last byte from the packet. For years i've been using a library i wrote that used the synchronous approach. (roughly write -> wait for written. read -> wait for data until a timeout. The hardware device is always silent and only responds to command coming from the PC. The process living in another thread so it didn't matter to the GUI if it was blocking)
I also wrote a new version that is almost completely asynchronous (synchronous write -> wait for bytes written. Then, clear the RX Buffer. Then, slot from data ready signal reads all the data an places it in a QByteArray, a QFuture runner periodically checks for data in the QByteArray and if i'm expecting a response places it in the response buffer)
Works flawlessly on hundreds of PCs around the globe, except these few ones.
They are all from different makes, less and more powerful CPUs, the only thing they have in common is that they all are from eastern europe countries. I tried spinning up VMs with those locales, thinking it could make a difference, but i could never make the device fail.If we get sent back the cables and the hardware, they all work on our machines.
I don't really know what to look at, some software is built with 6.8.3, other with 6.10.2. MinGW, i haven't tried building with MSVC
There is probably some edge case i'm not thinking about but i really don't know what to look at.
-
Hi,
That's fairly intriguing...
Did you also compare the motherboards ?
What USB chip they have ?
Might be silly but could one of these machines be sent to you ? -
To add to @SGaist, you could try setting up a real PC (not a VM) to eastern europe locale and time, since you're dealing with (perhaps) some hardware dependency. Running your app inside a VM that hardware gets emulated, i.e. not showing the exact same characteristics.
-
Checking some basics:
readyRead()fires as soon as something can be read, not everything.- does
QSerialPortlive in one thread? Accessing it from multiple threads can be problematic and lead to unpredictable behaviour, actually pretty much the symptoms described.
@monegator said in QSerialPort, randomly missing bytes:
almost completely asynchronous
The almost raises an eyebrow. While having no personal experience with that specific class in a such a setting, I'd recommend to avoid mixing async and sync API.
Any chance you can show us some code?
-
and on the tablet that Moses dropped while coming down from the mountain, it said "Thou shalt use flow control"
-
and on the tablet that Moses dropped while coming down from the mountain, it said "Thou shalt use flow control"
@Kent-Dorfman said in QSerialPort, randomly missing bytes:
and on the tablet that Moses dropped while coming down from the mountain, it said "Thou shalt use flow control"
Highly efficient on the Red Sea !
-
If you parse data with like "\r\n" may be you read begin incorrect index
void onReadyRead() { static QByteArray buffer; buffer.append(_serial->readAll()); int index; while((index = buffer.indexOf("\r\n")) != -1) { QByteArray line = buffer.left(index); buffer.remove(0, index + 2); if(!line.isEmpty()) { parseData(line); } } }If you use
_serial->read(N); //or _serial->readLine();problem is here my opinion.
-
On my Mac the solution I found is (message is in the global "inputQString")
void MainWindow::slotRead(void)
{
qint64 bw = 0;
QByteArray data;data = port->readAll(); while (port->waitForReadyRead(15)) data += port->readAll(); inputQString = data; bw = inputQString.size(); //qDebug() << "inputString: " << inputQString << " bw: " << bw;; ReadRequest(bw);} // slotRead
Perhaps adjust the ms parameter of "waitForReadyRead(ms)"
-
On my Mac the solution I found is (message is in the global "inputQString")
void MainWindow::slotRead(void)
{
qint64 bw = 0;
QByteArray data;data = port->readAll(); while (port->waitForReadyRead(15)) data += port->readAll(); inputQString = data; bw = inputQString.size(); //qDebug() << "inputString: " << inputQString << " bw: " << bw;; ReadRequest(bw);} // slotRead
Perhaps adjust the ms parameter of "waitForReadyRead(ms)"
@FRAUBRJ said in QSerialPort, randomly missing bytes:
Perhaps adjust the ms parameter of "waitForReadyRead(ms)"
Even better: don't use it at all.
-
On my Mac the solution I found is (message is in the global "inputQString")
void MainWindow::slotRead(void)
{
qint64 bw = 0;
QByteArray data;data = port->readAll(); while (port->waitForReadyRead(15)) data += port->readAll(); inputQString = data; bw = inputQString.size(); //qDebug() << "inputString: " << inputQString << " bw: " << bw;; ReadRequest(bw);} // slotRead
Perhaps adjust the ms parameter of "waitForReadyRead(ms)"
@FRAUBRJ I'm afraid, you haven't found a solution.
You have found a way that happens to work for your hardware and your data at the current time of the moon phase.
There is so much to improve here, but the important part is, you need some why to verify that you have all data you expect. Do not expect that all data is there when readAll() is called.
And despite what you expect, it is called exactly once, your while loop is literally doing nothing.