Debugging für den Arduino UNO mit Atmel Studio

Über den Beitrag

In meinem letzten Beitrag hatte ich eine Schnelleinführung in Atmel Studio 7 gegeben. Die Möglichkeit zum Debuggen ist beim Arbeiten mit Atmel Studio ein großer Vorteil gegenüber der Arduino IDE. Das Programmieren in C hingegen kann für eingefleischte Arduino Anhänger ein wenig abschreckend sein. Der eine oder andere möchte deswegen wahrscheinlich weiterhin den Arduino UNO und die „Arduinosprache“ nutzen, aber trotzdem Debugging für den Arduino einsetzen können. Die guten Nachrichten:

  • es geht, ihr könnt den Arduino UNO mit Atmel Studio programmieren
  • bestehendende Arduino Sketche könnt ihr importieren
  • ihr könnt Variablen verfolgen, den Sketch schrittweise ausführen und Breakpoints setzen

Und was sind die schlechten Nachrichten?

  • ihr braucht einen debuggingfähigen Programmer und die sind nicht ganz billig
  • es ist ein kleiner Hardwareeingriff am Arduino notwendig, den ihr auch wieder rückgängig machen müsst, wenn ihr wieder per Arduino IDE programmieren wollt
  • wenn der Arduino Sketch Bibliotheken enthält, gibt es je nach Art der Bibliothek ein paar Dinge zu beachten – aber dafür gibt es ja diesen Beitrag!

Wie man Atmel Studio installiert, habe ich in meinem letzten Beitrag beschrieben. Über verschiedene Programmer für Atmel Studio hatte ich in meinem vorletzten Beitrag geschrieben. Beide Themen werden deshalb hier ausgelassen. 

Debugging für den Arduino Uno vorbereiten

Hinweis: lest am besten erstmal den ganzen Beitrag durch und entscheidet dann, ob ihr den gleich folgenden Eingriff vornehmen wollt. Es besteht die potentielle Gefahr, dass ihr ihn nicht mehr rückgängig machen könnt. In diesem Fall könnt ihr den Arduino nicht mehr über die Arduino IDE nutzen.   

Die Art und Weise wie der Arduino UNO bzw. die Arduino IDE mit dem Reset am ATMega328P umgeht, ist leider unverträglich mit Atmel Studio, was mit dem speziellen Bootloader des Arduino zusammenhängt. Das wäre an sich kein Problem, da man Bootloader überschreiben kann, allerdings hat diese Besonderheit Konsequenzen in der Beschaltung des Arduino UNO Boards. Es ist aber recht einfach, diese Hürde zu beseitigen.

Wenn ihr auf euren Arduino UNO schaut, dann findet ihr rechts neben dem 16 MHz Oszillator zwei Lötpunkte in einem weiß umrandeten Bereich mit der Beschriftung „RESET EN“. Wenn ihr noch genauer hinschaut, dann seht ihr, dass die beiden Lötpunkte über eine schmale Leitung verbunden sind. Diese Leitung müsst ihr mit einem Rasiermesser, Skalpell o.ä. trennen (Vorsicht!). Ich habe, weil ich ungeduldig war und nichts anderes zur Hand hatte, ein nicht mehr ganz neues Cuttermesser genommen. Ging auch, ist aber eigentlich zu grob. 

Debugging für den Arduino erfordert einen kleinen Schnitt.
Die Leitung zwischen den Lötpunkten muss gekappt werden

Wie mache ich das wieder rückgängig?

Da gibt es drei Möglichkeiten:

  1. Man kann natürlich die Lötpunkte einfach zusammenlöten. So kann man allerdings nicht beliebig hin- und herwechseln.
  2. Ich habe an ein paar Stellen gesehen, dass sehr geschickte Leute sich zwei Pins aufgelötet haben, die sie dann nach Bedarf mit einem Jumper verbinden.
  3. Gar nicht. Man investiert in einen Zweit-Arduino UNO, den man nur für Atmel Studio benutzt. Diese Variante habe ich gewählt. Schließlich bekommt man so ein Teil für unter zehn Euro. Außerdem muss man für jeden Wechsel zusätzlich den Bootloader austauschen (siehe weiter unten) und das ist mir zu mühsam. 

Nicht alle UNO Versionen bzw. Klone funktionieren

