Wie debugge ich eine Arduino-Skizze?

10

Ich habe vor kurzem angefangen, für Arduino zu programmieren. Und diese Fehler im Code bringen mich um. Da es im Arduino keinen Hardware-Debugger gibt, ist serial.print () mein einziger Ausweg. Welche Methoden / Praktiken implementieren Sie, um Arduino-Code zu debuggen?

0xakhil
quelle
Bitte werfen Sie einen Blick auf playground.arduino.cc/Main/DevelopmentTools für IDE- und Debugger-Tools
Dallo

Antworten:

8

Modularität ist dein Freund. Schreiben Sie Ihre Hauptschleife, indem Sie Funktionen aufrufen, die Funktionen aufrufen, ... bis die Ebene erreicht ist, auf der Ihre Funktionen einfach wären. Beginnen Sie mit der Hauptschleife und der nächsten Ebene nach unten, und machen Sie Stub-Funktionen. entweder leer:

function foo(){
    ;
}

oder falsch:

function read_temperature(){
    return(95);
}

, die nichts anderes tun, als alles zurückzugeben, was die aufrufende Ebene benötigt, um fortfahren zu können. Wenn diese Ebene funktioniert, gehen Sie eine Ebene nach unten und geben Sie einfachen Code ein, der ebenfalls Stub-Funktionen aufruft. Deaktivieren Sie nach und nach eine Funktion, bis Sie eine funktionierende Anwendung haben.

Um eine Funktion zu debuggen, die einen fehlerhaften Wert zurückgibt, oder um eine Funktion zu erstellen, die keinen Einfluss auf den Rest Ihrer Anwendung hat, können Sie ein Gerüst erstellen - eine einfache Skizze, die der Funktion nur einige Beispielwerte zuführt und innerhalb der Funktion Parameterwerte druckt und einige Zwischenwerte, bis Sie einen Einblick erhalten, welcher Teil der Funktion fehlschlägt. Ich habe sogar Fälschungsfunktionen erstellt, die mich auf dem Terminal auffordern, einen Wert zurückzugeben. (Offensichtlich kann diese Technik nur funktionieren, wenn das System die relativ eiszeitliche Geschwindigkeit von uns Menschen toleriert! Eine andere Verwendung für Gerüste.)

Stubbing eignet sich besonders gut für Funktionen, die mit der Hardware verbunden sind. So können Sie die Anwendung aufrufen, bevor Sie sich mit Datenblättern, Zeitproblemen und anderen Kleinigkeiten (z. B. ohne Teile!) Befassen müssen, die andernfalls möglicherweise zum Stillstand kommen dein Fortschritt.

Wenn Sie von Timing-Problemen sprechen und einen Ausgangs-Pin an einem bestimmten Punkt in Ihrem Programm umschalten, z. B. beim Ein- und Ausstieg aus einem ISR, erhalten Sie eine Rechteckwelle am Arduino-Pin, deren Frequenz oder Arbeitszyklus Ihnen einen Einblick in das interne Timing geben kann Ihres Programms. Das direkte Port-I / O-Formular, z.

PORTC ^= 0x01;

, verzerrt das Timing weniger als das Aufrufen digitalWrite(). Nützlich, wenn Sie ein Oszilloskop zur Hand haben oder eines der DMMs mit der Fähigkeit, Frequenz und / oder Arbeitszyklus zu messen.

In ähnlicher Weise können Sie einen analogen Ausgangspin verwenden, um einen numerischen Wert aus dem Programm heraus an Ihr Messgerät auszugeben, ohne das Timing zu stark zu stören oder den Code mit den seriellen E / A-Funktionen aufzublähen. Verwenden Sie auch hier die direkten E / A-Formulare.

JRobert
quelle
6

Ich benutze Serial.print () und lasse LEDs blinken.

Das ist so ziemlich alles, was Sie tun können.

Außerdem stelle ich sicher, dass der Code lesbar und leicht verständlich ist. Teilen Sie die Dinge in einfache Schritte auf und erstellen Sie Funktionen für jeden Schritt, damit Sie die genaue Abfolge der Ereignisse sehen können.

Majenko
quelle
5

3 Andere Techniken:

  • Bauen Sie die Funktionalität eines Programms auf, indem Sie in jeder Phase langsam testen. Auf diese Weise treten jeweils nur wenige Fehler auf.

  • Erstellen Sie das Programm um einen Befehlsinterpreter herum, damit Sie wie hier beschrieben gleichzeitig mit Abschnitten arbeiten können .

  • Pulsieren Sie zu wichtigen Zeiten aus und verwenden Sie ein Zielfernrohr.

russ_hensel
quelle
3

Das Visual Micro- Plugin für Visual Studio bietet Arduino Debug . Enthält Quellcode-Trace und -Pause ermöglicht auch das "Überwachen" und / oder Ändern von Ausdrücken und Variablen.

Geben Sie hier die Bildbeschreibung ein

