Here we look at using serial communication 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.

INDEX

Arduino Serial Monitor
End Of Line Characters
Formatting output using the tab command
How fast is serial
Different Arduino Serials
   Hardware Serial/Serial
   SoftwareSerial
   AltSoftSerial
   NeoSWSerial
Using a software UART and usb adapter to talk to a PC
Buffer Size
Serial Commands

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
// Example 1

void setup() {     
    Serial.begin(9600);     
    Serial.print("Hello World"); 
}

void loop() {
}
Arduino_Serial_001

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

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.

Arduino_Serial_002
Arduino_Serial_003

Here a baud rate of 4800 and also 19200 has been set. You can see that garbage characters arise. This kind of output in the serial monitor is indicative of a baud rate mismatch.
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);
Arduino_Serial_005

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.

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
// Example 2

void setup()  {     
    Serial.begin(9600);     
    Serial.print("Hello World");     
    Serial.print("Another string"); 
}

void loop()  {
//empty 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
// Example 3

void setup()  {     
    Serial.begin(9600);     
    Serial.println("Hello World");     
    Serial.println("Another string");
}   
void loop()  {
// empty loop
}
Arduino_Serial_007

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

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

Serial monitor: Formatting output using the tab command

For quick and easy formatting spaces can be used but the output can become messy when the data has variable lengths. A better solution is the tab command “\t”. This works in exactly the same was as tab works in a word processor; it moves the cursor over to the next column and lines up the output.

Protected Area

This content is password-protected. Please verify with a password to unlock the content.

Arduino_Serial_025_800

Protected Area

This content is password-protected. Please verify with a password to unlock the content.

Serial Commands

If you look at the Arduino reference for serial you will see that serial has the following commands available:

begin()
end()
If (Serial)
print()
println()
write()
availableForWrite()
read()
readBytes()
readBytesUntil()
available()
setTimeout()
find()
findUntil()
parseFloat()
parseInt()
peek()
flush()
serialEvent()

It is very possible to produce very complex serial sketches and not use the majority of the serial commands. I have used about 5 of the above commands only. Commands like find() and findUntil(), I prefer to create my own routines that perform similar functions but without blindly deleting data (more below). Having said that I do feel it is useful to have an understanding of the commands and how they work.

 
begin(baudRate)
You have already seen above, begin() is used to start or enable serial. Serial doesn’t work unless you initiate it. The program will compile OK but nothing will be sent out over serial. Remember to use the same baud rate at both ends.

Serial.end();

end()
end() closes or disables serial. For hardware serial this is not normally required but can be used if you ever need to use the RX and TX pins for other things after using serial. The serial RX and TX pins, Pins D0 and D1, can be used as regular pins when not using serial. I can’t think of a reason why you would want to do this though. If you need to use pins 0 and 1 then you are highly unlikely to use them for serial communication.

end() can be useful when using software serial. You can implement more than one software serial but can use only one channel at a time. This means you need to open and close channels as you want to use them.

// wait for the serial port to connect
    while (!Serial) {
        ;
    }

If (Serial)
Checks to see if serial communication is available but take care, on most Arduinos Serial always returns TRUE even if you have not initiated the serial channel.
This command is only useful when used for the Leonardo (which has a usb CDC connection) and works as you may expect; TRUE when serial is available and FALSE when it is not. It does not work with Serial1 on the Leonardo which always returns TRUE. In the examples above you may have noticed

// Serial_Example 003 print v write
void setup() {
    Serial.begin(9600);
    Serial.println(123);
    Serial.write(123);
}

void loop()  { }

This is just for the Leonardo and waits for serial to be available before continuing..

print(), println() and write()
I have already mentioned the difference between print() and println(). println() adds carriage return and new line characters (\r\n) and print() does not. But what does print() and println() actually do and how are they different to write()?

According to the Arduino reference
Serial.write() writes binary data to the serial port.
Serial.print() prints data to the serial port as human-readable ASCII text.
This sounds fairly straight forward but there is more to it that that and isn’t all data binary anyway.

print() and write() may at first seem to be the same but there are some key differences. print() and println() convert all numeric values to human-readable ASCII text. write() doesn’t convert anything. It simply sends what you give it. This makes write() more efficient and faster than print/println().

What is the difference between binary and human-readable ASCII text? It is the difference between the value 1 and the character that represents a 1. IE ASCII 48 which is “1”.

Serial.print(123); displays “123” in the serial monitor (3 characters). The value 123 is converted to the ASCII characters “1” + “2” + “3”. Serial.write(123) sends a single byte with the value of 123. (123 is the ascii code for the “{” character so Serial.write(123) displays a “{” in the serial monitor). This seems straight forward but Serial.write() can handle strings. Serial.write(“123”) sends the ASCII characters “1” + “2” + “3”, this is because you are giving a string to the write command not a value. Sometimes it is easy to mix up string representations of numbers and actual values. “1” and 1 are not the same.

void setup() {
    Serial.begin(9600);
// wait for the serial port to connect. Required for Leonardo native USB port only
    while (!Serial) {
        ;
    }
int value = 65;
    Serial.println(value); // print as an ASCII-encoded decimal
    Serial.println(value, DEC); // print as an ASCII-encoded decimal
    Serial.println(value, HEX);  // print as an ASCII-encoded hexadecimal
    Serial.println(value, OCT);  // print as an ASCII-encoded octal
    Serial.println(value, BIN);  // print as an ASCII-encoded binary
}

void loop()  { }
ArduinoSerial_020_printVwrite

If you are not familiar with the ASCII table it is worth looking up. A good place to start is www.asciitable.com.

As you can see there is some overlap between Serial.print() and Serial.write. For example; Serial.print(“HELLO”) and Serial.write(“HELLO”) results in the same thing, “HELLO”. There are differences though, they handle numbers differently, print() can handle more data types, and has a built in base convertor.

Serial.print() can be used to display values in different base formats. For example as Hexadecimal or binary.

float f = 3.1234;
Serial.print(f);
Arduino_Serial_008

What happens if you use Serial.write(value);? I will leave this to you to find out.

Protected Area

This content is password-protected. Please verify with a password to unlock the content.

read()
reads a single character or byte from the serial input buffer. Data received over serial is stored in the buffer until the sketch reads them. If the buffer is empty read() returns -1

You can see an example of this is the serial pass through sketch above.

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

if ( Serial.available() ) – Check to see if data is available. Serial.available() returns the number of bytes in the buffer. Any value > 0 is classed as not FALSE. I am using it here as a check to make sure we have at least 1 character of serial data before trying to read it.

Protected Area

This content is password-protected. Please verify with a password to unlock the content.

parseInt()
parseInt() returns the first valid ascii formatted (long) integer number found in the serial buffer. Characters that are not integers (or the minus sign) are skipped.

parseInt() runs through the serial buffer looking for characters that could be part of an integer. When looking it will delete any non numeric character until it finds an integer. If it does not find a valid value it will empty the buffer, time out and return 0. If an integer is found any characters/data after the integer are left in the serial buffer. If the buffer only contains a valid integer, parseInt() will read the available data and then wait for the timeout before returning the value. This can cause performance issues.

If the buffer contains “12345” then parseInt() returns 12345 and the buffer will be empty.
If the buffer contains “abd1234zxy”. parseInt() returns 1234 and the buffer will contain “xyx”. The “abc” will be deleted.
If the buffer contains “-3434\r\n”. parseInt() returns -3434 and the buffer will have “\r\n” after the function has finished.

It is worth highlighting that parseInt() returns a long, which in Arduino land is a 4 byte value. parseInt() will work if you use an Arduino int (which is a 2 byte value) as long as the value is < 32,767 but you will run in to problems if the value is > 32,767 because when the long is copied to the int it will lose 2 bytes and so the value will change. For example; the signed long value 2147483640 gets truncated to -8 when converted to a signed int.

long parseIntValue = Serial.parseInt();

Always copy the return value into a long variable.

parseFloat()
Serial.parseFloat() returns the first valid ascii formated floating point number from the serial buffer. The function returns empty handed (0) if a floating point number is not found or the timeout is reached. The data does not need to be in the buffer at the time the function is called but the function will block your code while it waits for data to arrive.

parsefloat runs through the serial buffer deleting non floating point characters (non-numbers and non-minus sign) until it finds a number or minus sign. It then reads the floating point data until it reaches another non float character. It then converts the ascii formatted value in to an actual floating point value.

Protected Area

This content is password-protected. Please verify with a password to unlock the content.

Arduino Serial Part 2: Serial Data

In the previous post I went through the basics of using serial on an Arduino and ran through the different commands. In this post I want to talk about different types of serial data and some of the things you should consider before starting to create code. The type of communication you use or can use will depend largely on the project but there are things that can be considered before starting.

  • Type of communication? 1-way or 2-way
  • Type of data? Values or strings? Simple or complex?
  • How much data and how frequent? A couple of values every few seconds or a high rate continuous stream.
  • Is the data critical? Must you be sure you receive all the data or can you afford to lose some of it.

Type of communication

The type of communication will determine how complex parts of the project are. One way communication is generally easier to implement but you need to consider which way; sent from the Arduino or sent to the Arduino. The Arduino does not have high level data processing functions so if you have complex data patterns you will need to create code that parses it.

Two way communication means you need to send and receive at both sides. Will communication be synchronous or asynchronous? This will effect your code and what functions you can use, for example, Software Serial on the Arduino cannot receive and send at the same time.

Type of data

Think about what information you need to pass and if you can simplify the data format used to do it. For example, if you just want to switch a light on and off you can do this with very simple codes or commands like a single character (or even one bit of an 8 bit character).
If you are creating a weather monitoring station, you may need to accommodate wind speeds and temperatures which may need floating point values.
If you have a lot of different values you will need some way to let the Arduino know which is which when they are received.
You also need to consider how quickly you need to send/receive the data. If speed is not an issue there are no real restrictions on how complex the data can be and you could use human readable data like XML or something like “Temperature=24.75,humidity=34.5%” for example. If data is received very quickly then it should be as simple as possible.

As always, I advocate keeping things as simple as possible and I always try to simplify the data, or more specifically the format of the data, I use.
For complex data where speed is not the main concern I use formatted data sets and if possible fixed length data. How much you format the data can depend on what the data is.

When sending data to the Arduino I almost always stick to the same methods; I use fixed length data and use ascii for numbers. When sending data to high level languages such as App Inventor or VisualBasic it is less important but formatted data makes things easier.

Fixed length data

To give an example of what I mean here are a couple of examples. If I have 3 sliders in App Inventor used to control a RGB LED connected to an Arduino, I know I have 3 values (red, green, and blue) and each value can be anything from 0 to 255.
Using ascii, where the numeric values are converted to alphanumeric (string) values I will use 3 characters for each value; 0 becomes “000”, 100 becomes “100” and 255 becomes “255”. I may then enclose the data within start and end markers so that the actual data becomes “[100000255]”. Then on the Arduino side, as I receive data I add it to a buffer, when the buffer has both a start marker and an end marker I know I have all the data. This makes the data easy to read but it does mean the transmission is slower than it needs to be. When speed is important I may reduce the data to “[” byte1 byte2 byte3 “]” where byte1, byte2, and byte3 are the actual numeric values. I would still use the start and end markers though.

How much data

You also need to consider how much data you want to send and how often you want to send it. There is quite a difference between sending a temperature once a minute and streaming music. If you want to send a lot of data very frequently you also need to consider latency and how quickly the Arduino can receive and process data.

For example, using software serial on an Arduino has a limit to how fast you can reliably receive and send data. Hardware serial is much better but still has limits.

Critical data

If the data is critical and you have to know you have received everything then you need a way of checking. There are many different ways of doing this but, as always, I like to keep it simple if I can. In the few cases where I wanted to know for sure I have received everything I used a basic checksum value and a count of the number of times data has been sent and appended the count to the data. This means, if I get a block of data and the checksum is not correct I know it is corrupted and can request a resend. If every block of data is numbered; block1, block2, block3, I have a simple way of checking that I have received every block and if one is missing it can be resent.

The next couple of posts go through methods for sending serial data from one Arduino to another. In all the examples I use physical wires to connect the Arduinos but the wires can be replaced by any wireless module that speaks UART such as Bluetooth modules. And although I give examples of Arduino to Arduino, the same techniques can be used when receiving serial data from any device.

Arduino Serial Part 3: Getting started with serial communication

Up to now I briefly talked about different data formats and how I recommend keeping things as simple as possible. With this is mind for a first project let’s create a simple blinking LED. We will have one Arduino controlling an LED on a second Arduino. Controls to turn the LED on or off will be sent via serial from the first Arduino to the second Arduino. This is as basic as it gets. Arduino Blink by remote control. The LED has only two states so simple control codes can be used and to start I am using 1 of on and 0 for off.

Protected Area

This content is password-protected. Please verify with a password to unlock the content.

That’s it for this part. Everything so far should give you a decent introduction to serial data and how to implement it in your own projects.

End Of Post