Lesson 9: Mastering the Arduino Serial Library

Hello and Welcome to Electro Nerds Academy! In this tutorial, we’ll master the Arduino Serial Library, this library serves as a powerful tool that enables your Arduino to talk to your computer or any other serial device. Whether you’re debugging your sketches or building a full-fledged communication system, the serial library will be your go-to choice.

What Is an Arduino Library?

An Arduino library is a collection of pre-written code that simplifies the use of specific hardware modules or software features in our Arduino projects. Libraries save us from writing complex code from scratch by providing ready-made functions and tools which we can use in our main sketch. In our case, we will use a library for serial communication called the Arduino Serial Library.

Using the Arduino Serial Monitor:

Before we look into the Arduino serial library we will first take a look at what is the Arduino serial monitor, and what are the main components of the serial monitor. The Serial Monitor is a built-in feature of the Arduino IDE that allows real-time communication between your computer and the Arduino board using serial communication. It acts as a virtual terminal, enabling you to send data to and receive data from the Arduino. This makes it an essential tool for debugging, monitoring sensor data, and testing code.

To open the serial monitor, first connect your Arduino to the computer, then click on the button in the top right corner of the IDE. A new window will pop up, this is the serial monitor window. The main components in the serial monitor window are,

1. Input Area: It is located at the top of the Serial Monitor window. It is used to send data from the computer to the Arduino.

2. Output Display Area: It is the large white section in the center which displays any data sent from the Arduino to the computer, using functions like Serial.print() or Serial.println(). We will discuss these functions shortly

3. Dropdown menu for Baud-rate: It is located at the Top-right corner of the serial monitor window. This dropdown menu allows you to set the baud rate(communication speed) in bits per second, which must match the one defined in your sketch using the Serial.begin() function. We will discuss Serial.begin() function shortly.

4. Dropdown menu for terminating character: It is located next to the baud rate dropdown menu. It lets you choose how messages sent from the input box are terminated

🔸No line ending
🔸Newline
🔸Carriage return
🔸Both newline and carriage return

5. Clear Screen Button: It is located at the top-left corner of the Serial Monitor. pressing this button will clear all previous messages in the output area.

6. Enable Timestamp Button: the clock icon button located at the right of the clear screen button is the timestamp toggle button. Pressing this button will display the time at which each message was received, useful for tracking timing.

7. Auto-Scroll Button: This button is located at the right of the enable time stamp button. Pressing this button ensures that the latest data remains visible as new messages are received.

Introducing the Arduino Serial Library

The Serial Library allows your Arduino to send and receive data through serial communication. It’s included by default in the Arduino IDE, so you don’t need to install anything extra. And as mentioned earlier a library provides us functions which we can use in our main sketch so the main functions of the Arduino serial library which we will cover in this lesson are shown below,

🔸Serial.begin()
🔸Serial.available()
🔸Serial.print() And Serial.println()
🔸Serial.read()
🔸Serial.parseInt()

1. Serial.begin():

Let’s start our journey with the serial.begin() function. This function sets the transmission speed, also known as baud rate, in bits per second. Typically, it is housed in the setup function and usually requires a single parameter, which is the desired baud rate for communication. However we can also add an optional parameter which is the config parameter. This parameter sets the data, parity, and stop bits of the data packet used in serial communication.

Serial.begin(baud-rate, Config);

The common baud rates used for serial communication are 9600, 14400, 19200, 28800, 31250, 38400, 57600, 115200. However, if the device you’re communicating with requires a different baud rate, you can specify it in this function. Just ensure that the baud rate is consistent between the sender and the receiver.

As mentioned earlier, that the serial.begin() function also allows us to configure the number of data bits, type of parity, and the number of stop bits using a second parameter. Valid values for this parameter are shown below,

SERIAL_5N1
SERIAL_6N1
SERIAL_7N1
SERIAL_8N1 (the default)
SERIAL_5N2
SERIAL_6N2
SERIAL_7N2
SERIAL_8N2
SERIAL_5E1: even parity
SERIAL_6E1
SERIAL_7E1
SERIAL_8E1
SERIAL_5E2
SERIAL_6E2
SERIAL_7E2
SERIAL_8E2
SERIAL_5O1: odd parity
SERIAL_6O1
SERIAL_7O1
SERIAL_8O1
SERIAL_5O2
SERIAL_6O2
SERIAL_7O2
SERIAL_8O2

