Using Arduino Serial Communication with the Serial monitor

In this blog, I will show how to use the built-in Serial port on all Arduinos to communicate back and forth with your PC using the Serial library and the Serial monitor.

In the case of an Arduino, the program is uploaded to and runs on the board completely in isolation. While this is happening, there might be bugs, or a need to simply analyze some data points/variables. Since an Arduino does not come with a built-in display or rich debugging capabilities, these are not very straight-forward to do. This is where Serial communication (between the PC and Arduino) can be used for debugging or analyzing program values.

I will start with a short introduction to “Serial” communication on the Arduino and explain the flow of data between the PC and Arduino. I will then provide two sample programs which demonstrate the use of the Serial monitor and Serial library for two-way communication between an Arduino and PC. Let’s get started!

What is Serial communication?

“Serial” communication, as the name suggests, is about sending data one bit at a time sequentially. This is in contrast to parallel communication, where data is still sent multiple bits at a time.

Parallel Port & Transmission versus Serial Port & Transmission

The sender transmits the data bits in the form of high and low signals and is correspondingly received the by the receiver. The words Transmit and Receive are abbreviated to TX and RX respectively. On an Arduino UNO, these pins are 1 (TX) and 0 (RX) respectively.

Arduino UNO with Serial port pins

Serial communication is light-weight. It requires only two wires to achieve two-way communication and requires no extra synchronization between the two end-points, which brings down the cost and complexity of the required hardware. However, the two devices must agree on the speed of communication (the rate at which bits are sent and received) beforehand. This is called the baud rate.

Communication is of two types, simplex, where the role of the sender and receiver are fixed (one way) and duplex, where either side is capable of sending and receiving (both ways). Duplex communication can be further divided into half-duplex, where only one side can send data at a point in time (and the other side listens and waits for their turn to send) and full-duplex, where both sides can send and receive data simultaneously. The communication between your PC and Arduino is full-duplex.

Simplex
Half-Duplex (one at a time)
Full-Duplex (both at a time)

Do note that this is a very simplified picture of what actually goes on but it is enough to be able to effectively make use of the Arduino’s Serial library and tools.

Flow of data between the PC and Arduino

There are various hardware and software components involved in the communication between a PC and an Arduino.

A PC has a USB port, which the operating system (like Windows) presents as a virtual COM (communication) port for the Arduino IDE to use. The Arduino board, on the other end, has a built-in Serial port along with a USB-UART converter. The converter on the Arduino, allows outgoing data to be converted to USB, and incoming data to be converted to UART.

I have used the word UART in addition to Serial. This is because while both USB (Universal Serial Bus) and the Arduino use Serial communication, they use very different protocols to communicate. Additionally, it is possible to emulate a UART port using software (called bit banging), but it is not possible to do so with USB.

The hardware is then abstracted upon via software on both ends. On the Arduino’s side, the running program uses the Serial library (a collection of functions) to read/write data. The program you write will use the Serial library’s functions and methods to be able to use the port.

On the PC, the user can see the data received from Arduino or send back data using the Serial monitor built in to the Arduino IDE. The Serial monitor is a program that ships with the Arduino IDE and allows you to view the data (and also send some back) which is being sent on the virtual Serial port which your Arduino connects to. It can be opened by going to Tools>Serial monitor

Where to find the Serial monitor

Here is how it looks-

Serial monitor

Given below is the set of steps involved in the data flow.

  1. The running program on the Arduino calls a function (like Serial.print()) from the Serial library
  2. The Serial library sends the data through the Serial port to the USB-UART converter
  3. The USB-UART transmits the data to the PC
  4. The data is received by the PC and the operating system forwards it to the Arduino Serial monitor
  5. The Serial monitor displays the data sent from your program for the user to see.

While sending data from the PC (Serial monitor) to the Arduino, the same set of steps are executed, but in reverse order. The data is typed into the text-box in Serial Monitor and on pressing ENTER is sent to a running program on your Arduino and received using Serial library functions (like Serialread())

Hello World! with the Arduino’s Serial library

Let us now write a program which sends data from the Arduino to the PC. Start by copying the following code into your IDE and uploading it to your board.


void setup() {
	Serial.begin(9600); // start serial communication at 9600 bits/sec
}

