Programming an Arduino UNO is pretty easy – just open the Arduino IDE, load sketch, upload and done. But when experimenting or working with larger code, you may find that your program doesn’t work as intended.

And how do you solve that? The regular way is to check the program line by line and see if you find any bug, or maybe use Serial.print(); to know what the device is doing at a specific moment.

However, the professional way is to debug that program (execute it line by line with real time variable analysis, disassembly, etc.). To do that, you normally need a tool called debugger, like the Atmel-ICE. The problem is that they aren’t very cheap, as you can see in the following picture:

ATAtmel-ICE Price

And even if you buy it, it is a mess to set it up and working for an Arduino UNO. You’ll need to a cut a small soldered section called ‘RST EN’ to disable the reset capacitor and then set the DWEN fuse correctly, and much more.

However, there is a solution for that – you can debug an Arduino UNO board (and similar ones) without an external debugger and hardware setup/modifications.

Firstly, you’ll need to have Visual Studio Code installed. Then you need to install an extension called ‘PlatformIO’ (this enables support for MCUs on Visual Studio Code. Link to its website). After restarting VS code, you’ll find a new home icon on the bottom bar. Click on it.

Home button VS code

Then click on ‘New Project’ and configure it for your needs. When configured, open the platformio.ini file (if it’s not automatically opened) and add the following lines at the bottom of it:

debug_port = YOUR_ARDUINO_PORT lib_deps = jdolinay/avr-debugger
Code language: JavaScript (javascript)

(Obviously, change YOUR_ARDUINO_PORT with the port (COM*, /dev/tty*, etc.) in which your Arduino is connected)

Then, open src/main.cpp file and write (or copy) the desired code. For example, I’ve made an easy blink sketch:

#include <Arduino.h> void setup() { pinMode(LED_BUILTIN, OUTPUT); } void loop() { digitalWrite(LED_BUILTIN, HIGH); delay(500); digitalWrite(LED_BUILTIN, LOW); delay(500); }
Code language: Arduino (arduino)

After that, you will need to add the following lines:

#include <avr_debugger.h>
Code language: Arduino (arduino)

Below the #include <Arduino.h> one. Many tutorials say that you need to include avr8-stub.h instead, but there are some useful definitions in the avr_debugger.h header that the other one doesn’t have. However, if you want to use Serial functions, such as Serial.print(); you must include avr8-stub.h instead.

Then, at the beginning of the setup() function, write:

#ifdef __DEBUG__ dbg_start(); // use debug_init(); if you are using avr8-stub.h #endif
Code language: Arduino (arduino)

The #ifdef __DEBUG__ and #endif lines are optional, but those make that the code that enables debugging and blocks the normal execution is only run when debugging the sketch.

After adding those lines, the sketch should look like this:

#include <Arduino.h> #include <avr_debugger.h> void setup() { #ifdef __DEBUG__ dbg_start(); #endif pinMode(LED_BUILTIN, OUTPUT); } void loop() { digitalWrite(LED_BUILTIN, HIGH); delay(500); digitalWrite(LED_BUILTIN, LOW); delay(500); }
Code language: Arduino (arduino)

After that, open the ‘Debug’ section (on the left) and click on the icon. Wait a few seconds and the debugging session sould begin.

PIO Debug

And… you’re done! Use the controls on the upper part of the window to debug:

Continue debugging
Continues the debugging until the next breakpoint
Next Debugging
Jumps to the next instruction
In Debugger
Jumps into the function that is being executed
Out Debugger
Exists the function that is currently being executed (it’s the opposite of the previous button)
Relaunch Debugger
Relaunches the program with all the modifications that have been done during the debugging
Quits the debugging

You can set/remove breakpoints by clicking on the left of the line numbers.

On the left side of the screen (on the debug section) you can control the variables, look for a specific memory address, etc. And you can use the bottom terminal to run a specific command (on GDB).

And that’s pretty much all for this tutorial. If you like it, please share it with anyone who may be interested in this kind of things. Thanks!

Useful links:

Categories: Tutorials


A junior open-source developer on GitHub ( and owner of this website ( His favorite programming language is C++, followed by C, C# and Java.


Leave a Reply

Avatar placeholder