All of these values starts with the keyword “SERIAL” after that we have an underscore “_” then we have the number of data bits followed by N, E, or O letters indicating no parity, even parity, or odd parity, and finally, the number of stop bits.

If we omit the second parameter, the default data packet consists of 8 data bits, no parity bits, and a single stop bit. If you are having trouble understanding these concepts then read our previous lesson where we had explained serial communication in detail.  

2. Serial.available():

The next function we are gonna look at is the Serial.available() function, This function returns the number of bytes available to read in the serial receive buffer. Its syntax is shown below,

Serial.available();

We had introduced the concept of serial receive buffer in the previous video. The serial receive buffer is basically a temporary storage area that can accommodate up to 64 bytes of received data. Imagine if we send the word “Hello” serially to our Arduino. This word will be broken into individual characters H, E, L, L and O. These characters will then be converted into their respective ASCII values. These values are further converted into binary digits and sent to our Arduino. The USART on the Arduino re-assembles groups of 8 bits into their ASCII values, which are then stored in the serial receive buffer. So the receive buffer doesn’t store characters directly—it holds their ASCII numerical equivalents.

Now, if we call the Serial.available() function, it will check how many bytes are currently stored in the Serial receive buffer. Since we have sent five characters, it returns 5, indicating that five bytes (representing the ASCII values of “H”, “E”, “L”, “L”, and “O”) are available for reading. 

3. Serial.print() and Serial.println():

The next function we are gonna look at is the Serial.print() function. This function facilitates sending data from our Arduino to a connected computer or other serial devices via the RX and TX pins. Typically, this function takes a single parameter: the data to be sent to the connected serial device. However we can also add an optional second parameter defining the format of the value to be printed.

Serial.print(value, Format);

Whole numbers can be printed by simply specifying the number or the variable holding that number.

Serial.print(23);

OUTPUT: 23

int a = 10;
Serial.print(a);

OUTPUT: 10

For floating-point numbers, the default behavior is to print two decimal places. For example, if we send the number 3.141592, only 3.14 will be printed on the serial port.

Serial.print(3.141592);

OUTPUT: 3.14

However, if we want to send the complete number, we can utilize the optional second parameter. For floating numbers or variables of the float data type, this parameter specifies the number of decimal places to use. So if we add 6 as the second parameter the Serial.print() function will print the complete number up to six decimal places.

Serial.print(3.141592, 6);

OUTPUT: 3.141592

For integer numbers or variables of the integer data type, the second parameter specifies the base format. For instance, if we want to print the number 48 in binary format, we use “BIN” as the second parameter.

Serial.print(48, BIN);

OUTPUT: 110000

Similarly, “OCT” represents octal format, “HEX” stands for hexadecimal, and “DEC” is the default format for decimal. If the second parameter is not used, all numeric values are printed in decimal format.

Serial.print(48, OCT);

OUTPUT: 60

Serial.print(48, HEX);

OUTPUT: 30

Serial.print(48, DEC);

OUTPUT: 48

Characters and string values can also be printed on the serial port. Characters are enclosed in single quotation marks, while strings are enclosed in double quotation marks. Variables holding these data types can be sent in a similar fashion as those of integer or float data types.

char a = 'Q';
String b = "Hello";

Serial.print(a);
Serial.print('W');

Serial.print(b);
Serial.print("Hi");

OUTPUT: Q W Hello Hi

A variant of the Serial.print() function is called Serial.println() function. Unlike the print() function, println() function automatically adds a new line at the end of its output, mimicking the action of pressing the enter key in a word processor. For example, when we print the same data using both functionsas ahown below, the print statements on the left print their respective data on the same line, whereas on the right, each println statement prints the data and adds a new line so that the next statement will be printed on a new line. Despite this distinction, both functions can accept the same arguments.

char a = 'Q';
String b = "Hello";

Serial.print(a);
Serial.print('W');

Serial.print(b);
Serial.print("Hi");

OUTPUT: Q W Hello Hi