void loop() {
	Serial.print("\nHello World!\n"); // send the string "Hello World!" with newlines
	Serial.println(66);               // send the number 66
	Serial.println(66, OCT);          // send the number 66, but in octal form
	Serial.println(66, HEX);          // send the number 66, but in hexadecimal form
	Serial.println(66, BIN);          // send the number 66, but in binary form
	Serial.write(66);                 // Send the byet 66, same as sending 'B'

	delay(2000);                      // wait for 2 seconds before repeating
}

The code can be divided into two parts. In the first part (the setup), we initialize the Serial object to start communication at the specified bitrate, which is in this case 9600 bits per second. As mentioned before, the Serial object provides an abstraction over the hardware serial port and handles all the low level nuances on its own.

In the second part (the loop), we do the following things-

  1. Send the string “Hello World!” to the PC along with a newline character at the beginning and end.
  2. Send the integer 66 to the PC and simply print it.
  3. Send the integer 66 and print it in octal form (“102” will be printed).
  4. Send the integer 66 and print it in hexadecimal form (“42” will be printed).
  5. Send the integer 66 and print it in binary form (“1000010” will be printed).
  6. Write the value 66 as a byte (“The letter ‘B’ will be printed).

There is also a delay in the end which prevents the Arduino to continuously send information at full speed and flooding the Serial monitor. Here is how the output should look if everything went fine. Let us now understand this part of the code in a little more detail.

Both the Serial port and monitor do not inherently understand anything other than bytes and treat everything they send and receive as byte streams (This is one level above the actual communication which is done using sequences of bits). The Serial object abstracts this using the Serial.write method which accepts a single byte and writes that to the Serial port. Upon being received by the PC, its ASCII representation is displayed on the Serial monitor, which could be seen when 66 was written to the Serial port and the letter “B” was printed.

However, this is not enough in many cases. For example, to print the number 66 (or any other multi-digit number) on the Serial monitor, the write method in this byte-by-byte mode would have to be called repeatedly, for every digit of the number. Apart from this, each digit would have to be converted into its ASCII representation and all this would have to be done in the right order. The same would also be true for strings and floating point numbers.

To avoid all this extra work, these methods (write, print, println) are overloaded for different data types and also provide additional parameters. What this means is that you can use different data-types and the function will ensure that it is sent correctly and displayed in an understandable format by the user automatically. Furthermore, in case of numbers, they also take an additional parameter to specify the format of the number. For integers, the format specifies the base in which to print the number and for floating point numbers, it specifies the number of digits after the decimal point.

Serial.println() sends an additional newline character at the end as contrasted to Serial.print() as a simple added convenience.

Sending Data using the Serial Monitor to the Arduino

In this section, we will see how to send data from your PC using Serial Monitor to your running program on the Arduino. Messages can be sent from the Serial monitor by typing them out in the text-box given at the top of the window and either pressing enter or by left-clicking the send button on the top right corner.

The program running on Arduino must use certain functions from the Serial library to check if any data has come on its Serial port and then read it. The program can now use this data received like any other input for its flow control.

To demonstrate this capability in our sample, we will receive the data and then simply send the same back for the Serial monitor to show. In other words, we will write a program which accepts input sent from the Serial monitor and echoes it back to the PC.

Start by copying the following code into your IDE and uploading it.


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

void loop() {
	if(Serial.available()) {   // check if there is something to be read
		char c = Serial.read();   // read the next character
		Serial.write(c);          // send it back
	}
}

While the initialization remains the same, the loop has changed. Here is what the code is doing-

  1. Checks if there is something to be read from the Serial port and continue if there is nothing.
  2. Reads the character from the Serial port and sends it back.

If everything went fine, this should echo everything you sent back to the Serial Monitor. Let’s take a closer look at the code.

The initialization of the Serial port is the same as before. The loop() function now has an if-block which is executed whenever there is something to be read from the Serial port. The Serial.available() function is to check if there is some data available on your serial port. This function returns a non-zero number i.e. number of bytes which can be read when we send something from the Serial monitor to the Arduino.

If there is something available, we read it one character at a time (using Serial.read()) from the Serial port and for this sample, we simply echo it back using the Serial.write() function. In a more real life application, this could act as an input for the program to do something more meaningful like light up an LED.

You would have noticed however, that the messages which are echoed back are printed on separate lines, even though we have not sent a newline character explicitly. This is because the Serial monitor adds a newline character at the end of every message by default, which is echoed back as well. The Serial monitor also appends a carriage return character after the newline character. More on this in the next section.

