Introduction: Serial Port Options and Sample Programs

About: I have developed training courses for research companies during an interesting career. My computer book was published by Prentice Hall. Now, I'm sharing my hardware projects, some of which were aided by other …

This instructable answers the questions I had when developing projects that require serial communications between my computer and an Arduino device such as an Uno, Nano, Mega, or Due. The photo on above, on the right, is my Altair101a that simulates an Altair8800. I use the default serial port to display a virtual front panel, run the simulator from command line, and to display log messages. The second hardware serial port is used to upload machine code program to the simulator. The simulator then runs the program. Serial communications are key for the simulator.

The above photo (left) shows a Mega with physical serial connections:

  • RX/TX pins of the Mega are wired to the USB module that is plugged into a USB hub that is plugged into my laptop computer.
  • The other serial connection is through the USB cable that is connected to the Mega and to the USB hub.

The 2 physical connections are the 2 serial connections between the Mega and the laptop.

This instructable goes over 3 USB serial connection types:

  • The default Arduino serial port, serial port 0, which uses the Arduino hardware USB port connection. The connection is through the USB cable between the computer and the Arduino board.
  • Using a serial software library to create a serial connection through a USB module that is plugged into the computer or into a computer's USB hub. The USB module is wire connected to pins on the Arduino board.
  • Hardware USB port connection on a Mega or Due, serial port 1, 2, or 3. The physical connection is through a USB module that is plugged into the computer or into the computer's USB hub. The module is wired to TX(transmit) and RX(receive) pins on the Arduino board.

Arduino hardware serial communications is managed by a hardware UART on the Arduino board. Or, using a serial software library that controls serial communications on the Arduino board (digital pins) through a USB serial module that is plugged into the computer or the computer's USB hub.

For reference, Arduino Serial Communication documentation link.

Supplies

  • Arduino Uno or Nano ATmega328P microcontroller board with a USB cable to connect to your computer. This board will work for the steps that only require the default UART and the SoftwareSerial library.

  • Arduino ATmega2560 (Mega) or Due microcontroller board with a USB cable to connect to your computer.This will work for the steps that require the default UART and a second UART that is built into the board. The Mega and Due have 4 built in UARTs.

  • USB UART Module. I'm using a CH340G 3.3/5V Serial Converter. You can use a CP2102 USB module. Then, match the module (CH340G or CP2101) driver that you will install on your computer. I use CH340G because I already had driver installed for iCH340G. I've used both types, both work fine as long as the correct driver is installed.

I bought the parts on eBay, from Hong Kong or China distributors. US distributors may have the same or similar parts for reasonable prices and faster delivery. For a good price on USB UART modules, I included "2pcs" in the search, and bought a pair. Always nice to have a spare.

Approximately $15 for a Mega, and $5 or less for a Nano. $2 or less for a USB UART module.

Step 1: Using the Arduino Default Hardware Serial Port

The default Arduino hardware serial communications is managed by a UART on the Arduino boards. The communication is serial over a USB connection between the Arduino and the other device such as a laptop. The main usage is uploading programs, from the software development computer running the Arduino IDE, to the Arduino. The compiled machine byte code is upload over the serial port.

The other purpose for Arduino serial communications is for displaying program log messages on the development computer. The simplest tool to display the messages is the IDE monitor. Since serial communications is bidirectional, bytes (characters) can be sent from the IDE monitor to the Arduino.

Download and run the program: serialPort0.ino.

Monitoring the Default Serial Port Log Messages

View the available serial ports from the Arduino IDE, select Tools/Port. My Uno serial port shows as following. Select that port for use by the Arduino IDE Serial Monitor.

/dev/cu.usbmodem1421 (Arduino Uno)

To view the program log messages, from the Arduino IDE menu select Tools/Serial Monitor. Set the baud rate to 9600, which matches the setting in the program. The monitor program starts and displays the following messages. Close the monitor program. Re-open the monitor program, and the serialPorts0.ino program will re-run.

Note, each time the Arduino IDE monitor program starts, it re-runs the installed program.

+++ Setup: Ready for serial communications.
+ Go to loop.
++ Send characters using a serial program such as the Arduino IDE monitor program.
+

In the top bar of the Arduino IDE Serial Monitor program, enter "abc" and click the Send button. Do the same, and send "yes" and "okay". You will see each string echoed as follows.

+ abc
+ yes
+ okay
+

Here is the flow from the terminal window to the IDE serial monitor window:

