Erste Schritte mit dem Microcontroller ESP8266/NodeMCU

https://bildung.social/@oerinformatik/

https://oer-informatik.de/helloworld_mcu

tl/dr; (ca. 12 min Lesezeit): Keine neue Programmiersprache ohne ein “Hello World”, kein Microcontroller-Projekt ohne LED-Blinken. Hier geht es nur um die ersten Schritte mit dem Microcontroller-Board (ESP32, ESP8266 oder Arduino Uno): Einrichtung und zwei kleine Beispielprogramme zur Nutzung der internen LED und Taster. (Zuletzt geändert am 03.03.2025)

Dieses Tutorial beschreibt die ersten Schritte mit einem Microcontroller-Board. Die Schritte ähneln sich bei allen Microcontrollern, jedoch gibt es Abschnitte, in denen gesondert auf den Arduino Uno, den ESP8266 (nodeMCU) oder den ESP32 eingegangen wird. Über den jeweiligen Abschnitten gibt es Registerkarten, mit denen der passende Microcontroller ausgewählt werden kann.

Treiber für den Microcontroller installieren

Damit der Microcontroller auf dem NodeMCU erkannt wird, muss zunächst ein Treiber in der Arduino-IDE nachinstalliert werden (oder geprüft werden, ob die Einstellungen bereits vorhanden sind).

Unter Datei/Einstellungen (bzw. File/Preferences) gibt es unten den Punkt “Additional boards manager URLs”, in dem (ggf. neben weiteren) auch die folgende URL eingetragen werden muss:

http://arduino.esp8266.com/stable/package_esp8266com_index.json
In den Settings muss die URL des ESP8266 eingetragen werden
In den Settings muss die URL des ESP8266 eingetragen werden

Nach dem Klick auf “ok” wird die verlinkte JSON-Datei geladen. Kann im Boardmanager der entsprechende Treiber geladen werden. Boardsmanager öffnen (Tools/Board/BoardsManager):

Boards Manager öffnen (Ctrl-Shift-8)
Boards Manager öffnen (Ctrl-Shift-8)

Im Boards-Manager nach “ESP8266” suchen und die Boards installieren:

Boards Manager öffnen (Ctrl-Shift-8)
Boards Manager öffnen (Ctrl-Shift-8)

Port und Board

Der häufigste Fehler bei der Programmierung in der Arduino-IDE ist die Auswahl eines falschen Boards / Ports. Immer, wenn Fehler beim Übertragen eines Programms auftauchen, sollte überprüft werden, ob die folgenden Einstellungen stimmen.

An welchem Port hängt mein Microcontroller?

Unter Windows-Systemen wird dem Microcontroller ein COM-Port zugewiesen. Die zugewiesene Nummer weicht dabei ab, wenn unterschiedliche weitere Geräte angemeldet sind. Ein einfacher Weg, herauszufinden, welcher COM-Port zugewiesen wurde ist, das Board ein- und auszustecken und zu beobachten, welcher COM-Port betroffen ist.

In meinem Fall wurde dem Board COM4 zugewiesen. Falls hier kein Board erscheint muss ggf. der USB-Treiber noch nachinstalliert werden.

In der IDE wird der entsprechende Port über Tools/Port eingetragen:

Auswahl des COM-Ports, der dem NodeMCU zugewiesen wurde über Tools/Port
Auswahl des COM-Ports, der dem NodeMCU zugewiesen wurde über Tools/Port

Wer unsicher ist, welcher COM-Port betroffen ist - oder auf Fehler stößt und zusätzliche Infos benötigt - der kann z.B. im Gerätemanager oder mit Hilfe der PowerShell nach angeschlossenen USB-Devices suchen:

Aus der zugehörigen Ausgabe geht auch hervor, welcher USB-Chip verwendet wird, hier mal unterschiedliche Antworten, auf die ich später noch eingehe:

    Class Name                                          Description                            PNPDeviceID
    ----- ----                                          -----------                            -----------
