[Interest] Parsing data from serialport

Roland Hughes roland at logikalsolutions.com
Mon Apr 1 22:52:04 CEST 2019


You probably want to read as far as I got with this series.

http://www.logikalsolutions.com/wordpress/information-technology/how-far-weve-come-pt-1/

Be sure to pull down the code for the various SerialKeypad implementations.

Here is a direct link to one of the zip files which was posted in case 
you are impatient.

http://www.logikalsolutions.com/wordpress/wp-content/uploads/2016/07/SerialKeypad.zip

While that series wasn't meant to be a tutorial on serial communications 
with Qt, quite a few nuggets of what you need to know are there.

I've got some other code floating around for doing serial communication 
with Qt but, as you can tell, I don't check this list regularly.

You can do a search for CommLib because whenever I'm talking about 
GreenLeaf CommLib from back in the days of DOS I'm generally talking 
about how to do serial communications right. There are many many many 
many gotchas today's platforms do not magically fix for you.

At the core of GreenLeaf's success/brilliance was the double ring 
buffer. Their little TSR (under DOS) had one ring buffer for writing to 
serial port and one the TSR stuff read characters into. It also kept 
track of whether it wrapped either because you wrote too much or waited 
too long to read. The ring buffer layer allowed the library to do 
_exactly_ what every kid wants to do when they write their first serial 
program. Read and write a packet. At the serial comm layer there is no 
concept of a "packet" beyond what you configured to be a byte. While 
many use 8-N-1, one cannot rely on that being the case.

Some devices won't even transmit a full 8 bits. Most newer ones will, 
but don't count on it. In particular, scale systems which only need to 
transmit the digits 0-9 and a "settled" indicator along with a checksum 
or CRC of some kind were notorious for nibbles. Some could even use 
their own form of packed decimal to keep the packet short for 300 baud 
transmission. Adding insult to injury were those scales (and other 
devices) which had no self control when it came to calculating the 
CRC/CheckSum byte. They would have a start-packet indicator as well as 
an end-packet value and the CRC/Checksum would end up being one of those 
when the weight was just right.

Unlike TCP/IP, _you_ have to do all error handling and planning. Do not 
assume a clear communications channel. Random electrical currents, 
magnets or even someone slapping something down on a desk can generate 
noise on the transmission line. (That last part applies more to modems 
than hard wire port to port but it does apply to hard wire, specially if 
the connection isn't screwed down tight. Just "feels tight" when pushed 
on isn't good enough. An imperceptible amount of wiggle can introduce 
noise on the line.)

If this is a production system, forget trying to do serial comm in your 
primary (GUI) thread. In a perfect world with only happy path testing 
you will get this to work and it will fail in the field. Something the 
user does or the GUI does or the database or some other thing stolen 
from an example program and left to run in the primary event loop will 
take __just__ long enough for your intricate well designed 
communications code to miss one or more critical control characters 
causing it to get completely lost.

Roland

On 4/1/19 5:00 AM, interest-request at qt-project.org wrote:
> Hello,
>
> I'm trying to implement a serial connection with QIODevice (SerialPort). I
> would like to parse line by line (each line consists of multiple columns of
> data) and for this I found canReadLine().
> But as I understand I have to use startTransaction, because otherwise the
> buffer will not be used. I'm I correct?
>
> bool QIODevice::canReadLine() const
> {
>      Q_D(const QIODevice);
>      return d->buffer.indexOf('\n', d->buffer.size(),
>                               d->isSequential() ? d->transactionPos :
> Q_INT64_C(0)) >= 0;
> }
>
> So to read a full line, I have to open a QSerialPort and then start a
> Transaction. Then I have to wait a little bit (till data is in the buffer)
> and then I can use canReadLine. Am I correct? Is there a better way instead
> to wait a little bit? Or is it the wrong way to go?

-- 
Roland Hughes, President
Logikal Solutions
(630)-205-1593  (cell)
http://www.theminimumyouneedtoknow.com
http://www.infiniteexposure.net
http://www.johnsmith-book.com



More information about the Interest mailing list