IN: IDE serial monitor window >> USB serial module >> Arduino program
OUT: Arduino program >> Arduino UART Serial >> Computer IDE serial monitor

In summary, when you open a serial connection on the default port, the microcontroller resets and re-runs the installed program's Setup section and then goes into the Loop section.

Reference, Arduino Serial Communication link.

Step 2: Using a Secondary Software Serial Port

Since connecting to serial port 0 causes the program to restart, I needed a second serial port to be able to connect and re-connect to a serial port without restarting the installed program. So I bought a USB serial port module to use as a second port. Since an Uno only has one hardware serial UART port, I use a software library to manage serial communications from 2 of the Uno digital pins.

To use the USB serial port module, wire it to the Arduino board:

  • Serial module RX pin to Arduino TX pin, pin 11.
  • Serial module TX pin to Arduino RX pin, pin 12.
  • Serial module 5V to Arduino 5V.
  • Serial module GND to Arudino GND.

The Arduino pin numbers are configured in the SoftwareSerial library, and are used in the program. Following are the program lines that initialize the serial port.

#include <SoftwareSerial.h>
const int PIN_RX = 12;  // Arduino receive  pin (12) is connected to TXD pin on the serial module.
const int PIN_TX = 11;  // Arduino transmit pin (11) is connected to RXD pin on the serial module.
SoftwareSerial SerialSw(PIN_RX, PIN_TX);

Download and run the program: serialPortSw.ino.

Monitoring the Default Serial Port Log Messages

View the available serial ports from the Arduino IDE, select Tools/Port. My Uno serial port shows as following. Select the Arduino Uno port for use by the Arduino IDE Serial Monitor. This is the default serial port.

/dev/cu.usbmodem1421 (Arduino Uno)
/dev/cu.wchusbserial14220

To view the program log messages, from the Arduino IDE menu, select Tools/Serial Monitor. Set the baud rate to 9600, which matches the setting in the program.

Note, since the second serial port is software controlled instead of hardware controlled, it's suggested not use baud rates above 38,400.

The IDE monitor program starts and displays the following messages.

+++ Setup
+ Ready to use port 0 serial port with the Arduino Serial Monitor.
+ SerialSw is listening.
+ Ready to use the second serial port.
+ Go to loop.
++ Send characters using the Arduino Serial Monitor.
+ Port 0:

Use the IDE Serial Monitor to send strings such as "abc", then "def". Note, the IDE Serial Monitor includes a line feed (LF) character when it send the string.

+ Port Serial: abc
+ Port Serial: def
+ Port Serial:

Using the Second Serial Port, the Software Serial Port

List the serial ports on your computer and select the second port. Following is my sample second port.

/dev/cu.wchusbserial14220

If the IDE Serial Monitor is already open, it will refresh using the new port. Else, open the IDE Serial Monitor. Once opened, click the IDE Serial Monitor Send button, and the following prompt is displayed.

+ Port SerialSw:

Enter "a" and then click the Send button. The "a" is displayed and the a new prompt message is displayed followed by an unknown character. The reason is that the sending doesn't send a 9600 baud, it simply dumps to the port. Since the receiver (the Arduino software serial port) only receives at 9600 baud, any following characters are not correct.

Click the Send button to go to the next line. The prompt is printed. Then enter "bc" and click the Send button. Click the Send button to go to the next line. The prompt is printed.

The following is displayed.

+ Port SerialSw: a?
+ Port SerialSw: b??
+ Port SerialSw:

The Arduino program echos the characters it receives. For the line feed character (LF), a new line is printed and the prompt is printed.

Terminal Connection to the Second Serial Port

Following is how I list my ports in a Mac terminal window. You can use the same commands on a Linux computer. I used the screen command to connect the second port. The screen command uses 9600 baud rate by default.

$ ls /dev/tty.*
/dev/tty.Bluetooth-Incoming-Port /dev/tty.usbmodem14241 /dev/tty.wchusbserial14220
$ screen /dev/tty.wchusbserial14220

Note, if using a baud rate other than 9600 in the program, add the baud rate to the screen command. For example:

$ screen /dev/tty.wchusbserial14220 115200

Once connected, hit the enter key and the following prompt is displayed. Side note, the terminal window sends a carriage return (CR) where as the IDE sends a line feed (LF/newline) character.

+ Port SerialSw:

Enter "a" and the a is immediately displayed back to the terminal window. This is because the terminal window sends every character entered directly to the serial port. Hit the Enter key and new line is started with the prompt. Continue entering strings to test.

