Mein SmartHome-Projekt mit ESP8266
Der ESP8266 ist ein einfach zu programmierender, sehr günstiger und kleiner Mikrokontroller mit WLAN von der chinesischen Firma espressif. Etwa seit 2015 ist er in Deutschland verfügbar und seither in mehreren unterschiedlichen Varianten erhältlich. Die Seite ESP8266 und ESP8285 Module Anleitung von Stefan Frings ist ein sehr empfehlenswerter Einstieg zum ESP8266. Enwickelt wurde der ESP8266 offensichtlich für IoT-Anwendungen, die seit 2017 unter anderen von der ITEAD unter der Marke Sonoff erhältlich sind. Übrigens kann der ESP8266 auch in diesen Geräten ziemlich einfach mit einem Code geflashed werden. Damit ist man dann garantiert unabhängig von irgendwelchen Servern irgendwo auf der Welt!
Ein ESP8266 kann mit unterschiedlicher Software bespielt werden, aus meiner Sicht am einfachsten mit der Arduino-IDE und C/C++. Inzwischen gibt es ESP8266-Flasher für die unterschiedlichen Ausführungen des ESP8266 zu kaufen, mit entsprechenden Stiftleisten und Tastern (z.B. Reset und Flash). Eine Verkabelung "von Hand" mit einem FTDI-USB-Umsetzer ist damit überflüssig.
Die unterschiedlichen Varianten des ESP8266 unterscheiden sich durch die Größe der Platine und die unterschiedliche Anzahl herausgeführter Pins. Der einfachste und kleinste Vertreter auf einer Platine ist der ESP8266 ESP-01. Zur Entwicklung eignet sich ein ESP8266 NodeMCU oder ein ESP8266 ESP12 aber besser, da diese im Betrieb mit dem PC via Micro-USB verbunden bleiben (können). Auf diese Weise kann der Programmablauf über Meldungen auf dem seriellen Monitor der Arduino-IDE dargestellt und einfach debugt werden.
Zur Spannungsversorgung eies ESP8266 ESP-01 verwende ich immer einen Spannungswandlet AMS1117-3.3. Dieser erzeugt aus bis zu 12 VDC die Versorgungsspannung des ESP-01 mit 3,3 VDC (VCC). Damit der ESP-01 nach dem Anlegen der Versorgungsspannung mit dem eigenen Code überhaupt läuft, muss mindestens der Pin CH_PD auf Plus (VCC) gelegt werden. Die beiden GPIOs 0 und 2 können können unbelegt bleiben. Sobald diese jedoch verwendet werden, z.B. um eine LED anzuschließen, muss man beide beim Start des ESP-01 ebenfalls auf VCC ziehen, z.B. mit einem PullUp-Widerstand (10k). Wenn man den gleichen Fehler mach wie ich am Anfang und eine LED direkt zwischen einen der beiden GPIO-Pins und Masse hängt, dann startet der ESP-01 im Flash-Modus.
Der ESP8266 ESP-01 eignet sich perfekt für diverse Sensoren, deren Signale via WLAN bereitgestellt werden. Als Temperatursensor verwende ich immer die digitalen DS18B20. Diese können seriell verschaltet werden, zehn DS18B20 funktionieren einwandfrei. Eine Vierzahl weiterer Sensoren (Luftdruck, relative Feuchte, etc.) können über den I2C-Bus angesprochen werden, ebenso diverse Displays, z.B. LCD oder OLED.
Leider habe ich es bis dato nicht geschafft, einen ESP8266 sinnvoll mit Batterie zu betreiben. Trotz Kontaktierung des GPIO16 mit RST (ist eine löttechnische Herausforderung und man braucht gute Augen) ist es mir nicht gelungen, den angeblich vorhandenen DeepSleep-Modus zu erreichen und auch wieder daraus aufzuwachen. Bei einigen (aber nicht allen!?!) ESP-01 musste ich feststellen, dass ein flashen nur OHNE die Verbindung zwischen GPIO16 und RST funktioniert, was die Sache zusätzlich verkompliziert. Angeblich ist hier der Nachfolger ESP32 viel umgänglicher, hab ich aber noch nicht getestet!
Es gibt sicher viele Möglichkeiten, Daten wie z.B. Werte von Sensoren, die von einem ESP8266 gemessen werden, auf einen Raspberry Pi zu übertragen. Auch der umgekehrte Weg kann erforderlich sein, wenn zum Beispiel ein ESP8266 oder ein ESP32 mit einem Display ausgestattet, unterschiedliche Werte anzeigen soll.
Ich verwende in meinen Projekten diese drei Methoden, die übrigens je nach Bedarf auch alle parallel nebeneinander funktionieren:
Auf dem ESP8266 läuft ein Webserver, der die relevanten Daten via XML bereitstellt. Ein Python-Script auf dem Raspberry Pi fragt via URL-Request diesen XML-Code ab, und der WevbServer auf dem ESP8266 liefert dem Python-Script den XML-Code. Daraus werden dann die relevanten Informationen mit Python extrahiert und in die Datenbank geschrieben.
Ein Nachteil dieser Methode ist, dass manchmal ein ESP8266 temporär einfach nicht erreichbar ist. Dann kann der Raspberry Pi zu diesem Zeitpunkt auch keine Daten beim ESP8266 abholen.
Der ESP8266 ruft ein auf dem Raspberry Pi liegendes PHP-Script auf. Hierzu muss auf dem Raspberry Pi ein WebServer wie z.B. Apache laufen. Dieses PHP-Script bekommt via Get die Daten vom ESP8266 geliefert und kann diese direkt in die Datenbank schreiben.
Vorteil dieser Methode ist, dass der ESP8266 selbst entscheiden kann, wann Daten in die Datenbank geschrieben werden sollen. Wenn ich zum Beispiel ein Sensorwert über einen langen Zeitraum nicht verändert, muss nicht jede Minute der selbe Wert in die Datenbank geschrieben werden. Der Zählerstand einer Wasseruhr ist so ein Beispiel. Lange Zeit passiert nichts, aber wenn dann die Badewanne gefüllt wird, sollen gerne in höherer Frequenz Daten in die Datenbank geschrieben werden.
Auf dem Raspberry Pi läuft ein MQTT-Broker wie z.B. Mosquitto. Der ESP8266 veröffentlicht in regelmäßiger Frequenz (z.B. alle 10 Sekunden) aktuelle Werte an den MQTT-Broker. Ein Python-Script auf dem Raspberry Pi kann zu jedem beliebigen Zeitpunkt diese Werte vom MQTT-Broker abholen. Auch weitere ESP8266 etc. können sich diese Werte vom MQTT-Broker abholen.
Der Vorteil von MQTT liegt klar auf der Hand. Es ist ein standardisiertes asynchrones Protokoll, das viele Geräte beherrschen. Der ESP8266 entscheidet selbst, wann er welche Daten veröffentlicht. Und der Raspberry Pi wiederum kann diese beim Broker abholen wann er will. Zusätzlich kann auf einem Windows-PC mit dem Programm MQTT-Explorer überprüft werden, welche Geräte am MQTT-Broker angemeldet sind und wann welche Daten veröffentlicht wurden.
In diesem Beispiel-Code ESP8266_MQTT_minimal.ino meldet sich ein ESP8266 am MQTT-Broker an und veröffentlicht dann die aktuelle Laufzeit des ESP8266 in Sekunden. Die MQTT-Botschaft wird mit dem Flag "retain" gesendet (true am Ende von client.publish). Das bedeutet, dass die Botschaft vom MQTT-Broker vorgehalten wird, bis eine neue Botschaft anliegt. Der Vorteil von "retain" zeigt sich bei der Abfrage der MQTT-Botschaften mit einem Rasbperry Pi (siehe unten).
Dieser Python-Code verbindet sich mit dm MQTT-Broker (mit Benutzername und Passwort) und liest alles ('#') MQTT-Botschaften ein. Hierzu ist es wichtig, dass die MQTT-Botschaften alle mit dem Retain-Flag gesendet wurden. Denn nur dann liegen die MQTT-Botschaften sofort bereit. Ansonsten müsste der Python-Code warten, bis die MQTT-Botschaften nach und nach eintrudeln.
Alle anliegenden MQTT-Botschaften werden im Dictionary mqtt abgelegt und danach angezeigt. Eine Weiterverarbeitung aller MQTT-Botschaften steht damit nicht mehr im Weg!
Mit einem ESP8266 ESP-01 lässt sich vermutlich der günstigste WLAN-Temperatursensor selbst aufbauen. Man braucht einen ESP-01, einen oder mehrere digitale Temperatursensoren DS18B20, ein AMS1117-3.3, eine Einbau-Hohlbuchse für Stecker 5,5/2,1 mit Lötanschluss und ein kleines Gehäuse. Ich verbaue meistens noch eine LED um zu zeigen, dass die WLAN-Verbindung hergestellt wurde und der ESP-01 funktioniert (LED blinkt dazu). Ein oder mehrere DS18B20 können an die mit dem Gehäuse verklebte 3-polige Leiterplatten-Anschkussklemme angeschlossen werden.
Die Signal-Leitung der DS18B20 und die LED werden auf GPIO0 bzw. GPIO2 gelegt. Damit der ESP8266 richtig startet müssen beide GPIOs auf VCC gezogen werden. Das bedeutet für die LED, dass diese leuchtet, wenn der GPIO2 auf low gezogen wird. Die Schaltung sieht dann zum Beispiel so aus:
In diesem Beispiel-Code ESP8266_DS18B20_Generic.ino werden die Temperaturen der DS18B20 ausgelesen. Der ESP8266 arbeitet als Web-Server und stellt das Ergebnis im XML-Format unter der festgelegten IP bereit:
Nach dem Aufruf via 192.168.XXX.YYY erhält man vom ESP8266 mit einem DS18B20 zum Beispiel folgende Antwort:
<MyHome>
<ESP8266_ESP01>
<data name="SSID" value="MySSID" valueunit=""/>
<data name="IP" value="192.168.XXX.YYY" valueunit="xxx.xxx.xxx.xxx"/>
<data name="Version" value="1.14 from 2018-02-02" valueunit=""/>
<data name="MAC" value="aa:bb:cc:dd:ee:ff" valueunit="AA:BB:CC:DD:EE:FF"/>
<data name="Temp0" value="26.75" valueunit="degC" address="28:ff:68:cc:61:16:04:65"/>
</ESP8266_ESP01>
</MyHome>
Ein Raspberry kann mit einem einfachen Python-Skript die Temperatur(en) auslesen und zum Beispiel in einer MySQL-Tabelle ablegen. Ich erfasse auf diese Weise zum Beispiel Vor- und Rücklauftemperaturen diverser Heizkreise und die Temperatur unter der Fasaden-Isolierung. Ich wollte einfach schon immer mal wissen, wie warm oder kalt es unter einer Dämmung eigentlich ist.