1

My need is to connect an Arduino board (any board that has around 3 UARTs support) to a host PC via USB and expose the 3 UART connections as 3 USB devices (say /dev/ttyUSB0, /dev/ttyUSB1, /dev/ttyUSB2) in the host PC. From my search, I found Arduino Mega 2560 supports upto 3 UARTs. My question is can we expose these UARTs into individual USB ports to the host system?

Thanks, Alexander

2

Not directly, no. You have basically have 4 UARTs on the Mega2560 - one of them (USART0, pins 0&1) is connected to the USB interface chip, and the others are left unassigned for you to use as you like. It's the USB interface chip that is being seen in your computer as /dev/ttyUSB0, not the UARTs in the Mega2560 chip.

That's not to say that what you are after is not possible - it is perfectly possible, but it will require some clever programming on your part. You will need to:

  1. Define a protocol that will multiplex 3 streams of serial data through the one USB serial connection
  2. Write a sketch that works with that protocol to direct the incoming data to the right UART ports and multiplex the UART traffic into the protocol stream you have defined
  3. Write software on your computer to perform a similar task - read in data and multiplex it, and read the multiplexed data stream and split it out to three separate destinations.

What the destinations on the PC end can be is a bit of a wooly area. If you want to make it look like serial ports in /dev then you can use a pty pair, which is a master/slave pair of pseudo TTY devices that you can use to pass data through. On most Linux systems they are numbered devices in /dev/pts, so /dev/pts/1 would be an example.

The function openpty(...) creates and opens a pty pair for you to use in your program. You would do that 3 times to make three pairs and each one would be the endpoint to a sub-stream in your multiplexed data.

For instance, here is a bit of code I use to open a pty pair:

struct termios options;
openpty(&_masterfd, &_slavefd, _dev, NULL, NULL);
fcntl(_masterfd, F_SETFL, 0);
tcgetattr(_masterfd, &_savedOptions);
tcgetattr(_masterfd, &options);
cfmakeraw(&options);
options.c_cflag |= (CLOCAL | CREAD);
if (tcsetattr(_masterfd, TCSANOW, &options) != 0) {
    fprintf(stderr, "Can't set up PTY\n");
}

That makes it appear to almost be a serial connection in style. Of course you don't have the concept of a baud rate over a pty connection, so it will be down to your software to define how you control the baud rate (probably easiest to have it hard coded to the baud rates you need).

In that snippet you talk internally to the _masterfd with normal read() and write() functions as you would any other device or file. Some other piece of software would open the other end of the pty pair (the _slavefd), the name of which is placed in _dev when the pty pair are opened. You could use that _dev name to then create a symbolic link to a better named device instead of using the /dev/pts/x name that could change without warning from one run to the next.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.