The characters are echoed in both the default port window (IDE monitor) and second serial port window (terminal window). The characters come on the second port and are sent out on 2 ports. Here is the flow from the terminal window to the IDE serial monitor window:

IN: Computer terminal >> USB serial module >> Arduino SoftwareSerial >> Arduino program 
OUT 1: Arduino program >> Arduino SoftwareSerial >> Computer terminal
OUT 2: Arduino program >> Arduino UART Serial >> Computer IDE serial monitor

Note, if you copy and paste a string with multiple characters, the characters after the first one will not print properly because the sending doesn't send a 9600 baud, it simply dumps to the port.

If the terminal serial connection get shutdown, use the reset command to reset the terminal to print to the window properly.

$ reset
...

End of step.

Step 3: Using a Secondary Hardware Serial Port

Having multiple UARTs on a board is convenient because it allows the default port to be used for log messages and serial interactions with the program that is running. The second port can be used for uploads: connect, send bytes, then disconnect. At a later time re-connect, do another upload, then disconnect. The second port is great for interactions with the running program because it don't cause a re-boot. Each time a connection is made to the default serial port, the program is re-started (setup() and loop()). The reason for the re-start is that the default port is used to upload new programs. After the new program bytes are uploaded, the new program is run: setup() then loop().

The Mega and Due boards have 4 UART hardware serial ports:

  • Serial (default), the USB to computer connection. On the Due, I use the programming USB connector.
  • Serial1, pins: RX:19, TX:18
  • Serial2, pins: RX:17, TX:16
  • Serial3, pins: RX:15, TX:14

For this step, wire the serial module to the Mega Serial2 UART pins. Serial2 is used in the sample program.

  • Serial module RX to Mega TX pin 16.
  • Serial module TX to Mega RX pin 17.
  • Serial module 5V to Mega 5V.
  • Serial module GND to Mega GND.

Arduino Serial documentation reference link.

Download and run the program: serialPort2Hw.ino.

Monitoring the Default Serial Port Log Messages

View the available serial ports from the Arduino IDE, select Tools/Port. My Mega serial ports are shown as following. Note, the Bluetooth port is listed, but it's not from the Arduino board, it just happens to show based on the list parameters used by the IDE to list ports.

/dev/cu.Bluetooth-Incoming-Port
/dev/cu.wchusbserial14210
/dev/cu.wchusbserial14220

Select the first non-Bluetooth serial port which is the default serial port that will be used with the Arduino IDE Serial Monitor. Open the Arduino IDE Serial Monitor. Set the baud rate to 9600, which matches the setting in the program. The following log messages are displayed from the Serial port.

Note, since the second serial port is hardware controlled, you can use baud rates up to 115,200 bps. I most often use 115,200 in my projects. I'm using 9600 baud in this instructable for consistency and that it is a default.

+++ Setup
+ Ready to use port 0 serial port with the Arduino Serial Monitor.<br>+ SerialHw on the second port is listening.<br>+ Ready to use the second serial port.<br>+ Go to loop.<br>++ Send characters using the Arduino Serial Monitor.<br>+ Port 0: <br>

You can send strings which are echoed in the monitor window. For example:

+ Port Serial: abc
+ Port Serial: def
+ Port Serial: okay
+ Port Serial:

Using the Second Port, the Hardware Serial Port #2

In the IDE, list the serial ports on your computer (Tools/Port) and select the second port. Following is my sample second port.

/dev/cu.wchusbserial14220 

If the IDE Serial Monitor is already open, it will refresh using the new port. Else, open the IDE Serial Monitor. Once opened, click the IDE Serial Monitor Send button, and the following prompt is displayed.

+ Port Serial2:

Enter "a" and then click the Send button. The "a" is displayed and the a new prompt message is displayed. Then enter "bc" and click the Send button. The following is displayed in the same window.

+ Port Serial2: a
+ Port Serial2: bc
+ Port Serial2: 

The Arduino program echos the characters it receives. For the line feed character (LF) or a carriage return (CR), a new line is printed and the prompt is printed.

Note, when using the hardware serial port, multiple characters are received and printed correctly.

Terminal Connection to the Second Serial Port

Set the IDE back to the default port, list the serial ports on your computer (Tools/Port) and select the first serial port.

+++ Setup
+ Ready to use port 0 serial port with the Arduino Serial Monitor.
+ SerialHw on the second port is listening.<br>+ Ready to use the second serial port.<br>+ Go to loop.<br>++ Send characters using the Arduino Serial Monitor.<br>+ Port 0:<br>

