Electronic – arduino – How to debug an Arduino sketch

arduinodebugging

I started coding for Arduino very recently. And these bugs in the code are killing me. As there is no hardware debugger in the Arduino, serial.print() is my only resort. What are the methods/practices you implement to debug Arduino code?

Best Answer

Modularity is your friend. Write your main loop to do its thing by calling functions, which call functions, ..., until the level at which your functions would be simple. Start with the main loop and the next level down, make stub functions; either empty:

function foo(){
    ;
}

or fake:

function read_temperature(){
    return(95);
}

, that do nothing but return whatever the calling level needs for it to be able to continue. When that level works, move down a level and start filling in simple code that likewise calls stub functions. Gradually un-stub a function at a time until you have a working application.

To debug a function that returns a bad value, or to create one without any influence from the rest of your application, you can build scaffolding - a simple sketch that just feeds the function some example values, and within the function, print out parameter values and some intermediate values, until you gain some insight into what part of the function is failing. I've even made faking-functions that prompt me on the terminal for a value to return. (Obviously this technique can only work if the system can tolerate the relatively glacial speed of us humans! Another use for scaffolding.)

Stubbing works especially well to stand in for functions that interface to hardware, allowing you start bringing up the application before you have to dive into data-sheets, timing issues, and other minutiae (like, not having the parts!) that might otherwise stall your progress.

Speaking of timing issues, toggling an output pin at a particular point in your program, such as entry to and exit from an ISR, gives you a square wave at the Arduino pin whose frequency or duty cycle can give you some insight into the internal timing of your program. The direct port-I/O form, e.g.,

PORTC ^= 0x01;

, will distort the timing less than calling digitalWrite(). Useful if you have a 'scope handy, or one of the DMMs with the ability to measure frequency and/or duty-cycle.

Similarly, you can use an analog output pin to output a numerical value to your meter from inside the program without disturbing the timing too much or bloating the code with the serial I/O functions. Use the direct I/O forms here, too.