(1) Ports Silicon Labs CP210x USB to UART Bridge (COM7) Silicon Labs CP210x USB to UART Bridge USB\VID_10C4&PID_EA60\0001
(2) Ports USB-SERIAL CH340 (COM6)                       USB-SERIAL CH340                       USB\VID_1A86&PID_7523\6&24E558FB&0&4
(3) Ports USB-Enhanced-SERIAL CH343 (COM3)              USB-Enhanced-SERIAL CH343              USB\VID_1A86&PID_55D3\5735020188
(4) Ports USB Serial Device (COM4)                      Serielles USB-Gerät                    USB\VID_303A&PID_1001&MI_00\7&84C9D3C&0&0000
(5) Ports USB Serial Device (COM9)                      Serielles USB-Gerät                    USB\VID_0483&PID_374B&MI_02\9&5000A63&0&0002
(6) Ports USB Serial Device (COM10)                     Serielles USB-Gerät                    USB\VID_239A&PID_0010&MI_02\9&212F6B11&0&0002
(7) Ports USB Serial Device (COM11)                     Serielles USB-Gerät                    USB\VID_239A&PID_0010&MI_00\9&212F6B11&0&0000

Wenn keine dieser Möglichkeiten ausgegeben wird, fehlt vermutlich ein Treiber. Ob überhaupt ein Chip erkannt wird, kann man im Gerätemanager nachschauen oder mit folgendem Powershell-Befehl:

Hier sollte eine der oben abgebildeten Zeilen ausgegeben werden, allerdings ohne einen Eintrag in der Spalte “Class” (da ohne Treiber kein Port erkannt wird)

Am häufigsten ist das sicher der CP210x (Zeile 1 oben),

In meinem Fall wurde dem Board COM4 zugewiesen. Sollte dem ESP kein Port zugewiesen werden (Port ist dann oft ausgegraut), dann ist möglicherweise der USB-Treiber für den verwendeten Chip nicht installiert (USB-zu UART-Bridge). Die Software ist schnell nachinstalliert - mit etwas Mut, denn die Herstellerseiten sind mitunter komplett chinesisch:

  • Am häufigsten sind CP210x-Chips verbaut (Zeile 1). Die Treiber sind meistens bereits im System vorhanden. Falls nicht bietet deren Hersteller SiliconLabs auf dieser Internetseite die Treiber an.

  • Etwas seltener findet man CH340 oder ähnliche Chips (Zeile 2). Deren Treiber müssen meistens noch installiert werden. Der Hersteller bietet sie auf dieser Seite (falls Darstellung chinesisch: unten CH341SER.EXE)

  • Neuere ESP32 benötigen gar keine expliziten USB-UART-Chips mehr, da diese ESP32 direkt per USB angesprochen werden können (Zeile 4 - 7).

  • Falls das alles nicht hilft gibt es auf esp32.net eine gute Übersicht der verwendeten Chips.

Sollte der Treiber für CHG340 oder CP210x fehlen, so muss dieser über die oben genannten Internetseiten geladen und entpackt werden. Danach kann im Gerätemanager das nicht zugeordnete Gerät ausgewählt werden:

Im Geräte manager Gerät wählen und im Kontextmenü die Installation starten
Im Geräte manager Gerät wählen und im Kontextmenü die Installation starten

Über die manuelle Treiberinstallation kann der Pfad zum heruntergeladenen Treiber herausgesucht werden:

Den Treiber manuell installieren
Den Treiber manuell installieren

Nach der Auswahl des Pfads wird der Treiber dann korrekt installiert und der Microcontroller gefunden.

Pfad zum Treiber eingeben.
Pfad zum Treiber eingeben.

In der IDE wird der entsprechende Port über Tools/Port eingetragen:

Auswahl des COM-Ports, der dem NodeMCU zugewiesen wurde über Tools/Port
Auswahl des COM-Ports, der dem NodeMCU zugewiesen wurde über Tools/Port
Das korrekte Board wählen