List the serial ports on your computer. Following is how I list my ports in a Mac terminal window. You can use the same commands on a Linux computer.

$ ls /dev/tty.*
/dev/tty.Bluetooth-Incoming-Port /dev/tty.wchusbserial14210 /dev/tty.wchusbserial14220

Connect to the second port. I use the screen command to connect the second port. The screen command uses 9600 baud rate by default.

$ screen /dev/tty.wchusbserial14220

On a Windows computer you can view the ports from the Arduino IDE (Tools/Port). Then connect to the port using Putty or another serial terminal program.

When entering strings, the characters are echoed in both the default port window (IDE monitor) and second serial port window (terminal window). The characters come on the second port and are sent out on 2 ports. Here is the flow from the terminal window to the IDE serial monitor window:

Computer terminal >> USB serial module >> Arduino UART Serial2 >> Arduino program
Arduino program >> Arduino UART Serial >> Computer IDE serial monitor<br>

For example, the following were echoed in the terminal widow and in the default window:

+ Port Serial2: ghi
+ Port Serial2: jkl
+ Port Serial2: yes
+ Port Serial2:

End of step.

Step 4: Processing Serial Port Bytes

In this step, characters are received and printed in a table format. Download and run the program: serialPort0process.ino. This program demonstrate the receiving of each byte and displaying them.

Send the following string, "abc def +-...", from the IDE Serial Monitor. The following is displayed.

+++ Setup: Ready for serial communications.
+ Go to loop.
+   Char  ASCII  Binary    Octal
++   a     97    01100001  141
++   b     98    01100010  142
++   c     99    01100011  143
++  ' '    32    00100000  040
++   d    100    01100100  144
++   e    101    01100101  145
++   f    102    01100110  146
++  ' '    32    00100000  040
++   +     43    00101011  053
++   -     45    00101101  055
++   .     46    00101110  056
++   .     46    00101110  056
++   .     46    00101110  056
++  <LF>   10    00001010  012

Close the monitor window. Open a terminal window and connect to the default serial port.

$ screen /dev/tty.wchusbserial14210
...
+++ Setup: Ready for serial communications.
+ Go to loop.
+   Char  ASCII  Binary    Octal

Enter "abc". Then, hit the enter key.

+   Char  ASCII  Binary    Octal
++   a     97    01100001  141
++   b     98    01100010  142
++   c     99    01100011  143
++  <CR>   13    00001101  015

Using a Serial Port Java Program to Upload Bytes

This part requires that you have the Java JRE install on your computer. You can check by using the following java command from a terminal window whether in Windows, Mac OS, or Linux.

$ java -version
java version "15.0.2" 2021-01-19
Java(TM) SE Runtime Environment (build 15.0.2+7-27)
Java HotSpot(TM) 64-Bit Server VM (build 15.0.2+7-27, mixed mode, sharing)
$

If you do have Java install and want to test with my upload program, download: asm.jar. I use the program to upload file bytes over a serial port to a Arduino board that is running my Altair 8800 simulator program. For this exercise, download and run the program from a previous step. If you have 2 hardware UARTS, use serialPort2Hw.ino. Else use the SoftwareSerial library program, serialPortSw.ino. I have already tested sending text from the laptop to the Arduino using both of the mentioned programs. The upload work fine to a hardware port and to a software serial port.

Once you have your Arduino program running, do the following: create test text file that will be uploaded: test.txt. In the following code block, I used the cat command to list my test text file contents. Suggestion, leave the first line blank, as it prints nicer when uploaded.

$ cat test.txt

2c3
line 2

In the same directory as text.txt, run the asm.jar program. The program is cross assembler that generates machine code. This exercise only needs to the upload part of the program.

$ java -jar asm.jar
+++ Start 8080/8085 assembler, version 0.96a
+ Assembler opcode file: asmOpcodes.txt
+ Number of opcode byte values = 271
+ Assembler opcode file: asmOpcodes.txt
+ Number of opcode byte values = 271
+ Enter 'exit' to exit. 'help' to get a command listing.

In the following, run the commands where prompted by, ">". For example, list ports will list the available serial ports. Use, set port, to set to your actual port. Then set the baud rate to 9600. Set to use your test.txt file. Then, upload the file.

