Is cat the only reliable command that can read data from serial?
Your best bet is to place the tty in raw mode, and write a program that discards characters until it sees the start of a message, and then prints characters until it reaches the end of a message. With 'raw' added to the stty
, fgetc()
can be used on the tty to get a single character.
off the cuff psuedo:
char = fgetc(serial_port);
if char == START_CHARACTER {
putc(char);
for (i=0;i<MESSAGE_LENGTH;i++){
putc(fgetc(serial_port));
}
}
It may also be possible to do this with sed and a raw tty, see this other question: https://stackoverflow.com/questions/20943025/how-can-i-get-sed-to-quit-after-the-first-matching-address-range
Related videos on Youtube
thejavo
Updated on September 18, 2022Comments
-
thejavo almost 2 years
I have a scale that continuously send data via serial port, 2 times per second. The only reliable way on reading this data happened to be
cat
command. The following works:cat /dev/ttyUSB0
But the problem with
cat
is that, as it doesn't receive anEOF
, it continues retrieving data. I've also triedhead
,read
andtail
.head -1 /dev/ttyUSB0 | strings
works 'almost' everytime, but now and then shows old data, and only re-running cat command fixes it (?). The string after pipe retrieves only printable data.
read line < /dev/ttyUSB0 | echo $line
now and then retrieves data, but most of the time only shows an empty line.
tail -1 < /dev/ttyUSB0
just freezes, waiting for
EOF
, maybe?My issue is that i need to write a
bash
script that can be called and "read"/dev/ttyUSB0
and retrieve data. I'm going to usehead
. But I'm wondering, ascat
never fails, if there's a way to capture only one line ofcat
output and then stop it.Note: the port configuration is 9600 baud, 1 start bit, 8 data bits, no parity, 2 stop bits. To set the port properly this is the command:
sudo stty -F /dev/ttyUSB0 9600 -parity cs8 cstopb
-
Basile Starynkevitch almost 7 yearsDid you try
dd
? It might work (with suitable options). -
ivanivan almost 7 yearsYour
head
command may be getting slightly old data due to a buffer, and you are reading the top of it. When you triedtail
, it was with other arguments. Try repeating thehead
command options withtail
-
thejavo almost 7 yearsThank Basile, I'll investigate dd. Ivan, I agree with you. I've assumed that I'm reading some kind of buffer of stdout. ¿is there a way to reset it?. And don't understand why cat isn't affected with this buffer issue. Thank you. I've used head -10 /dev/ttyUSB0 | tail -1. But get the same result, erratic.
-
agc almost 7 yearsTry prefixing a non-
cat
command withstdbuf -i 0 -o 0
, i.e.stdbuf -i 0 -o 0 head -1 /dev/ttyUSB0 | strings
.
-
-
thejavo almost 7 yearsthanks you very much KJ4IPS!, i'll try not to "sound" rude, but I lack the vocabulary to "sound polite enough", so excuse me. But the answer you've wrote doesn't solve my problem. The scale already transmits data with 2Hz frequency. Inmediately after been turned on. Constantly. It never stops. So it's not possible to reach an end of message. On the other hand, I'm interested in solving this with pure bash.