- How to list all serial ports on Linux
- Background
- What do you need
- Listing the serial ports using a Linux GUI application
- Listing the serial ports using the Linux terminal
- Bash alias for listing the serial ports
- Wrap up
- How to send and receive data from serial port using command line?
- 3 Answers 3
- Using Screen:
- echo
- printf
- How to send a sequence of AT commands to a serial port in bash?
- 5 Answers 5
How to list all serial ports on Linux
Linux comes with serial communication functionality built-in. Before you can communicate with a device, connected to your PC’s serial port, you just need to know the name of the serial port. On Windows it is typically COM1 , COM2 , etc. On Linux it is essentially a filename in the format of /dev/ttyS0 , /dev/ttyUSB0 or /dev/ttyACM0 . This article explains how to list all serial ports on a Linux based system.
Background
Especially when developing software for or interacting with microcontroller based systems, you often communicate using RS232 serial communication. Typically by means of an RS232-to-USB adapter. To communicate with an RS232 device, you need to know the name of the PC’s serial port to connect to. On Windows, you open up the device manager and look up the COM-port number. Listing the available serial ports on Linux is a bit different and desktop environments do not offer a graphical user interface to quickly identify the available serial ports. This article presents two methods for listing the serial ports on Linux. One with the help of a graphical user interface program and another one for working directly in the terminal.
What do you need
To complete the steps to list the available serial ports on Linux, you just need two things:
- A Linux based PC. It can be a desktop, server, virtual machine or a single board computer such as a Raspberry PI.
- A serial device connected to the PC. For example an RS232-to-USB adapter, an Arduino or a Raspberry Pico.
For this article I’ll be using my main openSUSE Tumbleweed system. It’s a Lenovo ThinkCentre with one actual physical serial port. Additionally, I connected two serial devices: An RS232-to-USB adapter and an Arduino Uno.
Listing the serial ports using a Linux GUI application
Unfortunately, Linux desktop environments do not offer a GUI program to quickly and conveniently show all the available serial ports. However we can simply install one that does. Chances are you want a GUI program for monitoring the serial port in Linux anyway. My recommendation: CuteCom. Installation instructions for CuteCom on popular Linux distributions:
- Debian and Ubuntu: sudo apt install cutecom
- Fedora: sudo dnf install cutecom
- openSUSE: sudo zypper install cutecom
Once installed, open up the CuteCom program. It shows a Device drop-down list on the top of the main window. And voilà, it lists all serial ports on your Linux system:
As you can see in the screenshot, CuteCom lists all three serial ports currently connected to my Linux system:
- /dev/ttyS0 → The physical serial port on my PC.
- /dev/ttyUSB0 → The RS232-to-USB adapter.
- /dev/ttyACM0 → The Arduino Uno board connected via USB cable.
Listing the serial ports using the Linux terminal
The past section showed that Linux assigns a file name to serial devices with the acronym TTY in it. TTY stands for teletypewriter. With these historical devices you could send typed text messages to a remote location, using serial communication. Eventually leading to the invention of the fax machine. Hardly anyone still uses these devices. Nevertheless, the term TTY stuck around.
When it comes to using the terminal to list the serial ports, I prefer the approach that looks for TTY devices that the Linux kernel detected. Basically those that it found and managed to assign a driver to. The following command lists all of these:
- ls -l /sys/class/tty/*/device/driver
That’s a long list. I expected just three devices. The command output includes all so-called virtual and pseudo terminals. We just want to list the actual hardware serial ports. We can filter out the ones we don’t want by removing all lines that contain platform/drivers/serial8250 . The command then becomes:
- ls -l /sys/class/tty/*/device/driver | grep -v «platform/drivers/serial8250»
Alright, that looks a lot better. The output lists the three TTY devices that I expected: ttyACM0 , ttyS0 and ttyUSB0 . Ideally, the output shows just the actual device filename, needed to connect to the serial port. With a little akw magic, we can clean the output up for this:
- ls -l /sys/class/tty/*/device/driver | grep -v «platform/drivers/serial8250″ | awk » | awk -F’/’ »
Bash alias for listing the serial ports
I enjoy making one-liners for the terminal to get stuff done. However, the length of this one is such that I will never remember it. And I bet that’s the thought that crossed your mind too. Two options to solve this:
- Bookmark this page in your web browser and visit it whenever you need to list the serial ports from the terminal.
- Create a Bash alias.
With a Bash alias you essentially add a new command to your user’s shell with a name of your choice. Aliases are stored in the .bashrc file inside your home directory. You can edit it with whatever text editor you prefer. I’ll just use good old Nano:
Once in the text editor, add the following line. Note that escape characters were added where needed, to make it work. That’s before every double-quote and dollar sign:
- alias lsserial=»ls -l /sys/class/tty/*/device/driver | grep -v \»platform/drivers/serial8250\» | awk » | awk -F’/’ »»
Once done, save your .bashrc file and type this command to reload it:
Alternatively, you can just close and reopen your terminal program.
From now on you can list the available serial ports on your Linux PC, by simply typing this command in the terminal:
- lsserial
Wrap up
This article presented you with two different methods for listing the available serial ports on your Linux PC.
- Using the CuteCom GUI application.
- Piping several commands together for a terminal one-liner.
Going with method two, this article explained how you can add a Bash alias for the constructed terminal one-liner. Afterwards you can list the serial devices by simply typing the lsserial command in the terminal.
If you work with serial ports in Linux, you might be interested in one of the other serial port related articles:
How to send and receive data from serial port using command line?
In the past, I have used c++ and python to communicate with serial ports in a Linux and Windows environment. In Linux, I have also used programs like picocom, minicom, and cutecom for serial communication but now I want to read and write to the serial port using simple Linux commands which requires no installation of external programs. I would be using this method in raspberry pi to communicate with my Arduino board. In the below example I’m using stty for setting serial port options and I use echo and cat command to send and read data from the serial port but at the end, I’m not seeing any output, I have read other posts in this site related to this but nothing seems to work for me. I’m able to communicate with Arduino using cutecom but with below commands, I don’t see any response. Linux (Ubuntu):
$ stty -F /dev/ttyUSB0 9600 cs8 -cstopb -parenb $ echo "1" > /dev/ttyUSB0 //send data $ cat /dev/ttyUSB0
#include void setup() < Serial.begin(115200); >void loop() < if(Serial.available() >0) < Serial.println("[123,55,7777]"); >>
Here i send 1 and i get the response from arduino: This should be pretty simple I send 1 or any character to Arduino and it should return [123,55,7777] in the command line. Any kind of help and guidance is appreciated. Below is the code that I have tried but doesn’t return any data.
stty -F /dev/ttyUSB0 115200 cs8 -cstopb -parenb #CONFIGURE SERIAL PORT exec 3 /dev/ttyUSB0 #SEND COMMAND HEX 0x01 TO SERIAL PORT sleep 0.2s #WAIT FOR RESPONSE kill $PID #KILL CAT PROCESS wait $PID 2>/dev/null #SUPRESS "Terminated" output exec 3
Writing to the serial port from the Linux command line
The device starts the requested operation. When I try to accomplish the same operation from a stand-alone Debian box or from a Debian VirtualBox instance of the same Windows machine, I had no luck so far. Here are equivalent Linux commands (at least I think so):
stty -F /dev/ttyS0 speed 9600 cs8 -cstopb -parenb echo '\x12\x02' > /dev/ttyS0
3 Answers 3
If you want to use hexadecimal codes, you should add the -e option to enable interpretation of backslash escapes by echo (but the result is the same as with echo Ctrl + R , Ctrl + B ). And as wallyk said, you probably want to add -n to prevent the output of a newline:
Also make sure that /dev/ttyS0 is the port you want.
thanks, I am sure that it is the port that I want, is there a simpler way of testing serial connection, echo always returns success.
will not be interpreted, and will literally write the string \x12\x02 (and append a newline) to the specified serial port. Instead use
which you can construct on the command line by typing Ctrl V Ctrl R and Ctrl V Ctrl B . Or it is easier to use an editor to type into a script file.
The stty command should work, unless another program is interfering. A common culprit is gpsd which looks for GPS devices being plugged in.
Thanks so much for your response, I tried the echo -n CTRL+VCTRL+RCTRRL+VCTRL+B from command line but I couldn't make it work, I want to try other commands, therefore I want to know how you come up with these translations(0x12 = ^R , 0x02 = ^B), these are not ascii translations I suppose.
@erincarikan: use man ascii to see how 0x12 relates to Ctrl-R. They are pure ascii. It is possible that some ctrl combinations won't work, like ctrl-@ (NUL). It could be easier to write a program to do a binary protocol like this.
thanks I totally got it, but unfortunately it doesn't work, I am suspecting that something is interfering with stty , I don't have gpsd running. I got to look into this more.
Using Screen:
Note: Screen is actually not able to send hexadecimal, as far as I know. To do that, use echo or printf .
I was using the suggestions in this post to write to a serial port, and then using the information from another post to read from the port, with mixed results. I found that using Screen is an "easier" solution, since it opens a terminal session directly with that port. (I put easier in quotes, because Screen has a really weird interface, IMO, and takes some further reading to figure it out.)
You can issue this command to open a screen session, and then anything you type will be sent to the port, plus the return values will be printed below it:
(Change the above to fit your needs for speed, parity, stop bits, etc.) I realize Screen isn't the "Linux command line" as the post specifically asks for, but I think it's in the same spirit. Plus, you don't have to type echo and quotes every time.
echo
It follows praetorian droid's answer. However, this didn't work for me until I also used the cat command ( cat < /dev/ttyS0 ) while I was sending the echo command.
printf
I found that one can also use printf's '%x' command:
c="\x"$(printf '%x' 0x12) printf $c >> $SERIAL_COMM_PORT
How to send a sequence of AT commands to a serial port in bash?
but this does not evaluate the answer from the device on that port. Is there a very simple way to automate this within a bash script, probably with the help of socat and/or microcom but no tools which cannot found on the most simple linux system.
5 Answers 5
If you install the PPP package you can use the chat program that comes with it. Or you can use kermit . Or the cu program that comes with uucp. But to do it with pure shell is trickier. You might be able to use the read and printf functions, with stdio redirected to the port.
stty -F /dev/ttyS0 38400 raw chat -f script.txt < /dev/ttyS0 >/dev/ttyS0
Ok, that makes sense. But I tried to do sudo bash -c "chat -v -f chat.txt < /dev/ttyS0 >/dev/ttyS0" with the verbose action and the file consisting of '' AT OK AT OK , but got no output at all. Is it working or not? Did I oversee something?
You won't see anything normally, but it looks you you can use the -sv options to see it logged to stderr. The -v by itself logs to syslog. BTW, you could also use the expect tool.
I'm doing the same thing, but on android mobile. can this answer help me? if yes, what is ppp packet and who can I install it.
Here is a very simple way to automate this within a bash script:
$ (echo AT; echo ATS0=0) | atinout - /dev/ttyS0 - AT OK ATS0=0 OK $
by using the atinout program which is written specifically with this functionality as its sole purpose. The output above is assuming ATE1 ; without echo the response from the modem will be "\r\n\r\nOK\r\n\r\nOK\r\n" .
In the example above, atinout will send the first command AT (properly terminating the command line with \r ), wait until it receives a Final Result Code (e.g. OK ) and first then continue processing the next command.
You can give input from a file by specifying that instead of the first - , and if you want to capture the output give a file name instead of the last - . You can use here doc instead of grouped echo commands if you like.