char a = 'Q';
String b = "Hello";

Serial.println (a);
Serial.println('W');

Serial.println(b);
Serial.println("Hi");

OUTPUT:
Q
W
Hello
Hi

4. Serial.read():

Now that we know how to send data from our Arduino to any serial device, let’s delve into the process of receiving this serial data on our Arduino. To achieve this, we’ll utilize the Serial.read() function. As we know that any data sent serially to our Arduino is stored in the serial receive buffer. The Serial.read() function reads the first available byte from the receive buffer, returns its integer representation, and subsequently removes that byte from the buffer.

int data = Serial.read();

So if we send the letter “A” to our Arduino. Its ASCII value will be stored in the serial receive buffer. And if we call the Serial.read() function it will read the first byte, return it which can be stored in an integer variable and once the byte is read it will be removed from the buffer. If we send more than one character like a word for instance “hello” then we have to call the serial.read() function 5 times to read all the received characters.

We know that by now you guys must be having a lot of questions like,
1) We send the letter “A” but what we get from the Serial.read() function is it’s ASCII value. So how do we convert this number into our letter “A” ?
2) How can we read sentences like “Hello World” ?

Lets answer these questions with the help of some examples.

Example 1:

In the first example, we’ll send a single character to our Arduino and display it on the serial monitor. The code looks something like this,

int data;

void setup() 
{
  Serial.begin(9600);
}

void loop() 
{
  if (Serial.available() > 0) 
  {
    data = Serial.read();        // Read incoming character
    Serial.println(data);        // Print it back
  }
}

First, we declare an integer variable named data to store the incoming data from the serial receive buffer. In the setup section, we initialize serial communication by calling Serial.begin(9600), setting the baud rate to 9600 bits per second. This function is placed in the setup since it only needs to be executed once. In the loop section, we will first check if there’s data present in the serial receive buffer. For this we use an if statement and and in the condition of the if statement we are checking whether the returned value of the Serial.available function is greater than “0”. If it is then there is some data present in the serial receive buffer to be read. So we will read these bytes using the Serial.read function and save its output in the ‘data’ variable which we had declared initially. Next we will simply print this variable on the serial monitor using the serial dot print line function. 

Now lets upload this code to our Arduino and after a successful upload we will open the serial monitor and enter a single character lets say “A” in the text box and hit enter. We can see that the ASCII value of the character “A” is printed on the monitor.

But wouldn’t it be great if we print the actual character instead of its ASCII value. For this we will have to convert the integer value returned by the serial.read function into a character value. Which can be done by simply assigning the returned integer value to a char variable and the Arduino will automatically convert this integer value into its corresponding character and store it in the data variable. so we simply have to change the data type of the data variable from int to char.

char data;

void setup() 
{
  Serial.begin(9600);
}

void loop() 
{
  if (Serial.available() > 0) 
  {
    data = Serial.read();        // Read incoming character
    Serial.println(data);        // Print it back
  }
}

Now lets upload this modified code to our Arduino and after a successful upload we will open the serial monitor and again send the same character “A”. This time the letter “A” is printed on the serial monitor. 

Example 2:

In the next example, we’ll explore how to send entire words or even sentences to our Arduino and display them on the serial monitor. If we send the word “Hello” using our current code, we’ll notice that the individual letters H, E, L, L, and O are printed on the serial monitor.

This happens because the serial.read function can only read one byte at a time from the serial receive buffer. So when the loop runs for the first time, the if condition evaluates as true since there are five bytes in the buffer. The first byte, representing “H,” is read, converted, stored in the data variable, and printed on the serial monitor. On the next iteration of the loop the if condition is again evaluated as true, since four bytes still remain in the serial buffer, the next byte, representing “E,” is read, converted and the data variable is overwritten meaning the previous value is replaced with this new value which is then printed on the serial monitor. This process continues until all bytes are read and the buffer is empty.

So to reconstruct the complete string from these individual letters, we have to make some changes in our code as shown below,

String message;
char data;

void setup() 
{
  Serial.begin(9600);
}

void loop() 
{
  if (Serial.available() > 0) 
  {
    data = Serial.read();        // Read incoming character
    message = message + data;
    Serial.println(message);        // Print it back
  }
}