Visual Micro
quelle
1
Beachten Sie, dass dies über automatisch generierte serielle Ausdrucke erfolgt, die in Ihren Code eingefügt werden.
per1234
Das ist richtig, außer dass die seriellen oder WLAN-Ausdrucke und -Lesungen in eine temporäre Kopie des Codes eingefügt werden, nicht in den tatsächlichen Code! In den visualmicro.com-Dokumenten wird alles klar erklärt, und für die wenigen, die über Hardware-Debugger verfügen (normalerweise nicht für Uno usw.), werden diese ebenfalls unterstützt. Jede Methode hat ihre eigenen Vor- und Nachteile.
Visual Micro
Aus Debugger für Arduino : "Das Durchlaufen des Codes wurde nicht unterstützt, und es basierte auf verstecktem Code, der vor dem Erstellen in Ihr Programm eingefügt wurde, um mit dem Debugger zu kommunizieren."
Peter Mortensen
Das ist richtig. Es vermeidet, dass Benutzer serielle Ausdrucke hinzufügen müssen, ermöglicht die Aktualisierung benannter Variablen, während die CPU ausgeführt wird, zeigt Grafiken und digitale Pins usw. Es unterscheidet sich von einem Hardware-Debugger, ist jedoch schnell und einfach und bietet weitere Vorteile. Dies alles ist auf visualmicro.com gut dokumentiert. Bitte lesen Sie es durch. Wenn Ihr Board gdb unterstützt oder atmel studio verwendet, gibt es natürlich auch andere Debug-Optionen. Es hängt alles von Ihrem Fachwissen und Ihrer Hardware ab. Wenn Sie echtes Arduino haben, können Sie im Atmel Studio Arduino mit Atmel Debug oder Sim kombinieren.
Visual Micro
2

Ausgehend von Luxus-Tools wie ARM oder anderen Plattformen (AVR, PIC mit anständigen Tools) stimme ich zu, dass die Arduino-Debugging-Funktionen zu begrenzt sind. Aber es ist ein Starter-Tool mit geringem Einstieg.

Serial.print () ist dein Freund. An meinem speziellen Projekt (College) waren keine LEDs angebracht, also ist es Serial.print (). Wenn ich testen möchte, ob der Code die Anweisungen ordnungsgemäß durchläuft, platziere ich normalerweise Serial.print ("A"). , dann gehe zu B, C usw. oder so durch den Abschnitt, den ich debugge. Ich vergleiche die Debug-Buchstaben mit dem, was ich erwartet habe.

Ansonsten gibt es keine Haltepunkte oder Codeschritte. Arduino ist nichts anderes als ein Board mit einem AVR-Atmega-Chip, einer Bootloader + -Entwicklungsumgebung und einer Menge Softwarebibliotheken. Leider schränkt die Arbeit mit einem Bootloader die Debugging-Funktionen ein.

Hans
quelle
0

Um die Verwendung serial.printkontrollierter zu gestalten, können Sie eine globale boolesche Variable definieren, um das Debuggen ein- und auszuschalten. Alle Zeilen von serial.printwerden in eine ifAnweisung eingeschlossen, die nur ausgeführt wird, wenn das Debug-Flag aktiviert ist. Auf diese Weise können Sie die Debug-Zeilen auch dann im Code belassen, wenn Sie fertig sind. Stellen Sie jedoch sicher, dass Sie das Debug-Flag später auf OFF setzen.

Gabby
quelle
0

Verwenden Sie besser als direkt serial.print Makros. Beispiel:

#ifdef TRACE1
#define trace1(s) serial.print(s)
#define traceln1(s) serial.println(s)
#else
#define trace1(s)
#define traceln1(s)
#endif

Verwenden Sie es so:

function doIt(param1, param2) {
    trace1("->doIt("); trace1("param1: "); trace1(param1); trace1(" param2: "); trace1(param2); traceln1(")");

    ...

    traceln1("<-doIt");
}

Möglicherweise haben Sie unterschiedliche Ablaufverfolgungsstufen (#ifdef TRACE2 ...)mit weiteren Details.

Und Sie könnten das Makro "F" verwenden (trace1(F("param1"));). Das Makro "F" verhindert, dass die Zeichenfolge die extrem begrenzte Menge an SRAM verwendet.

Mangar
quelle
0

Blinken Sie LEDs, drucken Sie Dinge auf die serielle Schnittstelle und schreiben und debuggen Sie jeweils kleine Codeabschnitte, manchmal nur wenige Zeilen.

Es gibt Zeiten, in denen Sie modularisieren können. Wenn Sie beispielsweise in C eine Berechnungsfunktion entwickeln und testen können, die beispielsweise die Hardware eines Host-Computers oder eines anderen Prozessors nicht berührt, wickeln Sie die Funktion mit einem Prüfstand ein, um sie mit Eingängen zu versorgen und die Ausgaben zu überprüfen usw.

Eine andere ähnliche Möglichkeit könnte darin bestehen, einen Befehlssatzsimulator zu verwenden, wenn Sie Zugriff auf einen haben (wenn nicht, ist dies ein sehr lehrreiches und lohnendes Projekt, nachdem Sie einige davon durchgeführt haben, können Sie an einem oder zwei Wochenenden einen herausholen). Noch besser, wenn jemand einen Verilog- oder VHDL-Klon des Prozessors hat ( z. B. OpenCores ), können Sie GHDL, Verilator oder Icarus Verilog ausprobieren . Es könnte nah genug sein, um die Peripheriegeräte einzuschließen, an denen Sie interessiert sind, und Sie können einen Einblick in den Signalpegel erhalten, was im Inneren vor sich geht.

Zugegeben, es ist wahrscheinlich kein perfekter Klon, aber es könnte gut genug sein. Mit Verilator ist es wirklich sehr einfach, Peripheriegeräte in C / C ++ zu erstellen, sodass Sie simulieren können, an was auch immer Ihr AVR-Gerät angeschlossen ist.

UART-Ausgang und blinkende LEDs und / oder blinkende GPIO-Leitungen und Verwendung eines Oszilloskops oder Voltmeters. Der Schlüssel, um nicht verrückt zu werden, ist das Schreiben und Debuggen kleiner Codeabschnitte. Es ist besser, 10 Zeilen gleichzeitig zu schreiben und 100 Tests als 1000 Zeilen durchzuführen und zu versuchen, sie alle auf einmal zu debuggen. Insbesondere wenn Sie herausfinden, dass die meisten Datenblätter und Programmierer Referenzhandbücher für Hardware nicht immer korrekt sind. Es ist immer etwas Hacking erforderlich.

Oldtimer
quelle