Arduino Serial Part 1

Here we look at the various ways of using UART on the Arduino.

Serial UART is one of the various ways an Arduino can communicate with other devices. This includes a host PC and using the Arduino serial monitor is communicating with the PC using serial UART.

If you are very new to Arduino try these simple examples to get you started. If you are already familiar with the serial monitor feel free to jump ahead.

Arduino Serial Monitor

This is a basic example of displaying text in the serial monitor. Connect the Arduino to a PC, upload the following sketch, open the serial monitor and be amazed…

// Basic serial print example. Serial_Example_001
 
void setup() 
{
    Serial.begin(9600);
    Serial.print("Hello World");
}
 
void loop() 
{
}

After uploading the sketch, open the serial monitor. If you see the “Hello World” message you have everything set up correctly.
Arduino_Serial_001

If you do not see the “Hello World” message you need to figure out what is wrong. If you managed to upload the sketch I think we can safely assume the Arduino is connected to the computer. This means it is likely you have the wrong baud rate selected.

Here I have a baud rate of 4800 and also 19200. You can see that I have garbage characters. This kind of output in the serial monitor is indicative of a baud rate mismatch.
Arduino_Serial_002Arduino_Serial_003

If the mismatch is large you may not get anything at all.
Arduino_Serial_004

When using serial communications you need to make sure you are using the same baud rate at both ends. So how do you know what baud rate to use? It is the value you use when you begin the serial channel.

Serial.begin(9600);

This tells the Arduino to open a serial channel at 9600 baud rate.It is actually telling the Arduino to open a hardware serial channel but we will get to that a little later. You then select the same value in the serial monitor.
Arduino_Serial_005

Why 9600? No reason. There are many different rates I could have used. The important thing is to use the same speed at both sides.

End of Line Characters

If you print two strings you will see that they appear together on a single line.

// Basic serial print example. Serial_Example_002
 
void setup() 
{
    Serial.begin(9600);
    Serial.print("Hello World");
    Serial.print("Another string");
}
 
void loop() 
{
}

Arduino_Serial_006
This is because we didn’t tell the serial monitor to start a new line after the “Hello World” message.
There are two line end characters; new line and carriage return. These are non visible, non printable characters that act as controls telling the serial monitor to go to the start of the next line. There are two ways we can add the end of line (EOL) characters
1 – add “\r\n” to what we are printing, or
2 – use Serial.println()

Both produce the same results and Serial.println() simply adds the “\r\n” characters to what it is printing.

// Basic serial print example. Serial_Example_003
 
void setup() 
{
    Serial.begin(9600);
    Serial.println("Hello World");
    Serial.println("Another string");
}
 
void loop() 
{
}

Using Serial.println() the EOL characters are added and the two messages are displayed on separate lines.
Arduino_Serial_007

On a Windows system:
\r (Carriage Return). Moves the cursor to the beginning of the line without advancing to the next line
\n (Line Feed). Moves the cursor down a line without returning to the beginning of the line
\r\n (End Of Line): Combination of \r and \n

 

How fast is serial

Baud rate 9600bps mean 9600 bits per second. The Arduino uses the common 8N1 protocol which uses 10 bits for every character. This means (9600/10) 960 characters per second. This may seen fast but it is actually quite slow. 115200bps or 115200 bits per second is (115200/10) 11520 characters a second, much faster.

How fast can it go? Hardware serial on a 16 MHz Arduino is more than capable of 2,000,000 bps and with special considerations 2,500,000 bps is possible. As the speed gets higher you need to consider the clock speed and the transmission error percentage though. Software serial is very different and is much slower.

What is 8N1

8N1 is one of the more common serial protocols and means; 8 bits, no parity and 1 stop bit. It is slightly misleading as there are actually 10 bits, we also have a start bit. For more details start with the Sparkfun website or simply google it.

 
 
 

Arduino Serial

The Arduino has several implementations of serial UART. Not all are equal.
Hardware Serial/Serial
SoftwareSerial
AltSoftSerial
NeoSWSerial


 
Hardware Serial
Hardware serial, as the name may suggest, is built in to the Arduino hardware which means it has dedicated pins, the ones labelled RX and TX pins (pins 0 and 1). All Arduinos have at least one hardware serial channel.
Serial_Pins_Uno_02_800Serial_Pins_Nano_02_800

