ESP32

Die 8-Bit Mikroprozessoren sind aus dem elektronischen Alltag nicht mehr wegzudenken. Es gibt kaum ein Projekt in meiner Werkstatt, das nicht mindestens einen ATmega328 verwendet, sei es als “nackter” Prozessor auf der Platine oder zusammen mit USB-Interface und Quarz als Arduino Nano. Die Chips sind zuverlässig, vielseitig und vertraut – wie ein Werkzeug, das sehr gut in der Hand liegt.

Aber das Design der AVR-Prozessoren geht zurück auf die 90er Jahre und stößt natürlich an Grenzen. Besonders wünschenswert wären mehr RAM-Speicher, eine Floating-Point-Unit, mehr Timer und eine höhere Taktrate, die für zeitkritische Anwendungen hilfreich sein kann. Schon seit einiger Zeit gibt es verschiedene 32-Bit-Prozessoren, die mit wesentlich mehr Leistung anbieten und für eigene Entwicklungen geeignet sind. Hervorzuheben sind die STM32-Controller von ST (Nucleo-Boards) oder die SAM D21-Chips von Microchip Technology. Beide haben es auch in die Arduino-Welt geschafft (z.B. Arduino Due, Arduino-Board mit 32-Bit Architektur). Jedoch haben sich diese Chips in der Maker-Szene nicht so durchgesetzt, wie man es hätte erwarten können.

Anders erging des dem ESP32, eine neuere Entwicklung der chinesischen Firma Espressif. Dieser Chip verfügt über (fast) alles, was das Bastler-Herz begehrt, arbeitet mit Taktfrequenzen bis zu 240 MHz und ist darüber hinaus auf kleinen, günstigen Breakout-Boards verfügbar. Espressif hat es geschafft, den ESP32 sehr gut in die Arduino-Welt einzubetten, so dass der Umstieg von anderen Arduinos nicht schwer fällt. So ist es vielleicht nicht überraschend, dass der ESP32 eine beachtliche Verbreitung gefunden hat.

ESP32 Breakout Boards: Links das ESP32 Dev Modul, das leider etwas zu breit für einfache Steckbretter ist, dafür aber sehr preisgünstig. Rechts das etwas teurere ESP32 Pico Board.

Ein Grund für die große Akzeptanz ist sicherlich die Tatsache, dass Espressif WLAN- und Bluetooth-Kommunikation integriert hat. Ein zweiter Prozessor kümmert sich um die Netzwerkschnittstellen und arbeitet die entsprechenden Protokolle ab. Als Anwendungsentwickler hat man auch bei aktivem Netzwerk den Hauptprozessor vollständig zur Verfügung und muss sich nicht mit den Details der Kommunikation beschäftigen. Damit sind auch kleine Projekte ohne großen Aufwand über das Netz erreichbar. Der ESP32 ist zu einer Ikone des Internet of Things (IoT) geworden.

Breakout-Boards

Bei den Boards für den ESP32 gibt es etwas Wildwuchs. In meiner Praxis arbeite ich mit dem ESP32 Dev Module oder dem ESP32 Pico Board. Leider ist das preisgünstige Dev Module etwas zu breit für einfache Breadboards. Man kann aber zwei Breadboards zusammenstecken, so dass das Dev Module gut Platz findet.

ESP32 Dev Module auf zwei zusammengesetzten Breadboards.

Und es muss nicht unbedingt ein Steckbrett sein. Ich habe die Boards mit entsprechenden Buchsen-Leisten auch auf fertigen Platinen im Einsatz.

Die Boards haben viele Pins. Hier ist eine Übersicht der Pins mit ihren wichtigsten Funktionen für das Dev Module:

ESP32 Dev Module Pinout

Wie üblich sind die Pins mehrfach belegt und bieten je nach Konfiguration verschiedenen Funktionen an. Es gibt aber eine Reihe von Einschränkungen:

  • Die Pins 34, 35, 36 und 39 sind nur als Eingänge verfügbar. Eine digitalWrite()-Anweisung für diese Ports wird von der Arduino-IDE klaglos akzeptiert, bleibt aber völlig wirkungslos.
  • GPIO 6 bis 11 werden für den integrierten Flash-Speicher verwendet und stehen daher nicht frei zur Verfügung.
  • Der zweite ADC ist nicht verfügbar, solange der WiFi-Modus aktiv ist.

