13

Is it possible to create a "virtual" serial device that sends data through a "virtual" serial port? I need to develop some code to interact with an Arduino but don't have it with me. Can it be done with socat, or some code that writes to a dev/ttyXXX file?

EDIT: I'm running Arch Linux

Jonathan Ballet
  • 973
  • 9
  • 21
joaocandre
  • 1,621
  • 4
  • 25
  • 42

1 Answers1

20

Yes, you can use socat to simulate a serial port.

You need to use socat's PTY address type:

PTY: Generates a pseudo terminal (pty) and uses its master side. Another
process may open the pty's slave side using it like a serial line or
terminal.

The simplest option is:

socat PTY,link=./virtual-tty,raw,echo=0 -

Have the application you are testing opens virtual-tty. Output from your application will print to the console. Text you type will be sent to your application.

As noted above, the PTY address type creates a peudo-terminal. The link option creates a soft-link between the pseudo-terminal and the given file. You can choose any filename you wish. Without the soft-link you would need to open the device and it is difficult to determine the correct one. raw puts the pseudo-terminal in raw mode. You usually want this as you don't want any of the special terminal handling options. echo=0 disables echo mode.

If you have (or create) an application that simulates the code executing on the Arduino, you can connect it via socat as well. If your simulator comunicates via stdin/stdout, then use the following command:

socat PTY,link=./virtual-tty,raw,echo=0 EXEC:simulator-command

The above connects the stdin/stdout of simulator-command to the pseudo-terminal.

If your simulator communicates via a serial port as well, then use the PTY command twice:

socat PTY,link=./arduino-sim,raw,echo=0 PTY,link=./virtual-tty,raw,echo=0

Have your simulator open arduino-sim.

esorton
  • 1,562
  • 10
  • 14
  • Exactly what I was looking for. One question though, using a single PTY, the first command you mention, how would I type data into `virtual-tty`? And, on anther note, I assume it is ok if my `arduino-sim` uses `boost::asio` for serial communication? – joaocandre Mar 22 '14 at 12:21
  • `virtual-tty` is analogous to `/dev/ttyUSB#` in the simulated environment. You would have the code you are developing to communicate with the Arduino open `virtual-tty`. That is one side of the serial connection. Data sent from the code you are developing will be displayed on stdout and you can send data by typing on stdin. This will work as long as communications between your host application and Arduino application is ASCII. I'm not familiar with `boost::asio`, but as the pty created by socat is a real pty same as created by the serial driver, there shouldn't be any problems. – esorton Mar 22 '14 at 12:26
  • Then what exactly is the difference between opening just one PTY and two PTYs as you show in the last command? Is it to avoid blocking/two programs acessing the same file simultaneously? – joaocandre Mar 22 '14 at 12:28
  • 1
    The last example is when you want to use a virtual serial port for both sides of the connection. You can't open the same PTY twice. It won't work. Think of it this way, if you are connecting two Linux computers via a null modem cable, you would open `/dev/ttyS#` on one and `/dev/ttyS#` on the other. You open TWO ports. It is the same with `socat`; `socat` is analogous to your null modem cable. The difference is `socat` is very flexible. I'd recommend reading the examples in the `socat` manual page for examples of the interesting ways in which it can be used. – esorton Mar 22 '14 at 12:53
  • 1
    Using `socat PTY,link=/dev/ttySIM0,raw,echo=0 PTY,link=/dev/ttySIM1,raw,echo=0`, I can see the device files being created, however both my program (using `boost::asio`) and PuTTY I don't see any output from my simulator program (which is just sending '47' repeatdly). Could it be related to the baud rate? What is the default value in `socat`? – joaocandre Mar 22 '14 at 14:54
  • 2
    The default baud rate is 38400. Here is a simple test. Open three terminals. Run the command above in one. Run `cat /dev/ttySIM1` in another. Type `echo hello > /dev/ttySIM0` in the third. You should see hello in the second. Just tested this and it worked (Ubuntu 13.10). Only difference was that I dropped `/dev/` so I wouldn't have to run as root. If this test works, then replace the `echo` with your program sending '47'. Hopefully you see '47' on the terminal with cat. You can adjust the baud rate at the command line with `stty -F /dev/ttySIM1 9600` before running cat if needed. – esorton Mar 23 '14 at 13:47