Preview build — page text is a draft awaiting human review. Code badges come from real compiles. The flasher is real but not yet hardware-tested; the Playground is still a preview.

Day 5 of 30 · about 38 minutes

Serial Monitor and debugging

Today you build: A board you control by typing numbers

  • Read 8 min
  • Upload & tour the Serial Monitor 6 min
  • Line-ending experiments 5 min
  • Bug hunt 6 min
  • Try it: a speed command 10 min
  • Check yourself 3 min

Community draft — report a mistake

The Serial Monitor is your window into the board. Printing values is the fastest way to find out why a project isn’t doing what you expect — every experienced maker does it all day. Today you also send text the other way: from your keyboard to the board.

What you need

Just the Uno or Nano and its USB cable. The sketch uses the on-board L LED, so there’s nothing to wire. Day 2’s LED on pin 13 can stay.

A tour of the Serial Monitor

Upload today’s code, then open Tools → Serial Monitor. It opens as a panel under your code. Three things matter:

  • The baud menu (right side) — must say 9600 baud, matching Serial.begin(9600). Both ends have to agree on the speed, or the text turns into symbols.
  • The line-ending menu (next to it) — set it to New Line. It decides what’s added after what you type when you press Enter.
  • The message box (top) — type here and press Enter to send.

You should see:

Ready. Type a number from 1 to 20 and press Enter.

Close the monitor and open it again: the line prints again. Opening the monitor resets an Uno or Nano, so setup() runs once more. That’s handy — and the reason a sketch seems to “restart” whenever you open the monitor.

Talk to your board

Type 5 and press Enter. The LED blinks five times and the board reports what it’s doing:

Blinking 5 times
  blink 1
  blink 2
  blink 3
  blink 4
  blink 5
Done in 1500 ms

The time may be a millisecond or two over. Five blinks of 150 ms on and 150 ms off is 1,500 ms — the numbers check out.

How it works

  • Serial.available() tells you how many characters have arrived and are waiting.
  • Serial.parseInt() reads digits and stops at the first character that isn’t one. It returns the number, or 0 if no digits arrived within one second.
  • The while (Serial.available() > 0) Serial.read(); loop throws away the rest of the line, including the newline.
  • millis() is the number of milliseconds since the board started. Reading it before and after blink() measures how long it took.
  • F("...") keeps the text in flash memory instead of the Uno’s tiny 2 KB of RAM.
  • The range check (n < 1 || n > 20) refuses anything silly before it reaches the LED. Never trust input — from a keyboard, a sensor or a phone.

Experiments: what you type vs what arrives

Try each one and match it to the explanation:

  1. Type 25 → Out of range: 25. The range check works.
  2. Type abc → after a one-second pause, Out of range: 0. parseInt() found no digits, waited for its one-second timeout, and returned 0.
  3. Set the line ending to No Line Ending and type 5. The blinks start about one second late. With nothing after the 5, parseInt() can’t tell the number has ended, so it waits for the timeout. Set it back to New Line.

When a project “responds slowly” to typed commands, the line ending is the first thing to check.

Bug hunt

Plant a bug on purpose: in blink(), change i <= times to i < times. Upload and type 5.

The LED blinks only four times. Without the debug prints you’d be counting flashes and guessing. With them, the monitor shows blink 1 to blink 4 and Done in 1200 ms — the loop clearly stops one short, so the bug must be in the loop’s condition. Fix it back to <=.

That’s the whole method: print what the code is doing, compare it with what you expected, and the gap points at the bug.

Debugging habits that save hours

  1. Print before you guess. Add Serial.println(value) right where you think things go wrong.
  2. Garbage characters? The baud rate in the monitor doesn’t match the sketch. Full fix.
  3. Nothing at all? Check that Serial.begin() is in setup(), and that you picked the right port.
  4. “Port busy” when uploading or opening the monitor? Another program has the port — a second IDE window or a web serial page. Full fix.
  5. Change one thing at a time, upload, and watch.

When a sensor won’t respond, the I2C device not found guide uses exactly this technique.

Try it: a speed command

Make numbers from 100 to 1000 set the blink speed instead of a blink count.

  1. Above setup(), add int speedMs = 150;.
  2. In blink(), replace both delay(150) with delay(speedMs).
  3. In loop(), right after the line that drops the rest of the input, add:
if (n >= 100 && n <= 1000) {
  speedMs = n;
  Serial.print(F("Speed set to "));
  Serial.println(n);
  return;
}

Type 500, then 3. You should see Speed set to 500, three slow blinks and Done in 3000 ms. Then update the Ready message so a new user knows about the speed command.

You’re done when…

  • Typing 5 gives five blinks and Done in 1500 ms (or a millisecond more).
  • You can explain why abc and “No Line Ending” each cause a one-second wait.
  • You found the planted bug from the printed output, not by counting flashes.
  • 500 then 3 gives slow blinks and Done in 3000 ms.

That’s week one: output, input, analog and Serial. Next: sound, timing without delay(), and your first sensor.

Today's code

Verified — core avr 1.8.8, 3 Nov 2026Compile-only
lesson-serial.inoArduino C++Open in PlaygroundOpen in Playground
// Day 5 — Serial Monitor and debugging (Arduino Uno / Nano)
// Open Tools > Serial Monitor at 9600 baud. Type a number and press Enter:
// the board blinks the LED that many times and reports what it is doing.

const int LED_PIN = 13;

void setup() {
  Serial.begin(9600);
  pinMode(LED_PIN, OUTPUT);
  Serial.println(F("Ready. Type a number from 1 to 20 and press Enter."));
}

void blink(int times) {
  for (int i = 1; i <= times; i++) {
    digitalWrite(LED_PIN, HIGH);
    delay(150);
    digitalWrite(LED_PIN, LOW);
    delay(150);
    Serial.print(F("  blink "));   // debug print: shows progress inside the loop
    Serial.println(i);
  }
}

void loop() {
  if (Serial.available() > 0) {
    long n = Serial.parseInt();      // reads digits, stops at the first non-digit
    while (Serial.available() > 0) Serial.read();  // drop the rest of the line
    if (n < 1 || n > 20) {
      Serial.print(F("Out of range: "));
      Serial.println(n);
      return;
    }
    Serial.print(F("Blinking "));
    Serial.print(n);
    Serial.println(F(" times"));
    unsigned long start = millis();
    blink((int)n);
    Serial.print(F("Done in "));
    Serial.print(millis() - start);
    Serial.println(F(" ms"));
  }
}

↑↓ to move · Enter to open