Is cat the only reliable command that can read data from serial

catcommand lineheadserial porttty

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 an EOF, it continues retrieving data. I've also tried head, read and tail.

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 use head. But I'm wondering, as cat never fails, if there's a way to capture only one line of cat 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

Best Answer

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 Question