1

I want to read line by line from external device (ttyUSB) over serial on my Ubuntu PC. I have following script:

while true;
do 
    read line < /dev/ttyUSB0
    echo $line
done

The problem is that sometimes some lines or part of lines are corrupted. It looks more or less like that:

Long line which is ok
some text which is ok�J�� some text which is OK
Long lines which are OK
����Osome text which is OK

It looks like the problem gets more severe if there are more lines received one after another (or maybe if there are no pauses between lines) .

One suspicion was that it could be some issue with my serial adapter. However, I tried reading serial data using PuTTY and there everything was fine.

I can even make my script work properly if I have it running in parallel with PuTTY. In this case my script gives correct output and in Putty there is almost no data received - maybe every 20th character (this is understood as serial device can be read by only one application at a time)

So I assumed that it's a question of configuration of serial port which PuTTY is doing correctly while my script is not.

PuTTY is using default configuration: baud-115200, bits:8, stop:1, parity:none, flow control: XON/XOFF

I tried to set exactly the same configuration in my script as in Putty

stty -F /dev/ttyUSB0 115200 cs8 -cstopb -parenb ixon

but the problem is still the same.

Anyone have some other ideas?

6
  • I think it's bad USB UART adapter. I guess there is a voltage problem. Try another USB port or USB hub with own +5V power.
    – geoai777
    Apr 29, 2020 at 17:45
  • Not related to you exact issue, but opening and closing ttyUSB0 for every line you read will likely give you truncated or missing lines one day. You should open it once and keep it open. Among options to do this you can cat /dev/ttyUSB0 | while true .
    – A. Loiseau
    Apr 29, 2020 at 18:28
  • @A.Loiseau actually, I think it could be the issue. However, what I actually want to do is to break loop if line contains some string. With my method it's simple as I can just check line variable. Can it be done with your method?
    – Qwer
    Apr 29, 2020 at 18:34
  • I think something like (while test "${LINE}" != "foo" ; do read LINE ; done) < /dev/ttyUSB0 should work (more readable when multi-line). Also, if you only want to wait a line, grepping /dev/ttyUSB0 directly should work too.
    – A. Loiseau
    Apr 29, 2020 at 19:03
  • @A.Loiseau, you were right. It was as simple as cat /dev/ttyUSB0 | grep -m 1 "foo". Thanks!
    – Qwer
    Apr 29, 2020 at 20:15

1 Answer 1

0

Two things:

1- Your script actually opens and closes your serial line each time it reads one line, which may likely lead to missed characters or lines.

You can fix it in different ways, such as this one:

(
    while test "${LINE}" != "foo"
    do
        read LINE
    done
) < /dev/ttyUSB0

(I do not understand why this bug generates random characters)


2- But actually, as discussed in comments, this is a simple grep

grep --quiet --max-count=1 -F "foo" /dev/ttyUSB0
  • quiet: No need to pollute stdout with serial line stream
  • max-count: Exit successfully upon first match
  • fixed-strings: Do not waste CPU trying to find a regular expression

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .