WLAN-Thermometer mit ESP8266

Erstellt am 29.12.2015

Mehr IoT bitte!

Tja, was soll ich sagen. Mit den ESP8266-WLAN-Chips kommt mir eine Idee nach der anderen. Kürzlich beim Aufräumen bin ich über ein 128x64 Pixel OLED-Display gestolpert, welches ich schon vor einiger Zeit mal erworben hatte. Das lässt sich entweder per I2C oder SPI ansprechen. Das ESP-01-WLAN-Modul hat noch zwei GPIOs zur verfügung, über die man ein I2C-Signal generieren kann. Nachdem im Nodemcu-Projekt auch schon die u8g-Library für diverse displays eingebunden ist, wird das Ansteuern dieses Displays zum Kinderspiel. Also hurtig ein bisschen programmiert und heraus gekommen ist ein WLAN-Thermometer, das neben der Temperatur auch die Uhrzeit und die Luftfeuchtigkeit anzeigt. Den Luftfeuchtigkeitssensor habe ich bereits in meinem Artikel HH10D-Feuchtigkeitssensor erläutert. Als kleines Gimmick zeigt das Display außerdem ein Glockensymbol an, wenn an der Tür geläutet wurde - denn die Klingel ist inzwischen auch mit dem Homeserver verkabelt.

Der elektronische Part

Zum Einsatz kommen ein ESP8266 Modul, Typ 01, ein OLED-Display mit 128x64 Pixeln und SH1106-Controller, sowie ein 3,3 V Spannungsregler, welcher die 5,3 V aus der Wandwarze auf eine für das WLAN-Modul und das Display erträgliche Spannung herunter spannt. Dazu ein wenig Hühnerfutter, denn die Resetleitung des Displays muss zum Start einmal kurz auf Low gelegt werden. Der GPIO-0 des WLAN-Moduls kann als regulärer IO-Port genutzt werden. Wird er beim Einschalten auf GND gezogen, startet das WLAN-Modul allerdings in den Bootloader. Um das zu verhindern habe ich diesem Pin einen kleinen 4,7 kOhm Pull-Up-Widerstand verpasst.

Hier ein kleiner Schaltplan und ein Bild des ganzen, das ist wirklich nicht weiter schwer zu löten:

Schaltplan WLAN-Thermometer
oledtemp.sch Schaltplan
Platine gelötet
Platine Rückseite

Software für das WLAN-Modul

Der Einfachheit halber habe ich das WLAN-Modul mit Display sehr simpel gehalten. Es verbindet sich lediglich alle 30 Sekunden mit einem Serverdienst auf meinem Homeserver, der die eigentlichen Bilddaten erstellt, und zeigt diese dann direkt auf dem Display an. Es werden also keine Grafiken auf dem Modul selber erstellt, dies übernimmt alles der Server. Einzig für die Klingelanimation liegen zwei Bilddateien im Flash des Moduls, die dann abwechselnd aufgerufen werden.

Zunächst gilt es aber die Firmware auf das Modul zu bekommen. Wie schon bei meinem RFID-WLAN-Türöffner benötigt ihr den NodeMCU Flasher, um eine Firmware auf den Chip zu spielen. Wenn ihr ein Display mit SSD1306-Controller verwendet, dann könnt ihr euch die Firmware wieder direkt bei nodemcu-build.com holen. Wenn ihr, wie ich, ein Display mit SH1106-Controller verwendet, dann müsst ihr zum Glück nicht, wie ich, die Toolchain installieren, die Routine im Header-File aktivieren und alles kompilieren, sondern ihr könnt eine fertige Firmware einfach bei mir herunter laden: nodemcu_integer.bin.