Das zugehörige (und eben installierte) Board wird ebenso unter Tools eingetragen. Unter Tools/Board/ finden sich Gruppen der Microcontroller. Hier muss das passende Board gefunden werden.

Unter Tools/Board/esp8266 öffnet sich eine lange Liste:

Das Board unter Tools/Board/esp8266 wählen
Das Board unter Tools/Board/esp8266 wählen

Aus dieser Liste sollte der neuste NodeMCU-Treiber gewählt werden:

Aus der Liste “NodeMCU 1.0” auswählen
Aus der Liste “NodeMCU 1.0” auswählen

Damit ist alles Startbereit für den ersten Sketch!

Ablauf eines “Hello World” Programms

Einige Microcontroller haben bereits auf den Boards verbaute interne LED oder interne Buttons, die wir für ein erstes “Hello World” nutzen können.

Das nodeMCU-Board mit ESP8266 bietet uns folgende Möglichkeiten: Eine LED auf dem Microcontrollerboard, die mit dem Ausgang D4 verschaltet ist, eine LED auf dem nodeMCU-Board, die mit dem Ausgang D0 verschaltet ist und ein Taster (“FLASH”), der am Eingang D3 angeschlossen ist:

Die Lage der internen LED und Taster auf dem nodeMCU-Board
Die Lage der internen LED und Taster auf dem nodeMCU-Board

Wir nutzen die Arduino-IDE, um diese internen LED und Taster anzusteuern. Ein Arduino-Sketch besteht im wesentlichen aus fünf Komponenten, von denen drei durch uns konfigurierbar sind:

  • Nach dem Start wird eine Funktion init() aufgerufen, die alle nötigen Bibliotheken lädt und konfiguriert. Diese Methode wird uns nicht angezeigt und ist nicht konfigurierbar.

  • Danach kommt ein Bereich, in dem wir eigene Variablen erzeugen können, die wir in unserem Sketch benötigen.

  • Darauf folgt eine setup-Methode, in der wir alle Konfigurationen vornehmen können, die für unser Programm erforderlich sind. Die setup()-Methode wird genau einmal aufgerufen.

  • Nach der setup()-Methode folgt eine Dauerschleife. Die Schleife selbst sehen wir nicht, wir wissen nur, dass in ihr eine weitere Methode aufgerufen wird:

  • Die loop()-Methode befindet sich in der Dauerschleife. In der loop()-Methode befindet sich die eigentliche Programmlogik - entweder direkt, oder in Form von Funktionsaufrufen.

Grafisch lässt sich das ganze als Programm-Ablaufplan (PAP) darstellen:1

PAP: auf init und setup folgt die Schleife, in der loop immer wieder aufgerufen wird
PAP: auf init und setup folgt die Schleife, in der loop immer wieder aufgerufen wird

Der eigentliche Programmcode

Wir können die verbauten LED mit ein paar Zeilen Code ein- und ausschalten:

Zunächst legen wir die Variable fest für den General Purpose Input Output (GPIO), an dem die LED angeschlossen ist. Dazu definieren wir eine Variable, die den Anschluss der jeweiligen LED speichert. Dadurch ist das Programm später leichter änderbar, da wir nur an einer einzigen Stelle erfassen, wo sich die LED befindet.

Eine interne LED ist am ESP-12 über 470 Ohm mit dem GPIO D4 verbunden, die nutzen wir für unser Ausgangsbeispiel.

Lage der internen ESP-12-LED
Lage der internen ESP-12-LED

In der setup()-Methode werden alle Operationen aufgerufen, die genau ein einziges Mal beim Starten ausgeführt werden müssen. Hier wird konfiguriert, dass es sich bei dem Pin, den wir gerade ind er Variable ONBOARD_LED gespeichert haben, um ein Ausgabedevice (also eine LED aus Ausgabe) handelt:

