In der letzten Folge haben wir den ESP32 sein eigenes WLAN aufspannen lassen. Mit einem PC, Smartphone oder Tablet konnten wir uns in das Netzwerk „ESP32_MyJourneyIoT“ einloggen und über einen Webbrowser (Adresse 192.168.4.1) vom ESP32-Webserver ein Konfigurationsformular anfordern. In Textboxen lassen sich dort die SSID und das Passwort des eigentlichen Heimnetzwerks eintragen, über das ein Router Geräte ins Internet bringen kann. Nach Empfang des Formulars versucht der ESP32 sogleich, sich mit dem Router-Netzwerk zu verbinden, ist aber weiterhin auch über das eigene Netzwerk erreichbar. Im Erfolgsfall leuchtet die RGB-LED, die wir auf dem Steckbrett an das ESP32-Board angeschlossen hatten, grün auf. Der ESP32 ist nun bereit, über das Router-Netzwerk eine andere Webseite auszuliefern, mit der eine weitere LED geschaltet werden kann.


ESP32 macht PWM

So eine grüne LED als Bereitschafts-Zeichen ist schon praktisch. Allerdings bedeutet eine dauerhaft leuchtende LED lediglich, dass ein entsprechender Portpin des Controllers „high“ ist. Der Controller könnte sich inzwischen aufgehangen haben und daher nicht mehr in der Lage sein, Anfragen von Clients zu bearbeiten. Eine blinkende LED wäre schon ein besseres Signal. Sowas ließe sich leicht realisieren, wenn wir den Arduino-Sketch aus der letzten Folge geringfügig abwandeln. In der Hauptschleife wird ja periodisch geprüft, ob eine HTTP-Anfrage von einem Client hereingekommen ist, danach folgt ein kurzes Delay von 50 ms (und so fort). Mit einer einfachen Zählvariablen könnten wir es hier leicht erreichen, dass die LED beispielsweise (rund) ein Mal pro Sekunde an und ausgeht. Ich wollte das aber noch schöner hinbekommen, mit einem kontinuierlichen Ausfaden der LED. Hierfür kann man die PWM-Funktionen des ESP32 benutzen, welche die Entwickler von Espressif in einer hardwarenahen Bibliothek gekapselt haben (siehe dieses Tutorial). Mit
 
ledcSetup(0, 5000, 8);
ledcAttachPin(PinNumber, 0);
 
lässt sich ein PWM-Kanal 0 in der Setup-Funktion auf eine Auflösung von 8 Bit einstellen und mit einem Ausgabepin verbinden. In der Loop-Funktion kann man dann mit
 
ledcWrite(0, DutyCycle)
 
auf diesem Kanal 0 ein Tastverhältnis 0..255 einstellen. Die arduino-üblichen PWM-Funktionen analogWrite(…) funktionieren bei der von mir benutzten Version der ESP32-Library (noch) nicht.


Objektorientierte Programmierung

Ich habe die Aufgabe, mit der grünen LED Lebenszeichen zu signalisieren, genutzt, um endlich einmal Code in eigene Bibliotheksfiles auszulagern. Ein gutes Tutorial dazu habe ich im Internet gefunden (in deutscher Sprache). Ich habe mich davon inspirieren lassen, die beiden Files RGBLED.h und RGBLED.cpp erstellt und im Library-Ordner der Arduino-Entwicklungsumgebung untergebracht. Der Compiler sucht hier standardmäßig nach dem Code, wenn wir die Bibliothek im Hauptprogramm einbinden mit:
 
#include <RGBLED.h>

Die Library (die Sie unten downloaden können) ist in Form einer Klassenbibliothek realisiert. Sie spezifiziert Variablen und Funktionen und ist somit eine Blaupause für das, was eine RGB-LED innerhalb eines Programms „können“ muss. Zum Beispiel lässt sich mit der Funktion
 
setRGB(byte colorRed, byte colorGreen, byte colorBlue)
 
jeweils ein 8-Bit-Wert für die Farbe Rot, Grün und Blau setzen, um viele verschiedene Farben darstellen zu können. Die Klassen-Variablen
 
byte redPin;
byte greenPin;
byte bluePin;
 
enthalten dagegen die Nummern die Pins, an welche die rote, die grüne und die blaue Einzel-LED angeschlossen sind.
Um eine bestimmte RGB-LED im Anwendungscode anzusprechen, müssen wir aus der Blaupause (dem Klassencode) allerdings noch ein Objekt konstruieren, das für unsere RGB-LED zuständig ist. Im Hauptprogramm tun wir das mit
 
RGBLED BreadboardRGBLED(PIN_LED_RED, PIN_LED_GREEN, PIN_LED_BLUE);

