> For the complete documentation index, see [llms.txt](https://monasheng.gitbook.io/zerotohero/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://monasheng.gitbook.io/zerotohero/arduino-zero-to-hero/core-skills/serial-monitor.md).

# Serial Monitor

{% embed url="<https://www.youtube.com/watch?v=sKLF6KyWGAw>" %}

Because microcontrollers run code flashed to them on their own processors, in-situ, usually in hard-to-reach locations, it can be hard to know exactly where they are in their program at any given time. We can't simply place a breakpoint like we would if we were writing Python or MATLAB in an IDE!

Mercifully, most MCUs provide an easy way to communicate between a computer and an MCU in operation - via a functionality called the *Serial Monitor*.

## Serial Basics

Serial is a catch-all description for a range of digital communication protocols for computers, MCUs, etc, including [RS232](https://circuitdigest.com/article/rs232-serial-communication-protocol-basics-specifications#:~:text=The%20term%20RS232%20stands%20for,printers%2C%20factory%20automation%20devices%20etc.), [RS485](https://www.cuidevices.com/blog/rs-485-serial-interface-explained#:~:text=motion%20control%20equipment.-,What%20is%20RS%2D485%3F,devices%20on%20the%20same%20bus.), [UART](https://www.rohde-schwarz.com/au/products/test-and-measurement/essentials-test-equipment/digital-oscilloscopes/understanding-uart_254524.html#:~:text=UART%20stands%20for%20universal%20asynchronous,and%20receive%20in%20both%20directions.), etc. *Serial* protocols work by communicating information as a stream of `1` and `0` bits, one-bit-at-a-time, in a *series* - hence the name! Serial can run at various speeds, called *Baud Rates*, with higher rates allowing for faster data transmission and higher throughput.

<figure><img src="/files/S3tsX4qcfiGfAG9XwnvT" alt=""><figcaption><p>Serial communications transmit data one bit at a time. GIF taken from: <a href="https://www.youtube.com/watch?app=desktop&#x26;v=IyGwvGzrqp8">https://www.youtube.com/watch?app=desktop&#x26;v=IyGwvGzrqp8</a></p></figcaption></figure>

In Serial, at any time only one device is transmitting (`TX`) and the other receiving (`RX`).&#x20;

In practice, this is usually achieved by connecting a conductor between the `TX` of one device and `RX` of the other, and allowing the `TX` device to alter the voltage of this conductor between a `HIGH` and `LOW` state to represent  `1` and `0` bits.

<figure><img src="/files/IjSmbEeJrkVpPL4UbVDt" alt=""><figcaption><p>The voltage trace shown here alternates between HIGH and LOW to represent 1 and 0 bits respectively. GIF taken from: <a href="https://www.youtube.com/watch?app=desktop&#x26;v=IyGwvGzrqp8">https://www.youtube.com/watch?app=desktop&#x26;v=IyGwvGzrqp8</a></p></figcaption></figure>

While more sophisticated protocols now exist with much higher data throughput, many legacy and industrial devices still use serial due to it's relative simplicity, robustness, and ubiquity.

## Arduino Serial

Arduino-based MCUs usually have several serial-compatible `TX/RX` pin pairs/interfaces built-in, for communicating with sensor boards, other MCUs, and computers.

<figure><img src="/files/uEyODL6xqzeA4WPhpERp" alt=""><figcaption><p>Serial-compatible pins (<code>0-1</code>, and <code>14-21</code>) are highlighted in silkscreen on the board of an Arduino Mega.</p></figcaption></figure>

The 'main' serial interface on an Arduino is:

1. linked to a built-in serial-USB interface and internally routed to the main USB connector on the board, and,
2. also linked to `PIN 0` for `RX` (receive) and `PIN 1` for `TX` (transmit).

This building-in serial-USB interface provides an easy way for you to communicate with your Arduino using serial and your computer.

## Serial Setup

To communicate via the serial monitor, you must enable the built-in serial interface on your MCU via an initialisation command.&#x20;

{% embed url="<https://www.arduino.cc/reference/en/language/functions/communication/serial/begin/>" %}

As this only needs to be done once, it is typically achieved in the void `setup()` function.

```arduino
void setup() {
  // Initialize serial communication at 9600 baud rate
  Serial.begin(9600);
}
```

Here, the `Serial.begin()` function initialises the built-in serial interface at the baud rate specified as an input (here, 9600 bits/s). Higher baud rates will allow higher data throughput, but for most practical applications 9600 baud will be more than sufficient.

{% hint style="danger" %}
:zap: **Warning:** Once initialised with `Serial.begin()`, Arduino boards mirror their primary (USB) serial interface traffic on `PIN 1` and `PIN 0`. While this can be useful (you can verify the traffic by putting an oscilloscope on these pins!), it can also lead to unexpected behaviours.

**In general, after calling** `Serial.begin()`**, you should avoid using**`PIN 1` **or** `PIN 0` **for any other purpose**
{% endhint %}

## Serial Output

Writing to the serial monitor is very straightforward, and you'll most often do this using the `Serial.print()` family of commands:

{% embed url="<https://www.arduino.cc/reference/en/language/functions/communication/serial/print/>" %}

Provided you have called `Serial.begin()`, you can use `Serial.print()` to write to the monitor either once (by calling it in the `setup()` function), or repeatedly (by calling it in the `loop()` function).&#x20;

```arduino
void setup() {
  // Initialize serial communication at 9600 baud rate
  Serial.begin(9600);
  // Print this text to the serial monitor once, upon setup
  Serial.print("Hello! Is my serial monitor working?");
}

void loop() {
 // Print this text to the serial monitor every loop iteration
 Serial.print("Are we there yet?");
 // Add a small delay between calls so we don't overload the bus
 delay(500);
}
```

{% hint style="danger" %}
:zap: **Warning:** printing to the serial monitor is a relatively time-consuming task. It should ideally be done on an interval, using [Timers](/zerotohero/arduino-zero-to-hero/core-skills/timers.md) or the `delay()` function to avoid overloading the serial bus with messages.

Avoid printing to the serial monitor every `loop()` iteration wherever possible to avoid slowing your Arduino!
{% endhint %}

### Newline Functionality

You may have noticed that the `Serial.print()` function will display text on the serial monitor back-to-back with whatever was there previously. This can make it hard to spot when new information has been broadcast, and to read information generally.

<figure><img src="/files/rJAuFiMLZ4ZDoIjnWgoY" alt=""><figcaption></figcaption></figure>

The `Serial.println()` function is identical in functionality, but it adds a newline (or `ENTER`) character after printing, which can clean up the monitor output.

{% code overflow="wrap" %}

```arduino
void setup() {
  // Initialize serial communication at 9600 baud rate
  Serial.begin(9600);
  // Print this text to the serial monitor once, upon setup, with a newline character
  Serial.println("Hello! Is my serial monitor working?");
}

void loop() {
 // Print this text to the serial monitor every loop iteration , with a newline character
  Serial.println("Are we there yet?");
 // Add a small delay between calls so we don't overload the bus
 delay(500);
}
```

{% endcode %}

<figure><img src="/files/ScXT6mwdyAvVrMngscpY" alt=""><figcaption></figcaption></figure>

You can use a combination of `Serial.print()` and `Serial.println()` calls to build up complex lines of text:

{% code overflow="wrap" %}

```arduino
void setup() {
  // Initialize serial communication at 9600 baud rate
  Serial.begin(9600);
  // Print this text to the serial monitor once, upon setup, with a newline character
  Serial.println("Hello! Is my serial monitor working?");
}

void loop() {
 int x = 1;
 int y = 2;
 int z = x + y;
 
 // Print a complex string by building up Serial.print() calls, followed by one Serial.println() call
  Serial.print("x = ");
  Serial.print(x);
  Serial.print(", y = ");
  Serial.println(y);
  
  // You can also do this all on one line for readability, as long as each statement is terminated with a ;. Make sure the last one is a Serial.println()!
  Serial.print("z = "); Serial.println(z);
  
  // Add a small delay between calls so we don't overload the bus
  delay(500);
}
```

{% endcode %}

<figure><img src="/files/WukecSQIIRRsIqzukX1q" alt=""><figcaption></figcaption></figure>

## Connecting to the Computer

Mercifully, no additional or manual connections are required for you to use the Serial Monitor to communicate with an Arduino board - you can use the built-in USB connector on the board, and *any* USB port on your computer.

{% hint style="danger" %}
:zap: **Warning:** some USB cables (e.g. those for charging devices) are designed for power-transmission only. These cables are missing the data conductors required for serial communications to work.&#x20;

**Ensure you have a normal, data-compatible USB cable when attempting serial communications with your MCU.**
{% endhint %}

### COM Port

Because serial is a legacy technology, the Arduino IDE does not always automatically self-configure to speak with a connected MCU. In this case, you may need to tell it which hardware interface (called a *COM PORT*) on the computer the MCU is connected to.

You'll often have to do this when plugging/unplugging the MCU - especially if you change which USB port it is plugged into - or after flashing code.

Mercifully, this is relatively easy to do:

1. Click on `Tools` in the menu bar and find the `Port` row. If a board is currently selected it will be displayed here.
2. Hover over the `Port` to reveal all ports. For Arduino devices, the board name will typically be displayed after the port, for example:
   * `COM3 (Arduino Mega)`
3. Click on a port to select it.

## Opening the Monitor

You can open the serial monitor window to see active communications by either:

1. Clicking on *Tools* in the menu bar and selecting *Serial Monitor*, or,
2. Using the keyboard shortcut `CTRL+SHIFT+M` on a Windows machine or `CMD+SHIFT+M` on a mac.

The monitor window will show all active serial traffic on the selected [#com-port](#com-port "mention"). Note that:

1. Traffic still comes into the Arduino IDE when you're not looking at the serial monitor, meaning that there might be old traffic above incoming new lines, and,
2. Opening the serial monitor typically sends a command to reboot your arduino, meaning that it will re-run the `setup()` function when you do so.

<figure><img src="/files/p3rnnvgPuuX4PIghQabC" alt=""><figcaption></figcaption></figure>

Via a drop-down, you can also set the Baud Rate for communications. The rate set in this window must match the rate programmed in the MCU code, or no communications will be possible. If set incorrectly, it might display garbage characters, like `�` or nothing at all!

<figure><img src="/files/I9vX23t3wAAW5SHWH4yd" alt=""><figcaption></figcaption></figure>

Via a checkbox, you can also toggle *autoscrolling,* *timestamp,* and *clear monitor* functionalities - which can be useful if you want to:

1. interrogate a particular printed value,
2. identify whether the monitor is actually changing, or,
3. clear the monitor of old output.

<figure><img src="/files/NvKCeKAcjdyQTMAtODh5" alt=""><figcaption></figcaption></figure>