Wen man diese Dinge nicht weiß, kann die Fehlersuche sehr mühsam werden. Eine gute Zusammenstellung der möglichen Verwendung der Pins gibt es hier: https://randomnerdtutorials.com/esp32-pinout-reference-gpios/

Viel Peripherie

Ich beschäftige mich seit einigen Jahren mit dem ESP32 und habe ihn für verschiedene Projekte eingesetzt, durchweg mit guten Resultaten. Selbst wenn das WLAN nicht gebraucht wird, verfügt der Chip über eine ganze Menge nützlicher Peripherie. Neben den GPIOs und den üblichen Schnittstellen (ISP, SPI, UART) gibt es zwei ADCs, einen DAC, Deep-Sleep-Modus, Zugriff auf den Flash zur permanenten Speicherung von Daten und vieles mehr. Einzig die ADCs erfüllen nicht ganz die Erwartungen. Sie arbeiten zwar mit einer Auflösung von bis zu beachtlichen 12 Bit, leider aber mit mäßiger Linearität (siehe ESP32 ADC Non-linear Issue). Damit sind die ADCs für absolute und genaue Messungen nur eingeschränkt brauchbar. Für relative Vergleiche von Messwerten reicht es aber auf jeden Fall. Wenn für eine gegebene Anwendung ein exakter ADC unentbehrlich ist, dann bleibt natürlich noch die Möglichkeit, einen externen ADC über I2C oder SPI anzuschließen. Ein Ansatz, der z.B. beim Raspberry Pi in jedem Fall notwendig ist.

Vereinfachtes Pinout des ESP32 Dev Module

PlatformIO als Entwicklungsumgebung

Es gibt eine Reihe von Entwicklungsumgebungen, die zur Programmierung verwendet werden können. An erster Stelle steht natürlich die Arduino-IDE, die über den Boardverwalter mit der URL https://dl.espressif.com/dl/package_esp32_index.json für den ESP32 leicht erweitert werden kann. Man fühlt sich schnell Zuhause, wenn auch die Arduino-IDE für komplexere Projekte zu einfach gestrickt ist.