RBGLED ist der Name unserer Klasse, BreadboardRGBLED der Name des Objektes, mit dem wir die bestimmte RGB-LED ab jetzt im Code des Hauptprogramms ansprechen können. Der konstruierenden Funktion (dem Konstruktor) übergeben wir als Parameter noch die Nummern der drei ESP32-Pins, an welche die RGB-LED angeschlossen ist. Wegen der hardcodierten Verwendung der PWM-Channels 0, 1 und 2 in der Library (Screenshot) ist es leider nicht möglich, aus der Klasse noch weitere Objekte abzuleiten, um weitere RGB-LEDs in einem Projekt anzusprechen. Für solche Fähigkeiten braucht es Tabellen, die Hardwareressourcen verwalten.



Ab jetzt können wir im Hauptprogramm die Farben unserer Steckbrett-RGB-LED mit
 
BreadboardRGBLED.setRGB(colorRed, colorGreen, colorBlue);
 
einstellen. Dass das mit PWM geschieht, dass die ledc…-Funktionen verwendet werden, das alles spielt sich ab jetzt hinter den Kulissen ab. Entwickler des Hauptprogramms müssen nur die obengenannte include-Zeile, den Konstruktor und die ebengenannte „öffentliche“ Funktion kennen, um Farben einstellen zu können.

Ich habe in der Library noch eine weitere Funktion dimRGB() implementiert, um den mit setRGB() eingestellten Farbwert in rund 16 Schritten herunterdimmen zu können (bei jedem Aufruf ein Schritt, danach wird wieder der eingestellte Farbwert gesetzt). Die schon bisher genutzte Funktion SwitchRGBLED(…) habe ich ebenfalls in die Library verlagert. Mit
 
BreadboardRGBLED.SwitchRGBLED(LED_GREEN);
 
kann man die LED grün leuchten lassen, mit
 
BreadboardRGBLED.SwitchRGBLED(LED_ON);
 
wird wieder die gerade mit setRGB eingestellte Farbe gesetzt.
 

ESP32-Webserver mit Lebenszeichen

Mit der Library war es nun einfach, den ESP32 kontinuierlich Lebenszeichen aussenden zu lassen, während er auf Anfragen wartet. Sind SSID und Passwort des Routers richtig eingestellt, dann leuchtet die RGB-LED nicht mehr schnöde dauer-grün, sondern fadet von grün auf dunkelgrün und blitzt dann wieder mit voller Helligkeit auf.
Das Hauptprogramm der letzten Folge habe ich hierfür nur geringfügig abändern müssen. Vor „delay 50 ms“ in der Hauptschleife habe ich die Zeile
 
BreadboardRGBLED.dimRGB();
 
eingefügt. Das Dimmen soll allerdings nur stattfinden, wenn der Router auch tatsächlich eingeloggt ist. Dazu dient die neue Status-Variable RouterNetworkDeviceState, die bei einem erfolgreichen Einloggen auf NETWORKSTATE_LOGGED gesetzt wird.

So ganz konnte ich es dennoch nicht lassen, die Anwendung aus der letzten Folge noch etwas weiter aufzubohren. Das beginnt mit der Schaltung: An Pin 25 des ESP32 habe ich über 1 k noch die blaue LED der RGB-LED angeschlossen. Und im Konfigurationsformular, das man über „192.168.4.1“ erreicht, lässt sich nun auch die Farbe des OK-Signals abändern (siehe Screenshot). Vielleicht möchten Sie ja stattdessen eine blaue OK-LED statt einer grünen, oder die OK-LED soll etwas dunkler leuchten? Statt Textboxen werden im Formular drei Schieberegler (Slider) verwendet, um die Farben einzustellen.



Im Hauptprogramm werden alle Einstellwerte wie gehabt über mehrere Arrays verwaltet. Das neue Array
 
int    ConfigType[8];

bestimmt, ob der Konfigurationswert vom Typ String (Eingabe in ein Textfeld) oder Byte (Einstellung über Slider) ist. Die Funktion
 
String EncodeFormHTMLFromValues(String TitleOfForm, int CountOfConfigValues)

setzt den entsprechenden Code der HTML-Seite zusammen.

Im Falle eines Aufrufs von 192.168.4.1 wird eine Seite ausgeliefert, die sechs Konfigurationswerte enthält (der erste ist der Wert zur Einstellung der Aktor-LED). Fordert man die „normale“ Webseite über das Router-Netzwerk an, dann besteht das ausgelieferte Formular nur aus einem einzigen Textfeld zur Einstellung dieser LED. Da wir für beide Webseiten dieselben Funktionen zum Zusammenstellen des HTML-Codes und Auswerten der Antwort nutzen, fällt das Programm recht kompakt aus.

Probieren Sie das Ganze einmal aus – den Arduino-Sketch können Sie unten herunterladen (am besten sollten Sie ihn einmal mit dem Sketch aus der letzten Folge vergleichen). Auch die Library ist selbstverständlich im Download enthalten. Der Ordner RGBLED, der das .h und das .cpp File enthält, muss – wie schon erwähnt – im Library-Ordner der Arduino-IDE untergebracht werden.

In den nächsten Folge wollen wir das in den letzten Folgen erarbeitete Wissen verwenden, um ein Gerät zu konstruieren, das Messwerte in die Cloud sendet.