Das Debugging für den Arduino mittels Atmel Studio funktioniert hardwareseitig nur mit den UNOs, die den ATmega328P in der DIP Variante haben. Mit der folgenden Variante geht es nicht bzw. zumindest ich weiß nicht wie es geht:

Debugging für den Arduino geht nur an den Modellen mit DIP28 Versionen des ATmega328P.
Mit dieser Arduino UNO Version geht die Steuerung per Atmel Sudio (meines Wissens) nicht

Ein Anwendungsbeispiel

An einem praktischen Beispiel möchte ich Schritt für Schritt zeigen, wie man einen Sketch einschließlich Bibliotheken in Atmel Studio importiert.

Verschiedene Arten von Bibliotheken

Einen einfachen Arduino Sketch ohne Bibliotheken kann man ziemlich leicht mit Atmel Studio 7 auf den Arduino UNO hochladen. Dazu gibt es z.B. ein Youtube Video von Microchip (zu denen Atmel gehört). Bibliotheken einzubinden ist eigentlich auch einfach – wenn man weiß worauf man achten muss. Der erste Punkt ist, dass es unterschiedliche Bibliotheken gibt. Das sind auf der einen Seite diejenigen, die der Arduino Spezifikation für Bibliotheken entsprechen. Erkennbar sind sie z.B. daran, dass neben der oder den „.h“ und „.cpp“ Dateien auch eine Datei namens „library.properties“ vorhanden ist. Andere Libraries, die z.B. nur aus „.h“ und „.cpp“ Dateien bestehen, können auch eingebunden werden, aber auf einem anderen Weg. Solche Bibliotheken sind meist älter, nicht speziell für Arduino konzipiert oder der Autor war zu bequem.

Ein Beispielsketch

In meinem Beispielsketch werden LEDs über den Port A eines MCP23017 Portexpander geschaltet. Der Sketch verwendet die Wire Bibliothek, da der MCP23017 per I2C angesprochen wird. Zusätzlich verwendet der Sketch eine selbstgeschriebene Bibliothek (MCP23017), die nicht der Arduino Spezifikation entspricht. Die Bibliothek funktioniert trotzdem problemlos innerhalb der Arduino IDE.

#define MCP_ADDRESS 0x20 // (A2/A1/A0 = LOW) 
#include <Wire.h> 
#include <MCP23017.h> 
MCP23017 myMCP(MCP_ADDRESS,5); 
int wT = 1000; // wT = waiting time

void setup(){ 
  Wire.begin();
  myMCP.Init();  
  myMCP.setPortMode(B11111111, A); 
  delay(wT);
}

void loop(){ 
  myMCP.setAllPins(A, ON); 
  delay(wT);
  myMCP.setAllPins(A, OFF);
  delay(wT);
  myMCP.setPin(0, A, ON); 
  delay(wT); 
  myMCP.setPin(4, A, ON);
  delay(wT);
  myMCP.setPin(7, A, ON); 
  delay(wT);
} 

 

Die Schaltung zum Beispielsketch

Es kommt mir nur darauf an, das Prinzip des Imports zu erklären, aber der Vollständigkeit halber hier noch die Schaltung zu dem Beispiel:

Debugging für den Arduino - Fritzing Schema der Beispielschaltung
Beispielschaltung
Debugging für den Arduino - Beispielschaltung mit AVR Dragon als Programmer
Beispielschaltung mit AVR Dragon als Programmer

Wenn ihr genau dieses Beispiel nachbauen wollt, dann ist hier der Link zu meinem Beitrag in dem ich den MCP23017 und die Bibliothek behandele. Ihr könnt die Bibliothek auch hier direkt von Github herunterladen. Alternativ könnt ihr natürlich irgendeinen anderen Sketch wählen der Bibliotheken enthält.

Ich werde die MCP23017 Bibliothek demnächst überarbeiten, so dass sie der Spezifikation entspricht. Wenn ihr dann immer noch genau dieses Beispiel nachvollziehen wollt, dann benennt einfach die Datei „library.properties“ zwischenzeitlich um, damit Atmel Studio sie nicht mehr als Arduino Bibliothek identifiziert.

Import des Sketches und der Bibliotheken in Atmel Studio