In einer zweiten Methode, die in Arduino-Sketches immer vorkommt, werden alle Operationen aufgerufen, die in einer Dauerschleife laufen sollen. Hier wird an den Ausgabepin ONBOARD_LED abwechselnd ein HIGH- und ein LOW-Potenzial angelegt. Ein HIGH-Potenzial heißt, dass der Microcontroller an diesem Pin 5V (bei Arduino Uno) bzw. 3,3V (bei ESP8266 bzw. ESP32) anlegt, ein LOW entpricht einem Potenzial von 0V. Die LED sollte also blinken.

Das Potenzial wird kurz auf HIGH und lange auf LOW gelegt - wir erwarten also ein kurzes Leuchten (200 Millisekunden) und eine lange Pause (800 Millisekunden).

Es ist genau umgekehrt: lange Pause, kurzes Leuchten! Um das Verhalten zu verstehen müssen wir uns die interne Schaltung ansehen:

Schaltplan der LED des ESP8266-Chips
Schaltplan der LED des ESP8266-Chips

Sobald an D4 ein LOW-Signal anliegt ergibt sich eine Spannungs-Potenzialdifferenz (3,3V - 0V), die zu einem Stromfluss durch die LED führt. Liegt an D4 ein HIGH-Potenzial an, so ergibt sich keine Potenzialdifferenz (beide Seiten auf 3,3V) und die LED leuchtet nicht. Die LED verhält sich also gerade umgekehrt, als man es erwarten würde: sie ist bei einem anliegenden LOW-Potenzial aktiv, man nennt dies auch low-active.

Es gibt eine zweite LED am nodeMCU-Board, zwischen dem “RST”-Taster und den gelben Bauelementen:

Lage der internen NodeMCU-LED
Lage der internen NodeMCU-LED

Diese LED ist genauso an D0 verschaltet wie die vorige LED an D4:

Die interne LED des nodeMCU-Boards ist über 470 Ohm an D0 verschaltet
Die interne LED des nodeMCU-Boards ist über 470 Ohm an D0 verschaltet

Wir können daher alle Überlegungen von oben übernehmen, auch das Programm sieht genauso aus, wir müssen lediglich D4 durch D0 ersetzen:

Interne Taster der Microcontroller

Der FLASH-Taster, der neben dem Micro-USB-Port sitzt, lässt sich ebenfalls direkt für Programme nutzen. Er darf nur beim Booten des ESP-Boards nicht betätigt sein, danach kann er frei genutzt werden:

Schaltplan der LED des ESP8266-Chips
Schaltplan der LED des ESP8266-Chips

Intern ist er mit dem D3-Eingang verschaltet und verfügt über einen Pull-Up-Widerstand. Das heißt: wenn der Taster nicht betätigt ist, liegt ein HIGH-Signal an D3 an.

Die interne LED des nodeMCU-Boards ist über 470 Ohm an D0 verschaltet
Die interne LED des nodeMCU-Boards ist über 470 Ohm an D0 verschaltet

Bei Betätigung liegt an D3 eine sehr niedrige Spannung an, die als LOW-Signal interpretiert wird. Es sind nicht exakt 0 V, da zwischen D3 und GND noch ein 470\ \Omega Widerstand liegt. Die Potenzialdifferenz zwischen GND (0V) und 3V3 (3,3V) teilt sich im Verhältnis der Widerstände auf, an D3 liegen also 0,11V an:

U_{D3} = 3,3 V \cdot \frac{430 \Omega}{12.000 \Omega + 430 \Omega} = 0,11 V