Some, like the Mega, have more.
Serial_Pins_Mega_02_800

If the Arduino has a USB connector it is very likely the serial channel is connected to the USB via a a UART to USB adaptor chip. All common Arduinos are like this and this is why you can print to the serial monitor when using usb.

Some Arduinos, or Arduino compatible boards, do not have the UART to USB chip. This means they cannot be directly connected to a PC and need an adaptor.
Serial_Pins_MiniPro_02_800
The Mini Pro has the serial pins but no USB connector.

Hardware serial has the best performance and is the most robust and reliable. This is always the best solution when available but it does have a caveat. The Arduino IDE uses the hardware serial to upload to the Arduino so when uploading new sketches you may need to disconnect what ever is connected to the RX and TX pins.

Hardware serial can:
– transmit and receive at the same time
– work while the Arduino is performing other tasks
– handle fast baud rates

Some Arduinos, such as the Mega and the Due, have more than 1 hardware serial. ATMega328 based Arduino have just one.

Hardware serial is integrated in to the IDE and adding a library is not required, all you need to do to initiate a serial connection is use the serial.begin() command.

void setup() 
{
    Serial.begin(115200);  
    // 115200 is the serial port baud rate
    // remember to select the same baud rate in the serial monitor
 
    // wait for the serial port to connect.
    while (!Serial) {  ;  }
    Serial.println("Hello World");
}
 
void loop() 
{
}

If this is new to you see the examples above.

Hardware Serial links
Arduino reference

 
The rest of the serial implementations are what they call software implementations. This means all the work is done in code which has benefits and drawbacks. If you want to try out any of the software based serials you will need a usb to serial adapter. See the examples below.

UART_Adapters_001_800Various UART adapters.

 

 
SoftwareSerial
Software Serial is a library that is part of the standard Arduino IDE. To use it you need to add the library to the sketch and them tell it the pins you want to use. Here it is being initialised with pins 2 and 3. Pin 2 for recieve and pin 3 for transmit.

// Add the SoftwareSerial library
#include <SoftwareSerial.h>
 
// Initiate an instance of the SoftwareSerial class. Requires the pin numbers used for RX and TX.
SoftwareSerial swSerial(2, 3); // RX, TX

Since SoftwareSerial comes with the IDE and because it can use most of the Arduino pins it is a very convenient solution but does have drawbacks. It is not reliable at very slow or very fast speeds and because of how it works it can cause problems with timings.

SoftwareSerial uses pin-change interrupts when receiving data, and both receive and transmit use delay loops, and while it is delaying, interrupts are disabled. This means it blocks the sketch. The code simply sits and waits for SoftwareSerial to finish before it can do anything else.
Because interrupts are disabled, SoftwareSerial interferes with anything that uses interrupts.

SoftwareSerial:
– comes with the Arduino IDE as standard.
– can be used with almost all pins (see below)
– can not transmit and receive at the same time
– can have multiple instances but only one instance can be active at one time
– not very good at very slow or fast baud rates. The baud rate should be kept in the range 9600 – 38400
– requires a library which comes with the Arduino IDE by default

// Add the SoftwareSerial library
#include <SoftwareSerial.h>
 
// Initiate an instance of the SoftwareSerial class. Requires the pin numbers used for RX and TX.
SoftwareSerial swSerial(2, 3); // RX, TX
 
void setup() 
{
    // Start the connection and set the baud rate
    swSerial.begin(9600);
    swSerial.println("Hello, world!");
}
 
void loop() 
{ 
}

Try using softwareSerial with different baud rates. What is the fastest you can get reliable communication? In my own experiments 38400 is the fastest I been able to get 100% error free communication and this was only when the Arduino wasn’t doing much else. After 38400 I start to see errors.

