Arduino & ESP32 programmieren mit PlatformIO und Visual Studio Code

Die Arduino Entwicklungsumgebung kann nix, und das ist auch gut so. Denn diese Entwicklungsumgebung war dazu gedacht, die Einstiegshürde in die Microcontroller-Programmierung so einfach wie möglich zu halten und den Neuling nicht mit zu vielen Funktionen zu überfordern.

Ich gebe zu, ich bin professioneller Entwickler. Und mir fehlen in der Arduino Entwicklungsumgebung einige Funktionen, die mir den Spaß am Programmieren erhöhen. Daher ist die Arduino IDE für mich nicht ausreichend.

Stattdessen benutze ich PlatformIO! 

Was ist PlatfomIO

PlatformIO ist ein kostenloses Tool speziell für die Arbeit mit Microcontroller Systemen wie ESPs oder Arduino.

Es wird als Plugin in den ebenfalls kostenlosen Visual Studio Code Editor (kurz VS Code) installiert.

Dadurch, dass man also mit VS Code arbeitet, steht uns eine sehr mächtige Entwicklungsumgebung zur Verfügung, die viel mehr Funktionen bietet, als die Arduino IDE. Übrigens: Visual Studio Code ist nicht zu verwechseln mit Visual Studio (ohne Code), die große Software-Entwicklungs Platform. Ich finde die sehr ähnlichen Namen etwas unglücklich gewählt.

Wir werden jetzt einmal VS Code installieren. Dann zeige ich, wie man die PlatformIO Erweiterung in VS Code installiert. Und Parallel zu meinem Video, wo ich Arduinos und ESPs vergleiche, zeige ich, wie man mit PlatformIO ein Programm auf einen Arduino und auf einen ESP lädt.

Zunächst mal VS Code für euer Betriebssystem herunterladen: Visual Studio Code

Ich würde hier mal die Stabile Version von VS Code empfehlen.

Um PlatformIO zu installieren, gehen wir in den Extensions-Bereich, quasi ein App Store für VS Code Erweiterungen. Dort suchen wir nach der offiziellen platformIO Erweiterung, klicken installieren und warten die Installation ab.

Es poppen möglicherweise Empfehlungen auf, dass man noch zusätzliche empfohlene Plugins installieren sollte. Dabei geht es um Plugins für die C/C++ Programiersprache. Da das Arduino Framework ja C++ verwendet, macht die Installation absolut Sinn.

Projekt erstellen

Nun erstellen wir ein erstes Projekt in PlatformIO für das Arduino UNO Board. 

Dazu gehen wir auf die PlatformIO Home-Seite. Dort dann auf New Project. 

In dem Formular wählen wir einen Projekt Namen, wählen den Arduino UNO als Board aus und Arduino als Framework.

Location lasse ich immer auf default, das ist erstmal am einfachsten. Wenn ihr die Maus über das Fragezeichen bewegt, wird euch die default location angezeigt. Bei mir ist das mein Benutzerordner/Documents/PlatformIO/Projects/

Ein Klick auf OK, und das Projekt wird erstellt.

Bei PlatformIO sind die Projekte etwas anders Strukturiert als in der Arduino Entwicklungsumgebung. Schauen wir uns daher zunächst mal die Ordnerstruktur des leeren Projekts an.

Den Ordner TEST können wir erstmal vernachlässigen. Den benötigt man nur, wenn man mit Unit Tests arbeiten möchten.

SRC enthält alle Quellcode Dateien. Hier liegt auch unsere main.cpp.

INCLUDE kann verwendet werden, um header Dateien hier abzulegen.

Und LIB wird verwendet um projektspezifische Libraries abzulegen.

Die platformio.ini ist die Konfigurationsdatei für PlatformIO Projekte. Kommen wir aber später nochmal zu.

Uns interessiert jetzt erstmal nur der SRC Ordner, da hier die main.cpp liegt, die wir jetzt mit einem Doppelklick öffnen.

PlatfomIO füllt uns die main.cpp bereits mit der setup() und der loop() Methode.

Ausserdem muss ganz oben die Arduino.h Daten inkludiert werden. Das passiert in der Arduino-Entwicklungsumgebung automatisch im Hintergrund.

Ich füge hier den gleichen Code ein, den ich auch in meinem Video verwendet habe, bei dem ich Arduino Boards mit ESP Boards vergleiche.

Jetzt schauen wir uns noch diese unscheinbaren aber wichtigen Schalter hier unten an.

