77

On Linux, I want to send a command string (i.e. some data) to a serial port (containing control characters), and listen to the response (which also usually might contain control characters).

How can I do this as simplest as possible on Linux? An example is appreciated!

2
  • you should look at this unix.stackexchange.com/a/116705/53092 Commented Feb 26, 2014 at 12:28
  • I don't have interceptty installed. Commented Feb 26, 2014 at 12:32

6 Answers 6

101

All devices on Unix are mapped to a device file, the serial ports would be /dev/ttyS0 /dev/ttyS1 ... .

First have a look at the permissions on that file, lets assume you are using /dev/ttyS1.

ls -l /dev/ttyS1

You will want read.write access, if this is a shared system then you should consider the security consequences of opening it up for everyone.

chmod o+rw /dev/ttyS1 

A very simple crude method to write to the file, would use the simple echo command.

echo -ne '\033[2J' > /dev/ttyS1 

and to read

cat -v < /dev/ttyS1 

You can have cat running in one terminal, and echo in a 2nd.

If everything is gibberish, then baud rate, bit settings might need setting before you start sending. stty will do that. !! NOTE stty will use stdin as default file descriptor to affect.

Equivalent commands.

stty 19200 < /dev/ttyS1 stty 19200 -F /dev/ttyS1 

This might be enough for you to script something and log ? Not sure what you are trying to achieve.

For a more interactive, remembers your default settings approach would be to use minicom it is just a program which does everything I've mentioned so far. (similar to hyperterminal in Windows, you might be familiar).

An intermediate solution, would use a terminal program like screen which will work on a serial device.

screen /dev/ttyS1 

man screen man minicom man stty for more information

2
  • 1
    I'm not getting any output at all. Have any ideas? Commented Nov 10, 2018 at 1:01
  • Possibly hardware flow control, either switch off with atty command or strap high in serial cable, search for null modem cable. Commented Nov 10, 2018 at 9:37
32

All you have to do is open two terminals. In the first terminal you cat everything from the device, e.g.

cat /dev/ttyS0 

in the other terminal, you can send arbitrary hex characters and text to the terminal e.g. as follows:

echo -e "\x7E\x03\xD0\xAF und normaler Text" > /dev/ttyS0 

The echo -e command enables the interpretation of backslash escapes.

One has to make sure of course that (i) the serial settings (speed, word length, flow ctrl, etc) are correct and (ii) the serial device (on the other end) is not blocking.

4
  • You have answered this 10 mins after I wrote my answer above and you haven't added any further information at all ! Commented Feb 26, 2014 at 15:24
  • Oh sorry, I did not read your answer completly. I saw that my answer is included in yours, so I will accept your answer as the correct one, as you described just what I have described. Commented Feb 26, 2014 at 16:06
  • I don't know much about COM ports. Could you please explain what does "the serial device (on the other end) is not blocking" mean? Some issue with the firewall? Commented Sep 13, 2015 at 15:55
  • echo -ne '\xFF' > /dev/ttyUSB0 works for me. if someone is having issues make sure the baud rate of your port is the same as the baud rate of your device. Commented Jul 9, 2021 at 16:48
24

This could be a better approach:

stty -F /dev/ttyUSB0 115200 raw -echo #CONFIGURE SERIAL PORT exec 3</dev/ttyUSB0 #REDIRECT SERIAL OUTPUT TO FD 3 cat <&3 > /tmp/ttyDump.dat & #REDIRECT SERIAL OUTPUT TO FILE PID=$! #SAVE PID TO KILL CAT echo "R" > /dev/ttyUSB0 #SEND COMMAND STRING TO SERIAL PORT sleep 0.2s #WAIT FOR RESPONSE kill $PID #KILL CAT PROCESS wait $PID 2>/dev/null #SUPRESS "Terminated" output exec 3<&- #FREE FD 3 cat /tmp/ttyDump.dat #DUMP CAPTURED DATA 
4
  • This is very good because it automates the process! The only change I would make, which is totally optional, is to confirm the contents received is the same as sent - could be just a count or full on diff. Commented Feb 5, 2019 at 19:55
  • 2
    As I warp above code in bash function and call my entire script in loop by watch -n 0.2 ./send.sh I discover that after few calls or when send CTRL+C signal and re-execute it, my output data are printed in oddly way. The reason is about left cat-s process that have simulations access to my port. You can list that by lsof /dev/ttyUSB0 So I add lsof -t /dev/ttyUSB0 | xargs -r kill -9 at the beginning, to be sure that only one cat process exists in a given runtime of my function. Commented Feb 18, 2023 at 16:40
  • It might be better to switch the order of the first two commands — exec 3< and then stty.  Opening the device (with exec 3<) locks it into an “open” status, which should ensure that settings are persistent.  If you do the stty first, the device will be closed and the settings might be reset. Commented May 17, 2023 at 21:47
  • This script locks on line two "redirect serial output to FD 3". I'm on a mac. Any idea why? Commented Jul 23, 2024 at 14:50
22

Programs that talk to serial devices:

picocom minicom socat 

or from shell you can do:

stty -speed 19200 < /dev/ttyS0 # sets the speed of the port exec 99<>/dev/ttyS0 (or /dev/ttyUSB0...etc) printf "AT\r" >&99 read answer <&99 # this reads just a CR read answer <&99 # this reads the answer OK exec 99>&- 
2
  • 4
    speed is not recognized as a valid argument on ubuntu stty -F /dev/ttyS0 9600 cs8 -cstopb -parenb Commented Jul 7, 2020 at 17:45
  • This works great and provided a wonderful solution to my UART dilemma of downloading a file over the UART and providing feedback path to see if it got there successfully. It seems like this solution could also be extended to split a file into chunks, sending each chunk and sending success/failure indication for each chunk. Thank you for posting! Truly appreciated! Commented Apr 22, 2021 at 12:04
5

You can read and write to a device simulataneously like so:

cat /dev/cu.usbmodem411 & cat > /dev/cu.usbmodem411 

Your message is sent to the second cat from stdin, and the first cat relays the response to stdout, turning your terminal into a chatroom.

To finish up, ctrl-c, then run fg then ctrl-c again.

0

Besides other answers we can use cutecom a GUI application to communicate with serial devices in Unix like systems.

It seems more practical for non terminal gurus.

Install on Debian based systems

$ sudo apt install cutecom 

cutecom run


For a more useful example usage we can connect PC to an ESP32 board with an USB-UART convertor interface.

After connection we can detect and use it under the name of /dev/ttyUSB1.

You can ensure the serial device name connected to PC with consulting dmesg.

$ sudo dmesg --follow-new [ 7859.806558] usb 1-6.4: ch341-uart converter now attached to ttyUSB1 

So read what ESP32 write on serial port with cutecom.

ESP32 write some data on its serial port

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.