$ java -jar asm.jar
> list ports
+ -------------------------------------
+ Serial port name set to: /dev/tty.wchusbserial14220
+ List of available serial ports:
++ cu.Bluetooth-Incoming-Port : Bluetooth-Incoming-Port BaudRate:9600 Data Bits:8 Stop Bits:1 Parity:0
++ tty.Bluetooth-Incoming-Port : Bluetooth-Incoming-Port (Dial-In) BaudRate:9600 Data Bits:8 Stop Bits:1 Parity:0
++ cu.wchusbserial14210 : USB2.0-Serial BaudRate:9600 Data Bits:8 Stop Bits:1 Parity:0
++ tty.wchusbserial14210 : USB2.0-Serial (Dial-In) BaudRate:9600 Data Bits:8 Stop Bits:1 Parity:0
++ cu.wchusbserial14220 : USB2.0-Serial BaudRate:9600 Data Bits:8 Stop Bits:1 Parity:0
++ tty.wchusbserial14220 : USB2.0-Serial (Dial-In) BaudRate:9600 Data Bits:8 Stop Bits:1 Parity:0
+ End of list.

> set port tty.wchusbserial14220
+ Set the serial port name: tty.wchusbserial14220
+ Serial port set to: tty.wchusbserial14220
+ Serial port set to system name: /dev/tty.wchusbserial14220

> set baud 9600
+ Set upload baud rate to: 9600

> set byte test.txt

> upload
+ -------------------------------------
+ Write to the serial port, the program file: test.txt:
+ Serial port is open.
++ Load the program binary file: test.txt
+ Write to serial port. Number of bytes: 12 in the file: test.txt
00001010 00110010 01100011 00110011 00001010 01101100 01101001 01101110 01100101 00100000
00110010 00001010
+ Serial port is closed.
+ Write completed.
>

In the Arduino IDE Serial monitor window, the following is displayed.

+ Port Serial2:
+ Port Serial2: 2c3
+ Port Serial2: line 2
+ Port Serial2: 

The text.txt file contents were upload one byte at a time.

Here is the flow from the terminal window to the IDE serial monitor window:

IN: File >> Java program >> USB serial module >> Arduino UART Serial2 >> Arduino program
OUT: Arduino program >> Arduino UART Serial >> Computer IDE serial monitor

For reference, asmUpload.java, is the Java upload program.

Step 5: Summary

The serial protocol is useful for many projects and essential when debugging a new program. This instructable covered how to use the default serial port, and how to add and use a second serial port. The same techniques can be used if more than 2 serial ports are needed in your project. Also, when communicating between multiple Arduino boards, serial communications is an option.

At first, I had only used serial for program log messages. Now, it's my key protocal between my laptop and my Altair 8800 simulator that I'm running on a Mega. My simulator hardware is pictured in the above photo: Mega, USB cable to USB hub; Micro SD card reader; USB serial module. The USB hub is connected to my laptop. When the simulator program starts up, I can interact with it through the default serial port. I write assembler programs on my laptop, assemble them into machine code which is uploaded using the Java program in the previous step of this instructable.

I also can use the second serial port to interact with my assembled programs that are running on the simulator. The default serial port is for monitoring and logging messages. The second serial port is for sending commands to programs running on the simulator and receiving responses from the assembled program.

Below, is the virutal Altair 8800 front panel that is displayed in a VT100 terminal using the screen program on my Mac laptop. The same screen program was used in this instructable steps. For example, if I press the 8 key on the laptop, 8 is sent through the serial port to the Arduino simulator program. The program flips the S8 switch, on: ^ or off: v. The "^" or "v" is sent back from the program, through the serial port, to the terminal which displays the result in the window.

INTE MEMR INP M1 OUT HLTA STACK WO INT        D7  D6   D5  D4  D3   D2  D1  D0<br> .    *    .  *   .   .    .    *   .         .   .    *   *   .    .   .   *
WAIT HLDA   A15 A14 A13 A12 A11 A10  A9  A8   A7  A6   A5  A4  A3   A2  A1  A0
 *    .      .   .   .   .   .   *   .   *    .   .    .   .   .    .   .   .
            S15 S14 S13 S12 S11 S10  S9  S8   S7  S6   S5  S4  S3   S2  S1  S0
             v   v   v   v   v   ^   v   ^    v   v    v   v   v    v   v   v
 ------ 
+ Ready to receive command.
+ x, EXAMINE: 1280

For your reference, here is the link to the NetBeans Java project: asm, which has the upload program. I plan on doing an instructable for my Altair 8800 simulator when time permits.

Cheers,

Stacy David