we had first declared a String variable called message. Then in the loop function, after we have read the character using the `Serial.read()` function, we will append this character value to our message variable using the addition operator(+).

message = message + data;

This process of appending characters to our string variable is known as concatenation. Here we aren’t limited to just characters—we can also append numbers, floating-point values, or even other strings to our original string using the same addition operator.

So now when the loop is run for the first time the first byte is read, the value of the ‘message’ variable, initially empty, will be concatenated with the character ‘H’. in the next iteration of the loop the second byte is read, the character ‘E’ is added to the ‘message’ variable, and its value becomes ‘HE,’ and so on. Step by step, our string gets reconstructed into its original form. Now we will print the message variable instead of the data variable.

At this point, the code might seem ready for upload, but there’s a crucial issue—can you spot it? The problem is that we’re printing the message variable at each iteration of the loop, so the variable gets printed progressively: first “H” will be printed, then “HE”, then “HEL”, and so on. Instead, what we want is to print the message variable once it’s fully reconstructed. To fix this, we need to add a terminating character each time when we send data to our Arduino.  

As discussed earlier, we can add this terminating character in the “Serial Monitor’s window”. We can select the type of terminating character we want to use from the dropdown menu. Let’s set it to “Newline character( \n )” so that every message we send will be automatically terminated with backslash ‘n’ representing new line character, signaling that the full message has been received. Here we have chosen the new line character(\n) but we can also select carriage return(\r) represented by backslash ‘r’ as a terminating character.

Now let’s modify our code to handle this behavior correctly. We will place an if/else statement inside our main if statement, and the condition of the if statement will be to check whether the read byte is a new line character or not. If it is, that means we’ve received the entire message. At this point, we print the message variable and then reset it by assigning an empty string to it so that it’s ready for the next input. If the received byte is not a newline character, we simply concatenate it to the message variable, allowing the string to be built character by character. The final code is shown below,

String message;
char data;

void setup() 
{
  Serial.begin(9600);
}

void loop() 
{
  if (Serial.available() > 0) 
  {
    data = Serial.read();        // Read incoming character

    if(data == '\n')
    {
      Serial.println(message);        // Print it back
      message = "";
    }
    else
    {
      message = message + data;
    }
  }
}

After successfully uploading this code to our Arduino we will open the serial monitor and send the word “Hello”. and the Arduino will print it on the serial monitor as shown below,

5. parseInt()

Now suppose if we want to send numbers to our Arduino and display them on the serial monitor. With the code discussed in the example above, we can send numbers and also display them on the serial monitor, but with that code the sent numbers will be stored as strings rather than integers. This means we cannot perform arithmetic operations on them like we would with integer variables.

So to solve this problem we are gonna look at a new function called Serial.parseInt() function. This function scans the incoming serial data, extracts the first valid integer, and returns it to be stored in a variable of the int data type. For instance, if we send the string “abc123xyz12”, Serial.parseInt() will ignore all leading non-numeric characters, read ‘123’, and stop as soon as it encounters a non-numeric character (`x` in this case). Since it stops reading at the first non-numeric character after a number, the trailing ’12’ will be ignored. 

The code below will extract the first valid integer number from your message and display it on the serial monitor,

int number;

void setup()
{
  Serial.begin(9600);
}

void loop() 
{
  if (Serial.available() > 0) 
  {
    number = Serial.parseInt();    // Extract first integer
    Serial.println(number);
  }
}

The code is self explanatory. In the loop function we have the main `if` statement that checks if there are bytes available in the serial receive buffer. And in the body of the if statement, we have used the ‘Serial.parseInt()’ function which will extract the first valid integer from our message and save this extracted integer value in the `number` variable. Finally, we print this number variable to the serial monitor. After uploading this code to your Arduino, open the serial monitor and send any number via the serial monitor, you will notice that number will be printed on the serial monitor.

🙌 Wrap-Up

That’s all for this beginner-friendly tour of the Arduino Serial Library! With these tools in your kit, you can build smarter, more interactive projects. Whether you’re controlling LEDs or exchanging messages between devices, or debugging your code.

Leave a Comment

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