[Arduino] How to debug any program with tracing

Have you ever been faced with an Arduino board that crashes for no apparent reason? Have you ever decode an ESP8266 (ESP32, etc.) exception stack trace and ended with more questions than answers? If so, let me talk to you about a bulletproof technique: the good-old “tracing” technique.

Tracing

What I call “tracing” is logging every relevant step of the program, so you quickly understand what went wrong.

In a sense, it’s like using a debugger to execute the program step by step, except that you cannot interact with the program, you can only view what happened.

Everybody does that already: you add a little Serial.print() here… another there… until you find what line causes a crash.

Everybody does that but, unfortunately, there are is facility to help us, so everyone rolls her custom solution. That’s why I created ArduinoTrace, a small library to trace Arduino programs with minimal effort.

Here is how you use the library:

#include <ArduinoTrace.h>

int someValue = 42;

void setup() {
    Serial.begin(9600);
    DUMP(someValue);
}

void loop() {
    TRACE();
}

The program above would print:

E:\MyProgram\MyProgram.ino:7: someValue = 42
E:\MyProgram\MyProgram.ino:11: void loop()
E:\MyProgram\MyProgram.ino:11: void loop()
E:\MyProgram\MyProgram.ino:11: void loop()
...

All you need to do is call TRACE() and DUMP(variable). Simple isn’t it?

Do you want to write TRACE() yourself?

This library is very simple; in fact, you could even write the two macros yourself.

I made a video that shows how to write your own TRACE() macro, because I believe it’s important to look under the hood.

The video shows how I used tracing to fix the latest bug in ArduinoJson and how it lead to the creation of ArduinoTrace.

A word of caution

As I say in the video, tracing is not an alternative to logging. Logging (most likely to an SD card) is something you do in production; whereas tracing is something you do during very short periods, while looking for a bug.

Also, tracing is not an alternative to unit testing; I only trace a program when I cannot reproduce the bug with a unit test, like the Flash memory issue I show in the video.

Moreover, there is a severe performance hit when you add traces: the program gets fat and slow. That’s another reason why you should always remove every traces before committing your source files.


Please check out ArduinoTrace, and don’t forget to add a GitHub star to help me get the word out! Thanks ;-)

CAUTION: At the time I wrote this article, the library was not yet available in the Arduino Library Manager. If it’s still the case, clone the project in the library folder as for any other library.