EthicsComputerCourses
Join training +91 90532 10052

The Serial Monitor

IoT & Arduino · Lesson 9 of 29 Beginner 7 min read Updated

By the end of this lesson you will be able to print any value from your board, format numbers neatly, send commands from your keyboard to the board, and watch live graphs in the Serial Plotter. The Serial Monitor is your window into the board: you will use it in every lesson from now on.

A microcontroller has no screen. When a sketch does something unexpected, printing values is the fastest way to see what is really happening inside. Professional embedded engineers do exactly this, every day.

What "serial" means

Serial communication sends data one bit after another over a wire, like people walking through a single-file gate at a railway platform. Your board and computer agree on a speed, called the baud rate, measured in bits per second. Common values are 9600 and 115200.

If the two ends use different speeds, the computer reads the bits at the wrong times and shows nonsense characters. That is why the number in Serial.begin() must match the drop-down at the bottom of the Serial Monitor.

On the UNO R4, Serial travels over the USB cable. Serial1 uses pins 0 and 1 for talking to other devices, which you will meet in Communication: UART, I2C & SPI.

Step 1: Printing and formatting

FunctionWhat it prints
Serial.print(x)The value, without a new line
Serial.println(x)The value, then moves to a new line
Serial.print(f, 1)A decimal number with 1 digit after the point (default is 2)
Serial.print(n, HEX)A whole number in hexadecimal
Serial.print(n, BIN)A whole number in binary

This sketch prints a small report card. It runs once in setup(), so the output is always the same:

C++
void setup() {
  Serial.begin(115200);
  while (!Serial && millis() < 3000) { }   // wait up to 3 s for the Serial Monitor

  int marks = 87;
  float average = 78.456;

  Serial.println("--- Report for Ananya ---");
  Serial.print("Marks: ");
  Serial.println(marks);
  Serial.print("Class average: ");
  Serial.println(average);          // 2 decimal places by default
  Serial.print("Average to 1 place: ");
  Serial.println(average, 1);
  Serial.print("255 in hex: ");
  Serial.println(255, HEX);
  Serial.print("5 in binary: ");
  Serial.println(5, BIN);
}

void loop() {
}

Set the Serial Monitor to 115200 baud, then press the board's reset button to run setup() again:

Output
--- Report for Ananya ---
Marks: 87
Class average: 78.46
Average to 1 place: 78.5
255 in hex: FF
5 in binary: 101

Notice that 78.456 printed as 78.46: the Serial library rounds to the number of decimal places you ask for. Hex and binary are handy later for reading sensor registers and I2C addresses.

Step 2: Labels make output readable

Printing only numbers quickly becomes confusing. Always print a label first. A common pattern is one line per reading with labels and units:

C++
void setup() {
  Serial.begin(115200);
  while (!Serial && millis() < 3000) { }
}

void loop() {
  unsigned long seconds = millis() / 1000;   // time since start, in seconds
  Serial.print("Uptime: ");
  Serial.print(seconds);
  Serial.println(" s");
  delay(1000);
}
Output
Uptime: 0 s
Uptime: 1 s
Uptime: 2 s
Uptime: 3 s

millis() returns the number of milliseconds since the board started. Dividing by 1000 gives whole seconds. Depending on when the monitor connects, your first number may be 1 or 2 instead of 0.

Step 3: Sending commands to the board

The Serial Monitor also has a text box at the top. Whatever you type there is sent to the board when you press Enter. This turns your keyboard into a remote control.

In the drop-down next to the baud rate, choose New Line. Then the monitor adds a newline character (\n) at the end of everything you send, so the sketch knows where each command ends.

C++
void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  Serial.begin(115200);
  while (!Serial && millis() < 3000) { }
  Serial.println("Type on or off");
}

void loop() {
  if (Serial.available() > 0) {                  // has anything arrived?
    String command = Serial.readStringUntil('\n');
    command.trim();                              // remove spaces and \r
    if (command == "on") {
      digitalWrite(LED_BUILTIN, HIGH);
      Serial.println("OK: LED on");
    } else if (command == "off") {
      digitalWrite(LED_BUILTIN, LOW);
      Serial.println("OK: LED off");
    } else {
      Serial.print("Unknown command: ");
      Serial.println(command);
    }
  }
}