Line endings on the Serial monitor

We have seen how to print messages on the Serial monitor and even echo back messages sent by the Serial monitor to the Arduino, however one important aspect of the Serial monitor which is often confusing is the option to specify line endings.

By default, any message you send via the Serial monitor is sent along with two extra characters appended at the end, a newline/linefeed (\n) and carriage return (\r). You can see here for more about New Line. This can be seen on the bottom right corner of the window. As mentioned already, you can change this option to send both the above newline and carriage return characters, only one of them, or nothing at all.

Line endings selection menu

As the newline and carriage return are non printable characters, they can cause unintentional bugs in programs a lot of the times and must be taken care of. The sketch given below can be used to demonstrate this.


bool state = LOW;

void setup() {
	Serial.begin(115200); // start Serial communication
	pinMode(LED_BUILTIN, OUTPUT);
	digitalWrite(LED_BUILTIN, state);
}

void loop() {
	if(Serial.available()) {
		char c = Serial.read(); // read the character and discard it
		state = !state;         // toggle the state (HIGH becomes LOW and vice versa)
		digitalWrite(LED_BUILTIN, state); // set the built-in LED to the new state
	}
}

This sketch starts out by initializing Serial (I have set the baud to 115200 instead of the usual 9600, this will not affect the working of the sketch) and setting the state of the Arduino’s built-in LED to low/off in the setup. In the loop, we check if there is a character to be read and toggle the state of the built-in LED every time this happens. The character is discarded.

What this means is that if an odd number of characters are read from the monitor, then the the state of the LED will be the opposite of what it was when the characters were sent and if the number of characters were even, then the state of the LED would be the same (this can be trivially verified).

With no line endings, the sketch will work as expected. For example, sending the string “111” will indeed flip the state of the LED and sending “1111” will not affect it. However, this either newline or carriage return are selected. This is because an extra character is appended at the end making all even-length messages odd and vice versa. Selecting both newline and carriage return will restore the normal operation of the sketch, as appending two characters retains the parity of the message length, i.e. even-length messages remain even and the same with odd.

These details can sometimes get overlooked, which can cause improper functioning of the sketch, and must be kept in mind.

Conclusion

You should now have a fair idea of how to start using Serial Communication with your Arduino. The Serial Monitor is a simple and handy tool that comes along with the Arduino IDE while the Serial Library is a fairly rich set of functions for you to manage Serial from within your program. I have explained the core read/write functions however there are other ones which are available, should you want to do more advance stuff.

Some FAQs

Here are some typical questions and their answers on the subject –

What is Serial begin in Arduino?

Any two end-points in Serial communication have to operate on an agreed upon speed. This is called the baud-rate and is expressed as bits per second. The Serial library of Arduino provides the function Serial.begin(baud_rate) in order to set this speed for serial communication between the Arduino and your PC. This is typically the first function to be called and is done as part of the setup() function of your program. This speed should match the other end, i.e. the Serial monitor if you are communication with your PC. Reference link.

What is Serial write in Arduino?

Serial.write(value) is one of the several functions (print, println) again provided by the Serial library which is used to send data from your running program on Arduino to the Serial Monitor running on your PC. Using the function, you can send an individual byte OR a string OR a buffer of bytes providing its length. Reference link.

What is Serial print/println in Arduino?

Serial.print(value, format) is a function which is used to send data from your running program on Arduino to the Serial Monitor and print the same in human readable form. This function is overloaded to allow different data types to be handled differently i.e. you can give it a string or a number or floating point number and it will automatically manage its transmission over the serial link and its output back in a readable manner. For numbers, it allows further format to be specified. You can specify to how the number in a different base like a Hexadecimal (base 16) or Octal (base 8). For floating point numbers you can specify the number of decimal places to use which defaults to 2. Reference link.

It differs from Serial.write() in that it converts the data into human readable form, whichever type it might be, while Serial.write() sends data as just a set of byte(s). On the other hand Serial.println() adds a newline (actually a carriage return ‘\r’ and line feed ‘\n’) after sending the specified data.

What is Software Serial in Arduino?

Answer: Software Serial is a technique where software is used as a substitute for a dedicated hardware Serial port in order to perform Serial communication. Most (but not all, click here for more information) of the functionality provided by the Serial port can be emulated through software, allowing other pins, apart from the Serial port, to be used to do Serial communication. This is also referred to as bit banging.

6 Comments

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s