Das hier sind die Schalter, die zu PlatformIO gehören.

  • Das Haussymbol öffnet die PlatformIO Home Seite
  • Das Checkmark Symbol prüft den aktuellen Code auf Fehler.
  • Das Pfeil-Symbol prüft ebenfalls den Code und wenn kein Fehler gefunden wurde, lädt es den aktuellen Code auf das Board.
  • Der Mülleimer löscht alle bereits kompilierten Libraries. Diese würden dann beim nächsten Check oder Upload erneute kompiliert werden. So kann man ein Neu-Kompilieren erzwingen.
  • Das Steckdosen-Symbol öffnet die Serielle Konsole.
  • Und das letzte Symbol öffnet eine Shell, falls man z.B. manuelle PlatformIO oder Shell Befehle ausführen möchte.
  • Die beiden Bereiche ganz links sind nur für Git bzw. Versionskontrolle interessant.
  • Und dieser Schalter dazwischen listet uns Fehler und Warnungen auf, und präsentiert diese bei einem Klick in einer Übersicht. So kann man sich schnell zu bestimmten Fehlern im Code bewegen.

Unten rechts noch interessant:

  • Hier wird die Position des Cursors angezeigt.
  • Und hier kann man die Größe und Art der Einrückung im Code einstellen.
    Wenn ihr diesen Wert verändert, solltet ihr danach noch ein Format Document ausführen. Dazu im Quelltext mit rechts hineinklicken und dann Format Document wählen.

Gut nun wissen wir wie wir den Code hochladen. Dann lasset es es uns tun. 

Der Code wird kompiliert und hochgeladen. Und wir sehen, unsere LED blinkt. Hurra!

Jetzt nochmal mit ESP

Jetzt machen wir das ganze nochmal mit einem ESP32. Bevor ich den Arduino nun entferne, gehen wir vorher noch kurz auf den Devices Bereich von PlatformIO.

Hier werden alle Boards angezeigt, die PlatformIO entdeckt hat. Den Arduino UNO zeigt er mir immer als /dev/cu.usbmodem14101 an.

Nun schließen wir noch den ESP32 an und klicken auf Refresh.

In der Liste der Geräte tauchen nun zwei weitere USB Ports auf. Fragt mich nicht warum es zwei sind. Ich weiss aber, dass /dev/cu.SLAB_USBtoUART der richtige Port für den ESP32 ist.

Die zwei Ports werden gleich noch zum Problem. Deswegen zeig ich euch gleich, wie man damit umgeht.

Jetzt erstellen wir zunächst mal ein neues Projekt.

Wir wählen einen Projektnamen und als Board nehme ich das generische Espressif ESP32 Dev Module. Falls ihr ein Board verwendet, dass genau hier aufgelistet ist, dann würde ich natürlich das nehmen.

Als Framework nehmen wir natürlich wieder Arduino.

Wir öffnen die main.cpp und kopieren unseren Blinky Code hinein.

Klicken auf Upload, und …. bekommen einen Fehler.

In der Fehlermeldung sieht man auch was passiert ist: er hat versucht auf diesen USB Port den Code hochzuladen. Das ist aber der falsche Port. PlatformIO weiss halt nicht, welcher der beiden Ports der richtige ist, und nimmt natürlich prompt den falschen.

Das Problem können wir aber mit den Projekt-Settings lösen.

Geht dazu in den Projects Bereich von PlatformIO, sucht das richtige Projekt in der Liste und klickt auf Configure.

Es sollte ein Reiter esp32dev zu sehen sein.

Wir müssen eine Option mit dem Namen upload_port hinzufügen.

Dazu tippe ich das Wort port in das Feld bei New Option ein.

PlatformIO präsentiert daraufhin in einer Liste alle Optionen mit dem Begriff port.

Ich wähle upload_port.

Daraufhin wird eine neues Feld upload_port hinzugefügt und der Cursor sollte automatisch in dem entsprechenden Feld blinken.

Jetzt können wir einfach in dieses neue Feld hineinklicken und bekommen eine Liste mit allen USB Ports, die er schon im Devices Bereich angezeigt hatte.

Hier wählen wir den /dev/cu.SLAB_USBtoUART Port aus, und … gaaanz wichtig … klicken oben rechts auf Save.

Unter Windows wird das ein COM Port sein. Da müsst ihr dann die Devices Liste vor und nach dem Anschließe der Boards beobachten.

Wenn wir jetzt unseren Code hochladen, sollte alles funktionieren.

Funktionen Deklarieren

PlatformIO hält sich an die richtigen Coding Standards, während die Arduino-IDE uns einiges abgenommen hat. Das hinzufügen der Arduino.h Header Datei ist zum Beispiel so ein Fall.

