How To Debug Your Arduino
2019-03-21 | By Maker.io Staff
The Arduino range of microcontroller boards are incredibly useful in prototyping situations and can be used in many DIY and professional projects alike. However, one feature not available on the Arduino that other devices such as dedicated PIC and AVR circuits benefit from is debugging, which allows users to find problems with their code and then fix them. Here, we will learn how we can use simple code techniques to debug an Arduino!
The Hard Way
While Arduino boards are based on standard microcontrollers, such as the ATMega328, they use a boot loader, which is a special program located at the start of program memory. This boot loader, upon starting, will usually look at the USB or UART port for incoming data from a PC or other computing device. If specific signals are sent by the PC (often with the use of the RTS and DTR lines) the boot loader begins to load in bytes over the serial port (which represent bytes in program memory).
These bytes are then saved into program memory, and when all bytes have been transferred, the Arduino will then execute the code in program memory. This is how a PC can upload new programs to an Arduino without the need for a special programmer that connects to the ICSP lines. But since the boot loader itself is a program executed by the Arduino, and there is no dedicated programmer using the ICSP lines, the executing program cannot be stepped through or debugged.
Therefore, the only method for getting true debugging would be to use an external debugger that could halt the execution of the Arduino and then step through the assembly program line by line. But this causes another issue; you would not be able to debug the user-friendly C code but instead would be debugging raw assembler.
Unless an engineer can determine a way to link a debugger to the Arduino IDE, know where the boot loader sits, and understand how the program has been uploaded, the only option a debugger has left is to read the contents of all the memory (which is all in machine language).
The Easy Way
So, it is established that unless a dedicated programmer and debugging IDE are used, real debugging cannot be done. However, the Arduino does have some useful features that can be used to debug a program to try and find out where problems exist. One of the most useful tools for tracking down problems is the Hardware Serial Port that can be tied to a computer terminal -- just about anything can be printed to the screen.
For example, a variable could be printed to see the value of a loop counter, a string could be printed to see if a piece of code was executed, and the Serial input could even be used to inject values into a program to test functions. One of the simplest methods involves placing unique print string instructions at key locations in the code; if the code gets stuck in a specific place, the user will see that only some of the strings were printed. This can be used to isolate the exact code snippet that is causing problems, which can then be looked at more closely.
EXAMPLE 1 – DETERMINING IF A FUNCTION IS HALTING OR FREEZING THE ARDUINO
Serial.println("code got to part 1"); // Print this if the execution gets to here myFunction(); // Try to execute myFunction() Serial.println("code got to part 2"); // If myFunction does not freeze then print this anotherFunction(); // Try to execute anotherFunction() Serial.println("code got to the end"); // All the functions executed without stalling
EXAMPLE 2 – PRINTING THE VALUE OF A VARIABLE TO SEE IF ILLEGAL CHARACTERS ARE BEING PRINTED
for(int i = 0; str[i] != 0x00; i ++) { Serial.print(str[i]); // Print the character at i Serial.println(); // Print a new line Serial.println(i); // Print the value of i for checking }
EXAMPLE 3 – VALUE INJECTING FOR TESTING PWM OUTPUT
// Determine if the user has sent a value to write if(Serial.available() > 0) { // Get the integer value from the Serial port pwmTestValue = Serial.parseInt(); } analogWrite(4, pwmTestValue); // Write the PWM value to the digital output 4
Another useful feature is to try and compartmentalize code, so that each piece of code can be passed through a testing function and checked against an expected result. The program could pass a series of different inputs and the outputs checked; any errors would result in the Arduino printing an output error message or halting entirely.
These testing functions could then be placed into an external header file that keeps the debugging code separate from the main code, which can then be removed from the project in the final build. Such a method for debugging, however, is only helpful in scenarios where code can be compartmentalized, and the use of such as method may see the main code consist of functions (as opposed to readable code).
int myFunction(int i, int j); // A custom function that multiplies i and j together void setup() { // Testing myFunction for the correct answer if(myFunction(2, 2) != 4) { Serial.println("First test failed"); } // Testing myFunction for the correct answer if(myFunction(2, 8) != 16) { Serial.println("Second test failed"); } }
If the Serial Port is in use or testing functions are not particularly helpful, then the I/O can be used as inputs and outputs for debugging. LEDs connected to output ports, for instance, can be used to signal if the main loop is looping correctly or if a piece of code is being executed properly. Switches can be connected to interrupts, which can force the Arduino to execute a specific piece of code or even reset the whole system to get the Arduino out of an infinite loop.
Serial.println("code got to part 1"); // Print this if the execution gets to here myFunction(); // Try to execute myFunction() digitalWrite(4, HIGH); // Turn the LED on for one second here to indicate that it worked so far delay(1000); digitalWrite(4, LOW); anotherFunction(); // Try to execute anotherFunction() digitalWrite(4, HIGH); // Turn the LED on for two seconds here to indicate that it worked delay(2000); digitalWrite(4, LOW);
Have questions or comments? Continue the conversation on TechForum, DigiKey's online community and technical resource.
Visit TechForum