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

10,671

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

Share:
10,671

Related videos on Youtube

thejavo
Author by

thejavo

Updated on September 18, 2022

Comments

  • thejavo
    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 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
    
    • Basile Starynkevitch
      Basile Starynkevitch almost 7 years
      Did you try dd ? It might work (with suitable options).
    • ivanivan
      ivanivan almost 7 years
      Your head command may be getting slightly old data due to a buffer, and you are reading the top of it. When you tried tail, it was with other arguments. Try repeating the head command options with tail
    • thejavo
      thejavo almost 7 years
      Thank 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
      agc almost 7 years
      Try prefixing a non-cat command with stdbuf -i 0 -o 0, i.e. stdbuf -i 0 -o 0 head -1 /dev/ttyUSB0 | strings.
  • thejavo
    thejavo almost 7 years
    thanks 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.