If you type on, then off, then blink, the monitor shows:

Output
Type on or off
OK: LED on
OK: LED off
Unknown command: blink

Serial.available() returns how many bytes are waiting to be read. readStringUntil('\n') collects characters up to the newline. trim() removes stray spaces and the carriage return (\r) that some line-ending settings add. Without trim(), "on\r" would not equal "on", and every command would be "unknown".

Step 4: Live graphs in the Serial Plotter

The Serial Plotter (the graph icon next to the Serial Monitor) draws numbers as moving lines. Print one line per moment in time, with label:value pairs separated by commas:

C++
int level = 0;
int step = 1;

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

void loop() {
  Serial.print("up:");
  Serial.print(level);
  Serial.print(",down:");
  Serial.println(10 - level);
  level = level + step;
  if (level == 10 || level == 0) {
    step = -step;                      // turn around at the ends
  }
  delay(100);
}

The plotter shows two zig-zag lines crossing each other. In the Serial Monitor, the same data looks like this:

Output
up:0,down:10
up:1,down:9
up:2,down:8
up:3,down:7

Later you will plot real sensor values, such as temperature and light, to see trends that are hard to spot in a list of numbers. Close the Serial Monitor before opening the Plotter if your IDE says the port is busy.

Debugging with prints

When a sketch misbehaves, add prints to answer one question at a time:

  1. Did the code reach this line? Print a short marker such as "A" or "in setup".
  2. What value does this variable really have? Print it with a label.
  3. Which branch of an if ran? Print a different word in each branch.

Remove or comment out extra prints when you are done. They slow the sketch down a little, especially at 9600 baud.

Common mistakes

  • Mismatched baud rate. Garbled symbols mean the monitor and Serial.begin() disagree.
  • "No line ending" selected when the sketch waits for '\n'. The command never completes.
  • Forgetting trim(). Comparisons fail because of a hidden \r.
  • Printing too fast. A tight loop() with no delay can flood the monitor; add a short delay or print only when something changes.
  • Using pins 0 and 1 for LEDs on an UNO R3. On the R3 they carry the USB serial data. On the R4 they are Serial1 instead.

Key points

  • Serial.begin(baud) starts serial; the Serial Monitor must use the same baud rate.
  • print stays on the line, println ends it; add a second argument for decimals, HEX or BIN.
  • Serial.available() and readStringUntil('\n') read commands typed in the monitor; trim() cleans them.
  • The Serial Plotter graphs label:value pairs printed one line at a time.
  • Printing labelled values is the quickest way to debug a sketch.

Exercise

Write a sketch that understands three commands typed in the Serial Monitor: fast makes the L LED blink every 200 ms, slow every 1000 ms, and stop turns it off. Reply with a confirmation for each command. You may use delay() for the blinking.

Show solution
C++
int blinkMs = 0;                       // 0 means stopped

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  Serial.begin(115200);
  while (!Serial && millis() < 3000) { }
  Serial.println("Commands: fast, slow, stop");
}

void loop() {
  if (Serial.available() > 0) {
    String cmd = Serial.readStringUntil('\n');
    cmd.trim();
    if (cmd == "fast") blinkMs = 200;
    else if (cmd == "slow") blinkMs = 1000;
    else if (cmd == "stop") blinkMs = 0;
    Serial.print("Blink interval now: ");
    Serial.println(blinkMs);
  }
  if (blinkMs > 0) {
    digitalWrite(LED_BUILTIN, HIGH);
    delay(blinkMs);
    digitalWrite(LED_BUILTIN, LOW);
    delay(blinkMs);
  }
}

Typing fast, slow, stop prints:

Output
Commands: fast, slow, stop
Blink interval now: 200
Blink interval now: 1000
Blink interval now: 0

Because of delay(), a command typed during a slow blink is noticed only after the blink finishes. You will fix that with millis() later.

Quick Quiz

1. What does Serial.println(3.14159, 4) print?

2. Why do we call trim() on a received command?

3. What format does the Serial Plotter understand for named lines?

4. What does Serial.print(255, HEX) print?

Learn IoT & Arduino with a mentor

Free lessons get you started. Our IoT & Embedded Systems training adds real projects and code reviews from working developers.

  • Project-based learning
  • Mentor code reviews
  • Free counselling call