Genug der Vorbereitungen, jetzt geht es in Atmel Studio 7. Als Erstes legt ihr ein neues Projekt an.

Debugging für den Arduino - Neues Projekt in Atmel Studio anlegen

Im nächsten Schritt wählt ihr „Create Project from Arduino Sketch“ und gebt dem Projekt einen Namen (spätere Umbenennung ist komplexer als man meinen möchte).

Debugging für den Arduino - hier wählt die Option des Arduino Sketch Imports

Wählt den Sketch aus, also die „.ino“ Datei und das Board. 

Debugging für den Arduino - Auswahl des zu importierenden Sketches

Es dauert ein kleines bisschen, dann ist der Sketch importiert und erscheint mit ein paar von Atmel Studio generierten Kommentaren. 

Debugging für den Arduino - der ausgewählte Sketch im Atmel Studio Programmeditor

Wären nicht die beiden Bibliotheken einzubinden, wärt ihr jetzt schon fertig. Probiert mal „Build Solution“ aus: 

Build Solution

Ihr werdet die folgende Fehlermeldung bekommen: 

Fehlermeldung - Wire.h Bibliothek wird vermisst.

Einbinden von Bibliotheken

Einbinden spezifikationsgerechter Bibliotheken

Im ersten Schritt wird die Wire Bibliothek eingebunden. Dazu geht ihr in das Solution Explorer Fenster und macht einen Rechtsklick auf den Eintrag, der den Namen des eingebundenen Arduino Sketches trägt.

Auswahl des Sketches im Solution Explorer

Dann wählt Ihr „Add Arduino Library“… 

Arduino Bibliothek hinzufügen

… und im nächsten Schritt macht in der Auswahlliste einen Haken bei „Wire“. In dieser Liste tauchen nur die spezifikationsgerechten Bibliotheken auf. 

Auswahl der Wire Bibliothek aus der Bibliotheksliste

Wenn ihr jetzt nochmal auf „Build Solution“ geht, wird nun erwartungsgemäß die MCP23017 Bibliothek vermisst. 

Jetzt wird die MCP23017 Bibliothek vermisst

Einbinden nicht spezifikationsgerechter Bibliotheken

Für diesen Fall geht ihr wieder in das Solution Explorer Fenster und macht einen Rechtsklick auf den Eintrag, der den Arduino Sketch Namen trägt. Dann wählt „Add“ und dann „Existing Item…“. 

Auswahl nicht spezifikationsgerechter Bibliotheken

Nun geht ihr zu der Stelle an der eure einzubindende Bibliothek liegt. Markiert die „.cpp“ und „.h“ Dateien. Wenn ihr die Schaltfläche „Add“ unten rechts aufklappt, könnt ihr zwischen „Add“ und „Add As Link“ wählen. Beides hat seine Vor – und Nachteile. „Add As Link“ ist platzsparender, außerdem wird man immer die aktuellste Version der Bibliothek einbinden. Aber manchmal gibt es auch Gründe warum man genau das nicht will. 

Auswahl der h und cpp Dateien der Bibliothek

Wählt man „Add“ dann sieht man im Solution Explorer die importierten Dateien, wählt man „Add As Link“, dann sieht man die Links:

Importierte Bibliotheken
MCP23017.h und MCP23017.cpp liegen im Ordner „src“
Links zu importierten Bibliotheken
Hier liegen nur die Links im Ordner „src“

Die nächste wichtige Maßnahme ist, dass man im Programm die „< >“ Klammern hinter dem #include für diese Bibliothek durch Anführungszeichen ersetzt. 

Liegt die Header („.h“) Datei physikalisch im „src“ Ordner, wird sie über ihren Namen gefunden. Wurde nur der Link importiert, dann muss man den Pfad zu dem Ort angeben, wo sie wirklich liegt. 

Für Bibliotheken, die im Ordner „src“ liegen
Für Bibliotheken, die nur Links im Ordner „src“ haben

Jetzt geht nochmal auf „Build Solution“ und – siehe da – es gibt keine Fehlermeldung mehr. 

Debugging für den Arduino nutzen

Nun könnt ihr die Früchte eurer Arbeit ernten und Debugging für den Arduino nutzen, z.B. das Programm schrittweise ausführen, Breakpoints setzen, Variablen- und Registerinhalte verfolgen usw. Hier möchte ich nur kurz zeigen wie man in den debugWire Modus wechselt und Breakpoints setzt. Für die anderen Optionen schaut in meinen vorherigen Beitrag