SoftwareSerial is convenient and is fairly flexible but it is not the best software serial choice.


 
AltSoftSerial
AltSoftSerial was written by Paul Stoffregen the creator of the Teensy range of boards. It is the best software serial implementation and should be used instead of the default SoftwareSerial where possible.

The AltSoftSerial library is available from the PJRC website or through the library manager. AltSoftSerial takes a different approach over the regular SoftwareSerial library. The pins it uses are fixed, pin 8 for receive, pin 9 for transmit (regular Arduinos only), and uses the 16 bit timer which means PWM on pin 10 becomes disabled.

AltSoftSerial:
– Can transmit and receive at the same time.
– Minimal interference when also using the Hardware Serial and other libraries
– More reliable at higher speeds than the other software serials
– Fixed pins: pin 8 for receive, pin 9 for transmit (regular Arduinos only*)
– Disables PWM on pin 10
– Uses the hardware Timer1 (16 bit) and will not work with other libraries that also need the same timer

*Check the PJRC website for the pins used other types of Arduinos.

// Add the AltSoftSerial library
#include <AltSoftSerial.h>
 
// Initiate an instance of the altSerial class
// On ATmega 328 based Arduinos AltSoftSerial uses pin 8 for RX and pin 9 for TX
AltSoftSerial altSerial;
 
void setup() 
{
    altSerial.begin(9600);
    altSerial.println("Hello World");
}
 
void loop() 
{
}


 
NeoSWSerial
NeoSWSerial was written by Slash Devin and it is the next best choice or at least better than the standard SoftwareSerial library. Like SoftwareSerial it can use most of the regular pins but has a limited range of baud rates, 9600 (default), 19200, 31250 (MIDI) and 38400 only. This isn’t really an issue though. The regular software serial has issues when used below 9600 and above 38400 so slower than 9600 and faster then 38400 shouldn’t be used.

NeoSWSerial:
– Can be used with most pins.
– Can receive and transmit at the same time.
– More friendly to interrupts on RX than SoftwareSerial
– Limited range of baud rates; 9600 (default), 19200, 31250 (MIDI) and 38400 only

Requires a library which can be downloaded from github or added through the library manager.

// Add the NeoSWSerial library
#include <NeoSWSerial.h>
 
// initiate an instance of the NeoSWSerial class. Requires the pin numbers used for RX and TX.
// neoSerial( RX pin, TX pin )
NeoSWSerial neoSerial( 2, 3 );
 
void setup() 
{
  neoSerial.begin(9600);
  neoSerial.println("Hello World");
}
 
void loop() 
{
}

 

So which one should I use?

Depends on what you are doing and how fast you want to do it. If you have to use a fast baud rate (such as 115200 or even 2,000,000) then the only option is the hardware serial. Software versions cannot handle these speeds.

If you do not need super fast rates and you have pins 8 and 9 available then AltSoftSerial is for you. Don’t have pins 8 or 9 and you are OK with one of the available baud rates then NeoSWSerial. If none of these work you are left with SoftwareSerial.

If you need more than one fast serial connection then you need an Arduino with more than one serial channel such as the Mega.

 

Using a software UART and usb adapter to talk to a PC

I think most people will have used the hardware serial to communicate with a connected PC using the serial monitor. If not see the examples above. Sometimes though it is useful to have another connection and we can do this using one of the software serials and a usb to serial adapter. Here I am using AltSoftSerial.

Simple circuit. The Arduino is connected to a PC using the standard USB connection and also by a usb to serial adapter. The usb to serial adapter is connected to pins 8 and 9 of the Arduino and AltSoftSerial is used to communicate over the usb to serial adapter. Power is delivered through usb. GNDs are connected.

Having two connections to the same PC gives you 2 COM ports; one for the Arduino and one for the adapter. In the example below the Arduino is on COM 6 and the usb adapter is on COM 16.

Arduino_Serial_010_circuit_800

Arduino_Serial_016_800

// basicSerialPassThru_AltSoftSerial_001
 
#include <AltSoftSerial.h>
AltSoftSerial softSerial; 
 
char c=' ';
 
void setup() 
{
    Serial.begin(9600);
    Serial.print("Sketch:   ");   Serial.println(__FILE__);
    softSerial.begin(9600);  
    Serial.println("AltSoftSerial started at 9600");
}
 