Damit ihr dennoch wisst, wie ihr ggf. auch noch andere Module einkompiliert, die ihr nicht über nodemcu-build.com bekommt, hier eine kleine Anleitung:

  1. Besorgt euch am besten eine virtual Machine mit z.B. einem Ubuntu in der ihr alles installiert
  2. Setzt das SDK mit hilfe eines HowTos auf (das erklär ich hier nicht nochmal einzeln)
  3. Als nächstes benötigen wir den NodeMCU-Code aus dem dev-Branch (für die aktuellen Modulversionen):
    git clone -b dev https://github.com/nodemcu/nodemcu-firmware.git
  4. Mit einem Editor passt ihr die Datei nodemcu-firmware/app/include/user_modules.h an, sodass auf alle Fälle die Module bit, u8g und i2c gebaut werden.
  5. Zum Schluss wird die Datei nodemcu-firmware/app/include/u8g_config.h bearbeitet, sodass die Funktion für den SH1106-Controller ebenfalls gebaut wird:
    #define U8G_DISPLAY_TABLE_I2C                           \
        U8G_DISPLAY_TABLE_ENTRY(ssd1306_128x64_i2c)         \
        U8G_DISPLAY_TABLE_ENTRY(sh1106_128x64_i2c)          \
    
    Den Backslash am Ende nicht vergessen!
  6. Das Ganze kompilieren (mit den EXTRA_CCFLAGS wird die integer-Version der Firmware gebaut, sonst erhaltet ihr die float-Variante)
    make EXTRA_CCFLAGS="-DLUA_NUMBER_INTEGRAL"
  7. Ihr erhaltet zwei Dateien (0x00000.bin und 0x10000.bin). Diese einzeln zu flashen schlug bei mir fehl. Also installiert euch das Programm srec_cat mit dem die beiden Dateien in eine zusammengeführt werden können:
    srec_cat -output nodemcu_integer.bin -binary 0x00000.bin -binary -fill 0xff 0x00000 0x10000 0x10000.bin -binary -offset 0x10000
  8. Die entstandene nodemcu_integer.bin mit dem NodeMCU-Flasher auf den Chip übertragen

Das wäre geschafft, weiter geht's mit der Software und den Bilddateien für das WLAN-Modul. Ich habe diese in ein Zip zusammen gefasst, dann müsst ihr nur eine Datei herunter laden. Wie üblich müsst ihr noch die init.lua anpassen und eure WLAN SSID und den passenden Schlüssel hinterlegen.

Zum Hochladen auf das Modul verndet ihr diesmal am besten nicht das luatool sondern ein Programm mit dem sich auch Binärdaten übertragen lassen: nodemcu-uploader. Damit könnt ihr jetzt die folgenden vier Dateien hochladen:

./nodemcu-uploader.py --port /dev/ttyUSB0 upload /pfad/zu/init.lua:init.lua
./nodemcu-uploader.py --port /dev/ttyUSB0 upload /pfad/zu/oled.lua:oled.lua
./nodemcu-uploader.py --port /dev/ttyUSB0 upload /pfad/zu/bell.mono:bell.mono
./nodemcu-uploader.py --port /dev/ttyUSB0 upload /pfad/zu/bell_ring.mono:bell_ring.mono