Breakpoints, also Punkte an denen das Programm stoppt, setzt man einfach mit einem Klick auf die graue Leiste neben dem Programmcode. Sie erscheinen als roter Punkt. Ein nochmaliger Klick auf einen Breakpoint löscht diesen wieder. Das Programm stoppt übrigens vor der Ausführung der markierten Zeile. 

Debugging für den Arduino durch Breakpoints

Geht in der Symbolleiste auf Tools (das Hammersymbol). Dann wählt euren Programmer und als Interface „debugWIRE“.

Programmer und debugWIRE zum Debugging für den Arduino wählen

Klickt auf „Start Debugging and Break“ (das Play-Pause Zeichen):

Die folgende Fehlermeldung wird mit „Yes“ geschlossen. 

Fehlermeldung: debugWIRE benötigt aktivierten DWEN Fuse

Folgt der nächsten Anweisung und trennt den Programmer vom Arduino, unterbrecht einmal kurz die Stromversorgung vom Arduino und schließt den Programmer wieder an. Ich spare mir Schritt 1 und 3 immer und habe noch nie Probleme bekommen – nachmachen auf eigene Gefahr. Dann klickt auf OK.

Meldung von Atmel Studio: Prozedur um debugWIRE zu aktivieren

Das Programm startet um gleich wieder zu stoppen.

Erster Programmstop beim Debugging

Geht ihr nun auf „Continue“…

Fortsetzen des Debuggings

… läuft das Programm weiter bis zum ersten Breakpoint. Mit jedem weiteren „Continue“ geht ihr zum nächsten Breakpoint. In Kombination mit dem Verfolgen von Variableninhalten hat man so ein sehr effizientes Werkzeug zur Fehlerfindung. Gerade bei größeren Sketchen kann die Fehlerfindung länger dauern, als man für die Programmierung bis dahin gebraucht hat. 

Debugging für den Arduino in Action - Stop bei den Breakpoints

Debugging für den Arduino rückgängig machen

Um den Arduino UNO wieder mit der Arduino IDE programmieren zu können, sind vor der Wiederherstellung des „RESET EN“ Kontaktes auf dem Arduino Board noch weitere Einstellungen im ATmega328P rückgängig zu machen. Tut man das nicht, erhält man bei dem Versuch Programme hochzuladen solche Fehlermeldungen:

Debugging für den Arduino - leider muss man die Einstellungen auch wieder rückgängig machen, sonst bekommt man diese Fehlermeldungen

Hier nun die Prozedur. Beendet als Erstes den debugWIRE Modus über 

Debug –> Disable debugWIRE and Close

Beenden des Debugging Modus mit Disable debugWIRE and Close

Dann wechselt im Toolbereich in den ISP Modus:

Wechsel in den ISP Modus

Im nächsten Schritt geht ihr auf „Device Programming“ (das Symbol mit IC und Blitz). Dort klickt auf „Apply“. Über die „Read“ Schaltflächen könnt ihr die Signatur lesen und die Spannung am Arduino ermitteln. 

Wechsel in das Device Prorgramming Fenster

Wählt dann „Fuses“ und tragt die unten markierten Fuse Register Werte für EXTENDED, HIGH und LOW ein. Nun klickt auf „Program“. Wenn alles gut geht, sollte unten links ein „Verify Registers…OK“ auftauchen. 

Änderung der Fuse Register Adressen

Nun muss der Arduino Bootloader wieder auf den ATmega328P gebrannt werden. Dazu geht auf „…“ (rot umrandet). 

Den Arduino Bootloader zurückbringen

Der richtige Bootloader ist „optiboot_atmega328.hex“. Ihr findet ihn, ausgehend vom Arduino Installationspfad, unter hardware\Arduino\avr\bootloaders\optiboot

optiboot_atmega328 wählen

Klickt nun auf „Program“. Dann stellt den „RESET _EN“ Kontakt auf dem Arduino Board wieder her. Aber mal ehrlich, allzu oft möchte man so nicht hin- und herwechseln. Ich persönlich gebe dann doch lieber ein paar Euro für einen Zweit-Arduino aus. 

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.