void loop()
{
 
    // Read from the software serial and send to the hardware seral
    if (softSerial.available())
    {
        c = softSerial.read();
        Serial.write(c);
    }
 
    // Read from hardware serial and send to software serial
    if ( Serial.available() )
    {
        c = Serial.read();
        softSerial.write(c);  
    } 
}

Plug everything in, upload the sketch and try it out.

If you have the correct drivers installed for the usb to serial adapter you will have 2 COM ports; 1 for the Arduino, and 1 for the adapter. If you now open 2 serial monitors you can talk to yourself.

Arduino_Serial_011
Arduino_Serial_012
Arduino_Serial_013
Arduino_Serial_014
Arduino_Serial_015

At first this may appear to be of no use but using the usb to serial adapter can be very useful for debugging when the hardware serial is used for other things. You should also be able to see that the usb to serial adapter can be replaced with any device that talks UART and there are many, including all the Bluetooth modules I have written about on the rest of this website. It also forms an easy way to get 2 Arduinos talking to each other. One example that I am currently working on is an IOT Wordclock. The Word clock uses an Arduino and an ESP8266. The Arduino does most of the work and the ESP8266 takes care of the wifi stuff like the control webpage and getting the time from a NIST server. The two talk to each other through a UART connection using software serial.

Here is an example of linking two Arduinos together using AltSoftSerial. Both Arduinos have the basicSerialPassThru_AltSoftSerial_001 sketch.

Remember that RX on one side goes to TX on the other side

Arduino_Serial_020_640

Arduino_Serial_025_800

Arduino_Serial_022
Arduino_Serial_023

 

basicSerialPassThru_AltSoftSerial_001 sketch

// basicSerialPassThru_AltSoftSerial_001
 
#include <AltSoftSerial.h>
AltSoftSerial softSerial; 
 
char c=' ';
 
void setup() 
{
    Serial.begin(9600);
    Serial.print("Sketch:   ");   Serial.println(__FILE__);
    softSerial.begin(9600);  
    Serial.println("AltSoftSerial started at 9600");
}
 
void loop()
{
 
    // Read from the software serial and send to the hardware serial
    if (softSerial.available())
    {
        c = softSerial.read();
        Serial.write(c);
    }
 
    // Read from hardware serial and send to software serial
    if ( Serial.available() )
    {
        c = Serial.read();
        softSerial.write(c);  
    } 
}

I have used this sketch (or a version of it) many times throughout the website. It is the sketch I use when I am experimenting with Bluetooth modules (or anything that uses UART).

The sketch is very simple. It first initialises the hardware serial and soft serial and then prints a welcome message to the serial monitor (using the hardware serial channel).

void setup() 
{
    Serial.begin(9600);
    Serial.print("Sketch:   ");   Serial.println(__FILE__);
    softSerial.begin(9600);  
    Serial.println("AltSoftSerial started at 9600");
}

Of course, before we can initiate AltSoftSerial we need to tell the compiler to load the library

#include <AltSoftSerial.h>
AltSoftSerial softSerial;

Inside the main loop we check to see if there are any characters available on the software serial channel and if there are we read the first one and write it to the hardware serial channel. This prints it in the serial monitor.

// Read from the software serial and send to the hardware serial
if (softSerial.available())
{
    c = softSerial.read();
    Serial.write(c);
}

It then checks the hardware serial. If data is available it reads the first character and sends it to the saftware serial channel. You should notice that nothing is sent to the serial monitor. You could, if you wish, echo what ever is entered in the serial monitor back to itself.

void loop()
{
// Read from hardware serial and send to software serial
if ( Serial.available() )
{
    c = Serial.read();
    softSerial.write(c);  
}

Although only one character is read at a time because the main loop is constantly looping we eventually get all available characters.

 
All this well and good but we haven’t yet discussed getting two things talking to each other. That comes in part 2.

 
 

One thought on “Arduino Serial Part 1

Leave a Reply

Your email address will not be published. Required fields are marked *


seven − 1 =

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>