The Serial Monitor
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
| Function | What 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:
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:
--- 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:
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);
}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.
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:
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:
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:
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:
- Did the code reach this line? Print a short marker such as
"A"or"in setup". - What value does this variable really have? Print it with a label.
- Which branch of an
ifran? 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
Serial1instead.
Key points
Serial.begin(baud)starts serial; the Serial Monitor must use the same baud rate.printstays on the line,printlnends it; add a second argument for decimals,HEXorBIN.Serial.available()andreadStringUntil('\n')read commands typed in the monitor;trim()cleans them.- The Serial Plotter graphs
label:valuepairs 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
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:
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?
The second argument asks for 4 decimal places, and the value is rounded.
2. Why do we call trim() on a received command?
Line-ending settings can add \r; trim() removes it so "on" matches.
3. What format does the Serial Plotter understand for named lines?
Each printed line is one moment in time, with label:value pairs for each line on the graph.
4. What does Serial.print(255, HEX) print?
255 in hexadecimal is FF. BIN would give 11111111.
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