Eine positive Überraschung war für mich PlatformIO (https://platformio.org/), eine komfortable, plattform-übergreifende und als Open Source kostenlose IDE, mit der ich inzwischen sehr gerne an Mikrocontroller-Projekten arbeite. Die Bibliotheken für Arduino und für den ESP32 werden als Extensions installiert. Danach hat man eine große Auswahl an ESP32-Boards.

Der Umgang mit PlatformIO ist im Vergleich zur Arduino IDE etwas gewöhnungsbedürftig. Aber schon nach kurzer Zeit findet man alles, was gebraucht wird. Die zentralen Projekt-Einstellungen werden über die Datei platformio.ini vorgenommen. Hier ein typisches Beispiel für den ESP32:

platformio.ini für ein Projekt mit dem ESP32

Der serielle Monitor, als Debugging-Tool unerlässlich, lässt sich unter den Project Tasks mit “Monitor” anwählen. Mit “Upload and Monitor” wird direkt nach dem Laden des Programms der serielle Monitor aktiviert.

PlatformIO Tasks. Hier findet sich auch der serielle Monitor.

Außerdem sind die wichtigsten Funktionen (Übersetzen, Upload, serieller Monitor und mehr) über eine kleine Taskleiste am unteren Bildschirmrand verfügbar.

PlatformIO Task-Leiste mit vielen Funktionen

Die umfangreiche Funktionalität des ESP32 ist weitgehend in Arduino-Funktionen verpackt, so dass die ersten Programme ohne große Umstellung funktionieren. Wenn man auf spezifische Funktionen des ESP32 zugreifen möchte, dann ist auch das kein Problem. Wie üblich im Ardunio Framework sind die Bibliotheken des Herstellers (nach Einbinden der entsprechenden Header-Files) transparent verfügbar, z.B. Funktionen wie adc1_get_raw(), um den ADC anzusprechen, oder esp_adc_cal_raw_to_voltage() für die Umrechnung der Werte mit Kompensierung von Referenzspannungs-Abweichungen (siehe ESP ADC Reference). Damit steht dem tieferen Einstieg in die Welt des ESP32 nichts im Wege – sofern man bereit ist, sich durch die Beschreibungen und Datenblätter zu arbeiten.

Fazit

Der ESp32 hat sich schnell in meinen Arbeitsalltag integriert und kommt oft zum Einsatz. Umfang und Leistungsfähigkeit stehen zwischen den 8-Bit AVRs auf der einen Seite und dem Raspberry Pi auf der anderen Seite. wobei der Chip kaum teurer ist, als ein einfacher Arduino. Die Integration in das Arduino-Framework und die Verfügbarkeit einer leistungsfähigen Open Source-IDE lassen kaum Wünsche offen.

Laborpraxis: Ein versteckter Fehler

Wer mit Elektronik arbeitet, muss unweigerlich Fehler suchen. Das gehört einfach dazu. Es gibt sicherlich kein Projekt, das von der Idee bis zum Prototypen fehlerfrei funktioniert. Meistens kann man mit schrittweisem Vorgehen die Fehler einigermaßen gezielt lokalisieren und beseitigen. Jetzt ist mir aber ein verstecktes Problem begegnet, dass mich an der Weltordnung der Elektronik zweifeln ließ.

Es ging um eine Schaltung mit zwei ATmega-Prozessoren, die als Master und Slave über den I2C-Bus miteinander im Gespräch sind. Soweit so gut. Erst einmal funktionierte auch alles wie geplant, aber dann gab es sporadische Ausfälle.  Sporadisch, also nicht gezielt reproduzierbar, ist hier das Stichwort. Mal lief die Schaltung für Stunden ohne Probleme, und dann war plötzlich der I2C-Bus weg. Der Slave-Prozessor reagierte nicht mehr. Ein anderes Mal wollte die Schaltung schon nach dem Einschalten nicht so, wie sie sollte.

Zuerst einmal wurde gemessen. Das Oszilloskop zeigte ein vernünftiges I2C-Signal am Takt und auf der Datenleitung. Dann wurde die Software auf den Kopf gestellt. Stürzt die Slave-Software ab? Wo hängt die Geschichte? Aber ohne Ergebnisse. Eine regelmäßige blinkende LED wurde eingebaut, und als nach Stunden reibungsloser Tätigkeit der Fehler wieder auftauchte, zeigte die LED, dass der Slave nach wie vor sein Programm abarbeitete und auf Input wartete. Auch ein Austausch des Prozessors gegen ein fabrik-neues Exemplar brachte keine nachhaltige Besserung. Verflixt!

Als ich dann die laufende Platine in die Hand nahm, merkte ich, dass mechanische Spannungen, z.B. leichtes Verdrehen der beiden Seiten, den I2C-Bus wieder belebten. Also ein Lötproblem? Genaue Inspektion der Lötpunkte und Nachlöten aller I2C-involvierten Leitungen halfen immer noch nicht weiter. Mein Frustrationslevel erreichet den Siedepunkt. Ich legte die Platine zur Seite und baute einen zweiten Prototype, der für das Projekt sowieso gebraucht wurde. Und siehe da, diese zweite Platine arbeitet bis heute tadellos. Meine Elektroniker-Welt war halwegs wieder zurecht gerückt.

Aber natürlich war das Problem damit noch nicht behoben. Tage später setzte ich mich noch einmal an die fehlerhafte Platine. Dabei zog ich den Slave-Prozessor aus der Fassung, um ihn mit einem Software-Update zu versorgen. Und dann fiel es mir wie Schuppen von den Augen: Pin 27 der IC-Fassung sah irgendwie anders aus, als die anderen Pins. Genauer hingeschaut konnte ich erkennen, dass der innere Ring im Pin-Anschluss fehlte. Aha, eine fehlerhafte IC-Fassung! Ich steckte den Prozessor noch einmal in die Fassung und konnte mit einem Multimeter erkennen, dass Pin 27 nur gelegentlich Kontakt zum Chip hatte. Und tatsächlich: Bei diesem Pin handelt es sich um die Datenleitung des I2C-Bus.

Fehlerhafte IC-Fassung für den I2C-Slave-Prozessor
Fehlerhafte IC-Fassung für den I2C-Slave-Prozessor

Da es sich um “nur” um einen Prototypen handelte, wurde zur Fehlerbehebung der Pin des Prozessors direkt in der Fassung verlötet. Seit dem läuft die Platine tadellos.

Sporadische, nicht reproduzierbare Fehler brauchen Geduld und hohe Frustrationstoleranz. Um so schöner ist es, wenn der Fehler dann doch gefunden wird.

Ein Kollege sagte einmal: Wenn du frustriert bist, dann bist du dabei, etwas zu lernen! In diesem Sinne: Viel Erfolg beim Aufbau der nächsten Schaltung!