2

I have some device, connected to serial port. Actually, it is Arduino based temperature sensor.

I wish to write a script, which will connect to serial port, send a command to device, receive it's answer, print it to stdout and exit.

What is correct way to do this?

Usually, when accessing local program, it is ok to redirect it's output. For example, this is how I read CPU temperature.

datetime=$(date +%Y%m%d%H%M%S)
cputemp=$(sensors atk0110-acpi-0 | sed "s/CPU Temperature:[^0-9]*\([0-9\.]\+\).*/\1/;tx;d;:x")
echo "$datetime\t$cputemp"

Unfortunately, $() relies on explicit program end, which is not the case with serial communication. Serial server always online and has no explicit "sessions".

Of course, I can check to line feeds. But is this correct action? May be I should write my Arduino program so that it send Ctrl-Z after each response or something?

1 Answer 1

3

As you say, you cannot read end-of-file from a serial port. (Ctrl-Z is a microsoft thing). So usually, you read until you have the wanted number of characters, or until you find a delimiter like newline that signals the end of the data.

For example, I have a usb serial port with output connected back to input, so any writes to the device simply come straight back. The following script can retrieve what the device sends:

#!/bin/bash
tty=/dev/ttyUSB0
exec 4<$tty 5>$tty
stty -F $tty 9600 -echo
echo abcdef >&5
read reply <&4
echo "reply is $reply"

The script connects the serial device as file descriptor 4 for input, 5 for output, sets the speed and stops the echo you get for a tty, then writes "abcdef" and newline to the device. Each character will be sent back immediately, but the kernel driver will buffer up some input, so I dont need to start to read from the device before doing the write. The read ends by default when it sees a newline, and saves it in the variable reply, which is then echoed to stdout. You can put this script inside a v=$() type usage.

If your serial device data does not end with a newline, you can specify a different delimiter to the bash read with -d. Or if the reply is of a constant length, you can specify a length with -n. If you have binary data, you probably should add raw to the stty command to stop any special treatment of input.

You must log in to answer this question.

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