Ein weiterer wichtiger Punkt ist das Deklarieren von Funktionen.

Wir nehmen mal den Code aus der loop() Schleife, und stecken die in eine Funktion und rufen die neue Funktion in der loop() Schleife stattdessen auf.

Wenn wir jetzt einmal den Code Check auslösen, wird uns ein Fehler ausgeworfen. Das Problem ist, dass unsere neue Funktion noch nicht deklariert wurde.

In C/C++ muss man Funktionen deklarieren, als sozusagen anmelden, dass es diese Funktion überhaupt gibt.

In der Arduino-IDE war das kein Problem, weil er dort automatisch nach Funktionen in der main Datei gesucht hat, und diese für uns unter der Haube deklariert hat.

Wenn man weiterhin nur mit einer main.cpp arbeiten gibt es zwei einfache Möglichkeiten: entweder die Funktionen korrekt vor der Nutzung deklarieren.

Dazu nimmt man sich einfach den Funktionsnamen inklusive Rückgabewert und schreibt ihn einmal in den oberen Bereich, bevor die Funktion verwendet wird.

Oder setup() und loop() setzt man als letztes in den Code, unter alle Funktions-Definitionen.

Den Code der Funktion selber ist die Funktions-Definition.

Das Anmelden einer Funktion vor der ersten Benutzung ist die Funktions-Deklaration.

Hilfreiche Funktionen in VSCode

Jetzt natürlich die berechtigte Frage: Warum machen wir das eigentlich, wenn es uns die Arduino-IDE doch bequemer macht?

Ich würde sagen, ab einer bestimmten Projekt-Größe, wird es in der Arduino-IDE unübersichtlich. Sobald mehrere Funktionen oder gar eigene Klassen über mehrere Dateien hinzukommen, macht es in der Arduino-IDE keinen Spaß mehr.

Hier kurz ein paar hilfreiche Funktionen, die die Arduino-IDE zur Zeit nicht hat:

Intellisense

Wo Intellisense genau anfängt und aufhört ist mir bis heute nicht ganz klar. Für mich sind das die hilfreichen Vorschläge, wenn ich einen Befehl oder Funktionsnamen anfange einzutippen. Und auch die Parameter Vorschläge, die mir angezeigt werden. Oder auch die Funktionsbeschreibungen.

Go to Declaration/Definition

Man kann mit Rechtsklick auf eine Funktion klicken und mit Go to Definition bzw. Go to Declaration direkt zu einer Funktion springen. Geht übrigens auch mit Variablen.

Und Go to References listet alle Vorkommen einer Funktion oder Variablen auf.

Peek macht im Grunde das gleiche, verlässt aber nicht gerade aktuelle Datei, sondern blendet quasi einen Vorschau an der aktuelle Cursor Position ein.

Rename Symbol

Rename Symbol ist sehr praktisch, wenn man irgendwann mal mit einem Variablen oder Funktionsnamen unzufrieden ist. Hiermit können alle Deklarationen, Definitionen und auch Aufrufe in einem Rutsch geändert werden. Bei anderen Entwicklungsumgebungen nennt man so etwas auch Refactoring.

Kommentare für Funktionsbeschreibungen in Intellisense  

Letzter Tipp noch, wie man seine Funktionsbeschreibungen in die Intellisense hineinbekommt.

Wen man seine Dokumentation zu einer Funktion mit bestimmten Keywords und einer bestimmten Syntax versieht, dann werden diese in der Intellisense angezeigt, wenn man zum Beispiel mit der Maus über einem Funktionsnamen liegen bleibt.

Das ganze funktioniert nach einem Standard der sich Doxygen nennt. Einen Link zu weiteren Keywords stelle ich mit in die Link Liste am Ende des Artikels.

Outro

Damit sind wir am Ende dieses PlatformIO Intros. Wir haben Visual Studio Code und die PlatformIO Erweiterung installiert.

Wir haben uns die Projekt-Struktur angeschaut und sind auf ein paar wichtige Unterschiede gegenüber der Arduino-Entwicklungsumgebung eingegangen.

Wir haben uns angeschaut, wie man PlatformIOs Projekt-Settings verwenden kann, um Upload Probleme mit den USB-Ports zu beheben.

Wir haben eine kurzen Blinky Test mit einem Arduino und einem ESP32 Board gemacht. Und am Ende haben wir noch etwas über hilfreiche Features von PlatformIO erfahren, die das Programmieren vereinfachen.

Ich hoffe, ich konnte den einen oder anderen von PlatfomIO überzeugen. Habt Spaß, bastelt rum, bleibt gesund.

Links