Source: https://mokxi.com/learn/debug-arduino-code
Updated: 2026-09-27

Learn

# How to debug Arduino code, from Serial prints to breakpoints

Written by the Mokxi team, updated September 27, 2026

Try it now, no account Sign up free or see every lesson

- 192 parts on the bench
- 25 boards running now
- 1.00x real time, on every board

Click to open it in the editor

A potentiometer on A0 sets an LED on pin 9. Open it, paste in the worked example, and turn the knob with the serial monitor open.

An Arduino has no screen, so when a sketch misbehaves you cannot see what it is thinking. The classic Uno and Nano cannot be stepped through in the Arduino IDE either: the IDE’s debugger supports certain newer boards, and not the AVR ones most classes and kits use. So most people debug with `Serial.print`, and it works well once you use it deliberately.

This page is a method for narrowing a bug down, then three tools: printing, plotting, and stopping the board on a line. The circuit above is an Uno with a potentiometer on A0 and an LED on pin 9, which is enough to show all three, including a real bug that only happens on an Uno.

## Make the bug small before you chase it

Write down what you expected and what happened instead, in one sentence each. "The LED should get brighter as I turn the knob, and it goes bright, then dark, then bright" is a bug you can test; "it does not work" is not.

Then shrink the problem. Check the wiring against the pin numbers in the code first, since that catches a large share of bugs. Comment out everything not involved, or copy the suspect part into a new sketch. Change one thing at a time and run again. A bug that survives in ten lines is a bug you will find; the same bug in three hundred is guesswork.

## Serial.print, done deliberately

Start the port in `setup()` with `Serial.begin`, and on a real board set the serial monitor to the same baud rate, or you get garbage characters. Print something once at the end of `setup()`. If that line appears again and again, the board is resetting, which usually means a motor or servo is pulling the supply down.

Label every value, so `button: pressed` rather than a bare `0`. Print when something changes, not on every pass through `loop()`, which floods the monitor too fast to read. And wrap the prints in a macro, so they can be switched off in one place instead of deleted and retyped when the bug comes back.

Labeled prints, on a change, behind one switch

## Printing takes time

Each character takes about a millisecond to send at 9600 baud, so a 20-character line costs about 20 milliseconds. A real Uno hides the first 64 bytes in a transmit buffer, but a sketch that prints on every pass fills it quickly and then waits on every character. Use 115200 baud, which is twelve times faster, and print less.

This is also why adding a print sometimes makes a bug vanish. If slowing the sketch down fixes it, the bug is about timing: a button read too fast, a sensor read before it is ready, or an interrupt racing the main loop. That is a clue, not a fix. Do not print inside an interrupt handler at all; set a flag there and print from `loop()`.

## A worked example: the average that goes negative

Here is a real bug. The sketch averages 64 readings of the potentiometer to smooth them out. With the dimmer circuit above and the knob at 100, it prints `total:6400 average:100`, which is right. Turn the knob to the middle, 512, and it prints `total:-32768 average:-512`. At the top, 1023, it prints `total:-64 average:-1`.

The prints make the cause visible: the total is wrong, so the averaging is not the problem. On an Uno an `int` is 16 bits and holds at most 32,767, and 64 readings of 1023 add up to 65,472, so the total wraps around to negative. The same sketch works on an ESP32, where an `int` is 32 bits, which is exactly the kind of difference that makes a bug look random. The fix is `long total = 0;`. Without printing the total, you would only see a bad average and would likely go looking in the wrong place.

The bug, and its one-word fix in the comment

## Plot numbers instead of reading them

A value that changes over time is easier to judge as a line. The Arduino IDE’s Serial Plotter and Mokxi’s Plot tab read the same format: numbers on one line separated by spaces or commas, each optionally labeled as `name:value`. The worked example above already prints in that form, so open the Plot tab and turn the knob, and you can watch the total fold over into negative numbers at the halfway point.

Printing a threshold next to a reading, as `reading:512 threshold:600`, draws the threshold as a flat line, so you can see exactly when a sensor crosses it and how noisy it is near the edge. That answers "why does my light flicker on and off at dusk" in one look.

## Stop the board on a line

In Mokxi you can stop any board with a breakpoint, the Uno included, because the chip is simulated rather than connected over USB. Click in the gutter to the left of a line number, and a red dot appears; press Run, and the board halts before that line runs. The whole circuit stops with it, so an LED stays exactly as bright as it was and `millis()` does not jump while you look.

The Debug tab then shows where the board stopped, its registers, and a watch list for global variables. Step over runs one line at a time. The watch list reads globals only, so while debugging it can help to make the variable you care about global. On the ESP32 and ESP8266, Pause and the watch list work, but breakpoints do not, since the browser compiler cannot build for those two chips. The breakpoint example below walks through it on an ESP32-C3.

## Questions

Can you debug an Arduino Uno with breakpoints?

Not with the Arduino IDE’s debugger, which does not support the AVR boards. The ATmega328P has a one-wire debug interface, debugWIRE, but it needs a separate hardware debugger. In Mokxi, breakpoints work on the simulated Uno directly.

Why does my serial monitor show garbage characters?

On a real board, the monitor’s baud rate does not match Serial.begin. Set both to the same number, such as 115200.

Why does adding Serial.print make my bug go away?

Printing slows the sketch down, so the bug depends on timing: a read that happens too early, a missing debounce, or a variable shared with an interrupt.

Should I leave debug prints in a finished sketch?

Switch them off rather than deleting them, with a DEBUG macro like the one above. They cost time and memory when on, and nothing when off.

Related

## Keep going

Arduino Compile Errors Explained, With the Fixes Arduino Potentiometer: analogRead and a Dimmer UART Serial Explained: Baud, Frames and the Wire Interrupts vs Polling on Arduino, Side by Side Measure It: Read a Circuit With a Scope and Plotter The debugger, in full The serial plotter Help: the serial monitor shows nothing The project page, with the full sketch

Sources

## Where the facts on this page come from

- Arduino: Debugging with the Arduino IDE 2, and the boards it supports
- Arduino reference: int is 16 bits on the Uno, 32 bits on others

## Build this for real

Open the editor, change a value and watch the number move with it. Nothing to install, and no account needed.

Start building Open the editor