Wie ihr sehen könnt, liegen die Bilddaten im 1-Bit mono-Format vor. Selber könnt ihr solche Dateien ganz einfach erstellen, indem ihr ein BMP mit ebenfalls einer 1-Bit-Farbpalette erstellt und diese durch das convert-Tool von ImageMagick schickt: convert image.bmp image.MONO.
Für meinen Code muss die Bildgröße bei den 128x64 Pixeln liegen, die das Display als Auflösung hat. Die disp:drawXBM()-Funktion unterstützt allerdings beliebige Auflösungen (so lange sie auf's Display passen natürlich).

Software am Server

Der letzte Part behandelt schließlich die Software auf dem Server. Dabei handelt es sich um einen kleinen Perl-Daemon, welcher auf Port 1056 lauscht und die Bilddaten aus den Temperatur- und Luftfeuchtigkeitsdaten der Datenbank erstellt. Das Programm findet ihr in der Datei esp8266.pl. Natürlich könnt ihr auch andere Quellen für diese Daten programmieren. Die Funktionen getTemp() und getRh() müssen entsprechend angepasst werden. Es gibt außerdem noch die Funktion getTempGraph(), welche einen Perl-Hash mit der niedrigsten und der höchsten Temperatur zurück gibt. Außerdem ist ein Array in dem Hash mit den letzten 128 Messwerten. In meiner Installation sind das also etwa die letzten zwei Stunden. Damit kann mit der Funktion createPlot() ein Temperaturchart auf dem Display angezeigt werden. Mit derzeitiger Programmierung ist diese Funktion aber nur vorbereitet, wird aber vom WLAN-Modul noch nicht abgefragt. Denkbar wäre etwa ein kleiner Taster, der an der RX- oder TX-Leitung angeschlossen ist und diese Anzeige triggert.

Ansonsten hat der Server noch einen kleinen Cache eingebaut, sodass keine neuen Bilddaten verschickt werden, wenn sich die Daten seit dem letzten update-Request nicht verändert haben. Da man manchmal dennoch ein neues Bild braucht (z.B. nachdem das Display durch die Klingelanimation überschrieben wurde), gibt es noch den pull-Request. Dieser schickt ein neues Bild unabhängig vom Cache.

In einer Debian-Installation könnt ihr den Serverdienst ganz einfach mit meinem mitgelieferten esp8266-init-Script installieren. Kopiert die esp8266.pl nach /usr/local/bin/ und macht diese dort ausführbar. Die esp8266-Datei kommt nach /etc/init.d/ und muss ebenfalls ausführbar gemacht werden. Zu guter letzt noch in die Runlevel linken und fertig. Evtl. benötigt ihr noch ein paar Perl module. Zusammengefasst sieht das dann etwa so aus:

# cp /pfad/zu/esp8266.pl /usr/local/bin/
# cp /pfad/zu/esp8266 /etc/init.d/
# chmod +x /usr/local/bin/esp8266.pl /etc/init.d/esp8266
# update-rc.d esp8266 enable 2 3 4 5
# apt-get install libdbi-perl libdbd-mysql-perl libimage-magick-perl libio-socket-ip-perl libproc-daemon-perl

# /etc/init.d/esp8266 start

Mit telnet könnt ihr testen, ob der Serverdienst erreichbar ist: telnet <IP> 1056.
Hier z.B. updt oder pull gefolgt von Enter eintippen und es sollten ein paar krumme Zeichen zurück gegeben werden. Damit ist jetzt alles fertig und ihr könnt das WLAN-Modul mit Strom versorgen und die ersten Bilder auf dem Display bestaunen.

Ein passendes Gehäuse

Die nackte Platine schön und gut, aber so ist der WAF wohl noch eher im Keller. Zum Glück ist ein weit bekanntes Einrichtungshaus ganz in der Nähe und in der Krusch- und Nippesabteilung fand sich ein günstiges Thermometer das auf den Namen "Klockis" hört (früher hieß es wohl Löttorp). Dank Internet war auch schnell heraus gefunden, wie man die Innereien beseitigt, um eigenes Material unter zu bringen: Tinker Projects Blog. Das Teil gibt's sogar in drei verschiedenen Farben: weiß, grau und schwarz.
Nachdem ihr also die Innereien entfernt habt, könnt ihr noch ein paar Plastikteile, die den Piezosummer und die Knöpfe zum Einstellen gehalten haben, entfernen und das Display mit viel Heißkleber und z.B. mit zwei kleinen Holzleisten befestigen. Messt vor dem Löten genau aus, wie viel Platz eure Platine einnehmen darf, damit sie noch in das Gehäuse passt. Ist die Elektronik verstaut, braucht ihr jetzt eine kinderfreundliche Bastelschere und etwas schwarzes Tonpapier. :D Damit schneidet ihr ein Quadrat in der Größe des Gehäuses aus. Messt von den Seiten, bis wohin das Display geht, zeichnet es auf die Rückseite des Tonpapierstücks und schneidet es zu einem Rahmen (beim Übertragen der Messwerte beachten, dass ihr auf der Rückseite arbeitet - rechts und links sind quasi vertauscht). Das geht am besten mit einem Cuttermesser. Etwas doppelseitiges Klebeband fixiert das Tonpapier auf dem Gehäuse. Weiteres doppelseitiges Klebeband fixiert dann die transparente Folie auf dem Tonpapier, sodass das ganze wieder wie vorher aussieht. Hier noch zwei Bilder zur Illustration:

Display im GehäuseGehäuse fertig verklebt
Hier das Display zwischen den zwei kleinen Holzleisten. Habe das alles mit ordentlich Heißkleber fixiert. Oben rechts sieht man die Hohlbuchse über die der Strom aus dem Steckernetzteil eingespeist wird. Die Buchse steckt in einem etwas aufgefeilten Loch in der ehemaligen Batteriehalterung. Das fertige Gerät mit Anzeige der Uhrzeit, Temperatur und Luftfeuchtigkeit. Man erkennt ganz schwach das Tonpapier, welches das Display einrahmt.

Seitenanfang