Einfacher Arduino-Debugger
Zum Testen und Auffinden von Fehlern in Sketche ist es oft erforderlich, Haltepunkte zu setzen und Zwischenergebnisse und/oder Laufzeiten anzuzeigen, was als "debuggen" bezeichnet wird. Da solche Funktionen von der Arduino-IDE nicht zur Verfügung gestellt werden, habe ich zur Fehlersuche entsprechende Funktionen, vor allem also Ausgaben am Seriellen Monitor in den jeweiligen Sketch eingebaut, die dann, wenn der Sketch funktionierte, entweder wieder gelöscht oder auskommentiert werden mussten.
Angeregt durch ein Youtube-Video ("Debugging in der Arduino IDE" von "Der Hobbyelektroniker" https://www.youtube.com/watch?v=MOJGBwsPD7I) habe ich mir nun eine Bibliothek mit Makros zusammengestellt, die mir das Debuggen erleichtern sollen. Durch Auskommentieren einer einzigen Textzeile zu Beginn eines Sketches können alle eingebauten Debug-Makros wieder unwirksam gemacht werden und der zum Debuggen benötigte Speicherplatz wird wieder freigegeben.
Makro-Library MyDebug für Arduino:
Folgende Makros stehen derzeit zur Verfügung:
- Ausgabe von Text und Zahlen (Integer und Float-Zahlen mit 2 Kommastellen) am Seriellen Monitor
- Ausgabe von Text und Float-Zahlen mit Angabe der Anzahl der Kommastellen am Seriellen Monitor
- Ausgabe von bis zu drei Zahlen (Integer und Float-Zahlen mit 2 Kommastellen) mit definierten Trennzeichen
- Anhalten des Sketches bis Taste gedrückt wird
- Setzen von Delays
- Setzen von Zeitstempel in Milli- oder Mikrosekunden
- Ausgabe der Programmlaufzeit in Milli- oder Mikrosekunden seit dem Setzen des letzten Zeitstempels
Die Makro-Library kann hier heruntergeladen werden:
Sollte den Debugger jemand verwenden oder testen, würde ich mich über eine Rückmeldung sehr freuen!
Version 1.0
Leider kann ich hier kein "h"-Files hochladen, daher zum Verwenden der Makro-Library das Suffix ".txt" aus dem Dateinamen entfernen und in einem neuen Verzeichnis mit dem Namen "MyDebug" im Sketchbook-Ordner im Ordner "libraries" speichern.
Makros der Library MyDebug
Hinweise:
Fast alle Makros zur Ausgabe am Seriellen Monitor gibt es in den Versionen mit (...PRINTLN...) oder ohne (...PRINT...) nachfolgendem Zeilenvorschub!
Nachfolgend werden folgende Abkürzungen für die Übergabeparameter der Makros verwendet:
- rate: Baudrate zum Seriellen Monitor
- txt: Text
- val: Interger- oder Float-Zahl
- dec: Anzahl Dezimalstellen bei Float-Zahlen
- dT: delay-Zeit
- cond: Bedingung
Initialisierung:
Im Deklarationsteil:
/*
#define DEBUG_ON .... Debugger ist aktiviert
//#define DEBUG_ON ... Debugger ist deaktiviert
*/#define DEBUG_ON //Debugger ist aktiviert (Definition muss vor der include-Anweisung stehen!)
#include <MyDebug.h>
Im setup:
DEBUG_BEGIN(rate)
Bemerkung: Kann entfallen, wenn die Funktion Serial.begin(xxxx) im Sketch verwendet wird.
Ausgabe von Zahlen und Zeichen am Seriellen Monitor:
Zeilenvorschub:
DEBUG_PRINTLN
Ausgabe von Text:
DEBUG_PRINT_TXT(txt)
DEBUG_PRINTLN_TXT(txt)
Ausgabe einer Zahl (Interger- oder Float-Zahl mit 2 Kommastellen):
DEBUG_PRINT_VAL(val)
DEBUG_PRINTLN_VAL(val)
Ausgabe von bis zu 3 Zahlen (Interger- oder Float-Zahlen mit 2 Kommastellen):
DEBUG_PRINT_PARAM(val1, val2, val3)
DEBUG_PRINTLN_PARAM(val1, val2, val3)
Beispiel:
x1 = 5;
x2 = 6;
DEBUG_PRINT_PARAM(x1, x2, 0);
Ausgabe am Seriellen Monitor.: 5 6 0
Bemerkung: Nicht definierte Parameter müssen mit 0 deklariert werden
Ausgabe von bis zu 3 Zahlen (Interger- oder Float-Zahlen mit 2 Kommastellen) mit definierten Trennzeichen:
DEBUG_PRINT_PARAM_DEL(val1, val2, val3, txt)
DEBUG_PRINTLN_PARAM_DEL(val1, val2, val3, txt)
Beispiel:
x1 = 5;
x2 = 6;
X3 = 7;
x4 = 8;
DEBUG_PRINT_PARAM_DEL(x1, x2, x3, " | ");
DEBUG_PRINT_PARAM_DEL(x4, 0 , 0, " | ");
Ausgabe am Seriellen Monitor.: 5 | 6 | 7 | 8 | 0 | 0 |
Bemerkung: Nicht definierte Parameter müssen mit 0 deklariert werden
Ausgabe einer Float-Zahl mit Angabe der Anzahl der Kommastellen:
DEBUG_PRINT_FLOAT(val, dec)
DEBUG_PRINTLN_FLOAT(val, dec)
Ausgabe von Text und einer Zahl (Interger- oder Float-Zahlen mit 2 Kommastellen):
DEBUG_PRINT_TXT_VAL(txt, val)
DEBUG_PRINTLN_TXT_VAL(txt, val)
Ausgabe von Text, einer Zahl (Interger- oder Float-Zahlen mit 2 Kommastellen) und einem Text:
DEBUG_PRINT_TXT_VAL_TXT(txt1, val, txt2)
DEBUG_PRINTLN_TXT_VAL_TXT(txt1, val, txt2)
Beispiel:
tempWert = getTemp(); //Einlesen eines Temperaturmesswertes eines Sensors
DEBUG_PRINTLN_TXT_VAL_TXT("Messwert1 = ", tempWert, " °C");
Ausgabe am Seriellen Monitor, z.B.: Messwert1 = 15.21 °C
Ausgabe von Text und einer Float-Zahl mit Angabe der Anzahl der Kommastellen:
DEBUG_PRINT_TXT_FLOAT(txt, val, dec)
DEBUG_PRINTLN_TXT_FLOAT(txt, val, dec)
Ausgabe von Text, einer Float-Zahl und einem Text mit Angabe der Anzahl der Kommastellen:
DEBUG_PRINT_TXT_FLOAT_TXT(txt1, val, dec, txt2)
DEBUG_PRINTLN_TXT_FLOAT_TXT(txt1, val, dec, txt2)
Beispiel:
luftDruck = BME.readPress(); //Einlesen des Luftdrucks eines Sensors
DEBUG_PRINTLN_TXT_FLOAT_TXT("Luftdruck = ", luftDruck, 1, "mBar");
Ausgabe am Seriellen Monitor: Luftdruck = 980.3 mBar
Ausgabe der Programmlaufzeit seit dem letzten gesetzten Zeit-Punkt in Millisekunden
DEBUG_PRINTLN_RUNTIME
Beispiel:
DEBUG_SET_TIMEPOINT;
for (byte i = 0; i < 127; i++) Serial.println(i);
DEBUG_PRINTLN_RUNTIME;
Ausgabe am Seriellen Monitor: Runtime = 8 ms
Ausgabe der Programmlaufzeit seit dem letzten gesetzten Zeit-Punkt in Mikrosekunden
DEBUG_PRINTLN_MICRO_RUNTIME
Beispiel:
DEBUG_SET_MICRO_TIMEPOINT;
strcpy(txt1, txt2);
DEBUG_PRINTLN_MICRO_RUNTIME;
Ausgabe am Seriellen Monitor: Runtime = 12 us
Sonstige Befehle:
Anhalten des Sketches und warten auf Tasteneingabe 'c' :
DEBUG_WAIT(txt, cond)
Beispiel:
DEBUG_WAIT("Haltepunkt 1", true);
Ausgabe am Seriellen Monitor:
Haltepunkt 1
Druecke 'c' fuer Weiter ...
Ausführen einer Delay-Funktion:
DEBUG_DELAY(dT)
Setzen eines Zeitstempels in Millisekunden
DEBUG_SET_TIMEPOINT
Bemerkung: siehe dazu Makro DEBUG_PRINTLN_RUNTIME
Setzen eines Zeitstempels in Mikrosekunden
DEBUG_SET_MICRO_TIMEPOINT
Bemerkung: siehe dazu Makro DEBUG_PRINTLN_MICRO_RUNTIME
Programmbeispiel mit Einsatz des Debuggers:
Nach Betätigung der Taste 'c' wird die for-Schleife durchlaufen, wobei die Zwischenergebnisse der Schleife und die Gesamtlaufzeit angezeigt werden:
//Debugger Beispiel 1
//Code fuer Arduino
//Author Retian
//Version 1.0
/*
Die Anregung zum Debugger erhielt ich durch das Youtube-Video
"Debugging in der Arduino IDE" von "Der Hobbyelektroniker"
https://www.youtube.com/watch?v=MOJGBwsPD7I
*/
/*
#define DEBUG_ON .... Debugger ist aktiviert
//define DEBUG_ON ... Debugger ist deaktiviert
*/
#define DEBUG_ON //Debugger ist aktiviert (Definition muss vor der include-Anweisung stehen!)
#include <MyDebug.h>
int sum;
void setup() {
DEBUG_BEGIN(115200);
DEBUG_PRINTLN_TXT("*** Debugger-Test ***");
}
void loop() {
DEBUG_WAIT("Wartepunkt 1!", true);
DEBUG_SET_TIMEPOINT;
for (byte i = 1; i <= 9; i++)
{
sum += i;
DEBUG_PRINT_TXT_VAL_TXT("Durchgang ", i, ": ");
DEBUG_PRINTLN_TXT_VAL("Summe = ", sum);
}
DEBUG_PRINTLN_RUNTIME;
DEBUG_PRINTLN;
}
Programmspeicherbedarf:
Mit aktiviertem Debugger: 2240 Bytes
Mit deaktiviertem Debugger: 462 Bytes
Ausgabe am Seriellen Monitor mit eingeschaltetem Debugger:
Abbildung 1: Debugger-Ausgabe am Seriellen Monitor