Gemäß Datenblatt erkennt der ESP8266 Eingangssignale zwischen -0,3V und 0,8 V gesichert als LOW, wir sind somit also auf der sicheren Seite. Der Arduino-Sketch ist folgendermaßen aufgebaut:

  • Wir deklarieren eine neue Variable für den internen Taster: const int ONBOARD_BUTTON und weisen ihr den Wert D4 zu.

  • In der setup()-Methode wird dieser Pin als Eingang festgelegt: pinMode(ONBOARD_BUTTON, INPUT);. Die LED an Pin D4 wird wieder als Ausgang genutzt.

  • In der Dauerschleife (loop()) wird ausgelesen, ob das anliegende Potenzial an D3 ein LOW-Pegel ist: if (digitalRead(ONBOARD_BUTTON)==LOW){...}.

  • Bei anliegendem LOW-Pegel wird die Zeit, die die LED aktiviert wird auf kurz eingestellt (200 Millisekunden), sonst auf einen längeren Wert (1200 Millisekunden).

Im Ganzen sieht das so aus:

Den so festgelegten Pin müssen wir jetzt noch als Eingang deklarieren:

Und schließlich in der Programmschliefe den Zustand des Button-Pins abfragen (mit digitalRead()). Wenn der Eingang des Pins LOW ist, soll die LED schnell blinken. Andernfalls soll sie langsam blinken:

Nach dem Hochladen kann man erkennen, dass die LED normalerweise langsam blinkt (der Pins also regulär HIGH ist) und nur bei Betätigung des Buttons langsam wird (also LOW). Dieses Verhalten liegt an einem intern verbauten “Pull-Up-Widerstand”. Dazu später mehr, wenn wir uns die Belegung von externen Tastern genauer anschauen.

Wo befinden sich die versteckten Programmbestandteile?

Für alle, die es genau wissen wollen (alle anderen können diesen Absatz getrost überspringen):

Eingangs wurde erwähnt, dass es über die beiden oben genannten Funktionen setup() und loop() hinaus noch weiteren Programmcode gibt, den die Arduino-IDE aber vor uns versteckt. Gibt es eine Möglichkeit danach zu forschen? Gibt es beispielsweise eine main()-Methode, wie sie die Java und C/C++ Programmierer kennen?

Ja, die gibt es, man kann sie tief im Arduino-Ordner aufspüren, bei den 1.8.x-Versionen der Arduino-IDE in Windows liegt sie beispielsweise hier:

In dieser main.cpp-Datei befindet sich die main()-Methode des C++-Programms. Und darin befinden sich die eingangs erwähnten Methodenaufrufe (siehe Programmablaufplan oben) init(), setup() und loop(), sowie die Dauerschleife (hier über for (;;) {…}` umgesetzt):

Für den ESP ist dieser Aufruf nicht ganz so einfach aufzuspüren - und das umgebende Programm etwas aufwändiger. Der Grundaufbau ist aber identisch: setup() wird einmal aufgerufen, loop() immer wieder.

Wie geht es weiter?

Weiter geht es im zweiten Teil, in dem digitale Ausgänge genutzt und externe LED angesteuert werden.

Weitere Literatur und Quellen


Hinweis zur Nachnutzung als Open Educational Resource (OER)

Dieser Artikel und seine Texte, Bilder, Grafiken, Code und sonstiger Inhalt sind - sofern nicht anders angegeben - lizenziert unter CC BY 4.0. Nennung gemäß TULLU-Regel bitte wie folgt: Erste Schritte mit dem Microcontroller ESP8266/NodeMCU” von oer-informatik.de (H. Stein), Lizenz: CC BY 4.0. Der Artikel wurde unter https://oer-informatik.de/helloworld_mcu veröffentlicht, die Quelltexte sind in weiterverarbeitbarer Form verfügbar im Repository unter https://gitlab.com/oer-informatik/mcu/arduino-esp. Stand: 03.03.2025.

[Kommentare zum Artikel lesen, schreiben] / [Artikel teilen] / [gitlab-Issue zum Artikel schreiben]


  1. Grafik wurde erstellt mit dem PAP-Designer von Friedrich Folkmann: http://friedrich-folkmann.de/papdesigner/Hauptseite.html

Kommentare gerne per Mastodon, Verbesserungsvorschläge per gitlab issue (siehe oben). Beitrag teilen: