Alles Pins am Wemos Mini D1 ausgenutzt

Mein neuer ESPHome Multisensor mit Display für Home Assistant

Mit der ESPHome Plattform kann man in kurzer Zeit umfangreiche Projekte auf Basis der preiswerten ESP8266 und ESP32 Controller umsetzen. Ich zeige in diesem Beitrag eines meiner umfangreicheren ESPHome Projekte.

ESPHome Multisensor mit Display DIY

Mein eigentliches Ziel war ein Gerät auf Basis eines Wemos Mini D1 und ESPHome, um mehrere 1-Wire Temperatursensoren auslesen zu können, die ich an den Vor- und Rückläufen unserer Heizungsanlage, sowie oben, in der Mitte und unten in unserem Pufferspeicher montiert habe. Die 1-Wire Sensoren vom Typ DS18B20 sind nicht nur preiswert und für diese Aufgabe hinreichend genau, sondern können auch gut verlängert werden und es lassen sich etwa 100 Sensoren an einer einzigen Datenleitung betreiben.

Bei mir geht es hingegen nur um 9 Sensoren: Fußbodenheizung Vorlauf/Rücklauf, Wandheizkörper Vorlauf/Rücklauf, wassergeführter Kamin Vorlauf/Rücklauf und eben die 3 Sensoren im Pufferspeicher.

Der fertig aufgebaute ESPHome Multisensor mit Display
Der fertig aufgebaute ESPHome Multisensor mit Display

Nun finde ich es aber immer schade, wenn man einen ESP für nur eine Aufgabe verbrät und die anderen Pins ungenutzt lässt. Also warum nicht gleich noch einen BME280 Sensor nutzen, um die Luftfeuchtigkeit und Temperatur im Technikraum zu messen? Dank des eingebauten Luftdrucksensors kann man dann auch gleich noch die absolute Luftfeuchtigkeit und den Taupunkt ausrechnen lassen.

Und wenn man schon die Daten hat, wäre doch ein Display ganz nett? Dazu hatte ich noch einige Nokia 5110 Displays vom PCD 8544 herumliegen. Mit seinen 84×48 Pixeln ist es für diese Aufgabe optimal geeignet. Mit der passenden Schriftart kann man 6 Zeilen zu 14 Zeichen gut lesbar darstellen. Man bekommt hier einfach mehr unter als bei einem zweizeiligen HD44780 Display und kann auch Grafiken einsetzen.

Zudem unterstützt die ESPHome Plattform bei diesem Display auch „Pages“, sodass man sehr einfach zwischen mehreren Seiten und Anzeigen durchblättern und somit jede Menge Informationen übersichtlich darstellen kann. Zum Blättern braucht es aber auch ein Bedienelement und hier habe ich mich für einen einfachen Taster entschieden, denn für einen Endlos-Encoder waren nicht mehr genug Pins vorhanden. Dafür kann das Display über Home Assistant in der Helligkeit gesteuert werden und ein WS2812 LED-Streifen mit 8 RGB-LEDs gibt Auskunft über verschiedene Betriebszustände.

Der Aufbau

Es ist immer eine gute Idee, solche umfangreicheren Projekte zunächst auf einem Breadboard aufzubauen und zu testen, bevor man sich an den Lötkolben wagt. Funktioniert der fliegende Aufbau wie gewünscht, kann man sich an die Umsetzung auf einer Platine machen.

Testaufbau auf einem Breadboard
Testaufbau auf einem Breadboard

Ich bin von jeher ein Fan von Streifenrasterplatinen. Damit habe ich schon mit 9 Jahren gebastelt, in meiner Ausbildung damit gearbeitet und ich mag die Streifenraster-Philosophie lieber als diese Lötzinnbäche auf Punktraster-Boards. Dabei verfolge auch noch die „reine Lehre“, nämlich dass Drahtbrücken nur in einer Richtung verlaufen. Wemos Mini, Display und BME280 Sensor werden gesteckt, sodass man sie auch schnell mal tauschen könnte.

Der grundlegende Aufbau und Schaltplan meines Multisensors mit Display

Für die Anbindung der 9 1-Wire Sensoren habe ich mich für 9-polige Federklemmblöcke entschieden. 3 Stück davon passen nebeneinander auf eine Europlatinenbreite und sind für die dünnen Adern der DS18B20 Sensoren ideal geeignet. Die Datenleitung der Sensoren muss mit einem 4,7 kOhm Widerstand auf High (3,3 Volt Betriebsspannung) gelegt werden und ein 10 uF Elko direkt an der Spannungsversorgung der Sensoren sorgt für einen stabileren Betrieb. Die 1-Wire Sensoren werden immer in der Reihenfolge DATA (Gelb), VCC (Rot), GND (Schwarz) von links nach rechts angeschlossen.

Der komplette Aufbau passte auf weniger als eine halbe Eurokarte und sieht meiner Meinung nach ganz ordentlich aus.

Natürlich könnte man auch eine richtige Platine gestalten und herstellen (lassen). Allerdings werde ich diesen Aufbau nur ein einziges Mal benötigen, sodass der Aufwand hier nicht gerechtfertigt ist und eine sauber aufgebaute Streifenrasterplatine ist ebenso zuverlässig.

Die Programmierung mit ESPHome

ESPHome ist eine grandiose Lösung für eigene Sensoren und Aktoren. Es basiert auf Arduino Bibliotheken, wird aber in der Hauptsache mit YAML eher konfiguriert, als programmiert. Trotzdem lassen sich auch komplexe Funktionen und Berechnungen damit umsetzen, in dem man mit sogenannten Lambdas auch C-Code innerhalb der YAML Konfiguration einsetzen kann. Was die Programmierung jedoch noch vereinfacht, ist die Integration der ESPHome Plattform direkt in Home Assistant. Hat man die ESPHome Integration in HA, kann man auf Flash-Tools etc. verzichten.

Dazu benötigt man nur den Chrome-Browser oder Edge (vermutlich gehen auch andere Browser, die auf Chromium basieren), denn diese bieten die Web Serial Schnittstelle. Damit verbindet man den ESP per USB mit dem Rechner, an dem man gerade sitzt und kann, öffnet die ESPHome Integration in HA im Browser und kann damit den ESP direkt flashen. Wichtig dabei ist nur, dass die Verbindung zu Home Assistant per SSL erfolgt.

ESPHome direkt aus Home Assistant über den Browser flashen

Hat man das erledigt, wird der neu angelegte und geflashte ESP in der ESPHome Oberfläche als „online“ angezeigt und kann von da an direkt über die Weboberfläche programmiert werden. Auch die Logs des ESP werden darüber ausgegeben und ESPs können von dort aus auch upgedatet werden. Ich habe früher Tasmota und ESPeasy eingesetzt, aber ESPHome ist so viel einfacher, eleganter und flexibler in der Nutzung – besonders wenn man mehrere solcher Geräte im Einsatz hat. Die ESPHome Geräte können praktisch von überall aus programmiert werden, wo man Zugriff auf seinen Home Assistant Server hat.

Der Code für den Multisensor mit Display

Hier zunächst einmal der komplette Programmcode meines ESPHome Multisensors:

esphome: name: technik platform: ESP8266 board: d1_mini # Logging an RX/TX ausschalten, da diese Pins als GPIOs verwendet werden logger: baud_rate: 0 # Home Assistant API aktivieren api: ota: password: "Dein-OTA-Passwort" wifi: ssid: "DEINE-SSID" password: "DEIN-WLAN-PASSWORT" # Fallback hotspot (captive portal) aktivieren, falls WLAN fehlt ap: ssid: "Technik Fallback Hotspot" password: "DEIN_PASSWORT" captive_portal: # GPIO Übersicht und Verbindungen # D0 = RST Display # D1 = I2C SCL BME280 # D2 = I2C SDA BME280 # D3 = DC Display # D4 = 1Wire Data für DS18B20 Sensoren # D5 = SPI CLK Display # D6 = WS2812 LED Data # D7 = CS/CE Display # D8 = SPI MOSI Display Din # RX = Backlight Display = GPIO3 # TX = Switch = GPIO1 # A1 = noch nicht im Einsatz light: # WS2812 LED Infostrip - platform: fastled_clockless chipset: WS2812B id: light_fastled pin: D6 num_leds: 8 rgb_order: GRB name: "Infostrip" effects: - pulse: # LEDs definieren - platform: partition name: "PL0" segments: - id: light_fastled from: 0 to: 0 effects: - pulse: - platform: partition name: "PL1" segments: - id: light_fastled from: 1 to: 1 effects: - pulse: - platform: partition name: "PL2" segments: - id: light_fastled from: 2 to: 2 effects: - pulse: - platform: partition name: "PL3" segments: - id: light_fastled from: 3 to: 3 effects: - pulse: - platform: partition name: "PL4" segments: - id: light_fastled from: 4 to: 4 effects: - pulse: - platform: partition name: "PL5" segments: - id: light_fastled from: 5 to: 5 effects: - pulse: - platform: partition name: "PL6" segments: - id: light_fastled from: 6 to: 6 effects: - pulse: - platform: partition name: "PL7" segments: - id: light_fastled from: 7 to: 7 effects: - pulse: # Displaybeleuchtung - platform: monochromatic name: "Technik Display" output: technik_display output: - platform: esp8266_pwm id: technik_display pin: GPIO03 inverted: true # 1-Wire Sensoren dallas: - pin: D4 # I2C-Bus für BME280 i2c: sda: D2 scl: D1 scan: true id: bus_a # SPI-Bus für Display spi: clk_pin: D5 mosi_pin: D8 # Statusdaten für den ESP holen text_sensor: - platform: template name: Uptime Human Readable id: uptime_human icon: mdi:clock-start - platform: wifi_info ip_address: name: ESP IP Address id: my_ip ssid: name: ESP Connected SSID id: my_SSID bssid: name: ESP Connected BSSID mac_address: name: ESP Mac Wifi Address id: my_mac # 1-Wire Sensoren einbinden sensor: - platform: dallas address: 0x42030297792CC028 resolution: 12 name: "Vorlauf FBH" id: fbh_vl - platform: dallas address: 0x16030297794F1A28 resolution: 12 name: "Rücklauf FBH" id: fbh_rl # BME280 Sensor - platform: bme280 temperature: name: "ESP1 Technik Temperatur" id: bme280_temperature oversampling: 16x pressure: name: "ESP1 Technik Luftdruck" id: bme280_pressure humidity: name: "ESP1 Technik Feuchte" id: bme280_humidity address: 0x76 update_interval: 120s #längere Updateintervalle verhindern Erwärmung des Sensors iir_filter: 4x # Messwerte glätten # WLAN-Signalstärke holen - platform: wifi_signal name: "Technik ESP Wifi Signal" update_interval: 30s id: wlan_signal # Uptime des ESP auslesen und menschenlesbar formatieren - platform: uptime name: Uptime ESP Technik id: uptime_sensor update_interval: 60s on_raw_value: then: - text_sensor.template.publish: id: uptime_human state: !lambda |- int seconds = round(id(uptime_sensor).raw_state); int days = seconds / (24 * 3600); seconds = seconds % (24 * 3600); int hours = seconds / 3600; seconds = seconds % 3600; int minutes = seconds / 60; seconds = seconds % 60; return ( (days ? String(days) + "d " : "") + (hours ? String(hours) + "h " : "") + (minutes ? String(minutes) + "m " : "") + (String(seconds) + "s") ).c_str(); # LCN-WIH Außentemperatursensor von HA holen - platform: homeassistant id: temp_aussen entity_id: sensor.wih_temp_aussen # Luftdruck mit Höhenkorrektur auf 516 Meter berechnen - platform: template name: "Technik Luftdruck" update_interval: 60s lambda: |- const float STANDARD_ALTITUDE = 516; // in Meter return id(bme280_pressure).state / powf(1 - ((0.0065 * STANDARD_ALTITUDE) / (id(bme280_temperature).state + (0.0065 * STANDARD_ALTITUDE) + 273.15)), 5.257); // in hPa unit_of_measurement: 'hPa' # Absolute Luftfeuchtigkeit in g/m3 berechnen - platform: template name: "Technik Absolute Luftfeuchtigkeit" lambda: |- const float mw = 18.01528; // molare Masse von Wasser g/mol const float r = 8.31447215; // universelle Gas-Konstante J/mol/K return (6.112 * powf(2.718281828, (17.67 * id(bme280_temperature).state) / (id(bme280_temperature).state + 243.5)) * id(bme280_humidity).state * mw) / ((273.15 + id(bme280_temperature).state) * r); // in Gramm/m^3 accuracy_decimals: 2 update_interval: 60s icon: 'mdi:water' unit_of_measurement: 'g/m³' id: wsabs # Taupunkt berechnen - platform: template name: "Technik Taupunkt" lambda: return (243.5*(log(id(bme280_humidity).state/100)+((17.67*id(bme280_temperature).state)/ (243.5+id(bme280_temperature).state)))/(17.67-log(id(bme280_humidity).state/100)- ((17.67*id(bme280_temperature).state)/(243.5+id(bme280_temperature).state)))); unit_of_measurement: °C icon: 'mdi:thermometer-alert' # Uhrzeit von Home Assistant holen (für Uptime-Berechnung) time: - platform: homeassistant id: homeassistant_time # Display-Fonts definieren font: - file: "fonts/hd44780.ttf" id: font_a size: 8 - file: "fonts/VCR_OSD_MONO.ttf" id: font_b size: 20 # Icons definieren image: - file: "icons/water-percent.gif" id: water_percent - file: "icons/thermometer.gif" id: thermometer - file: "icons/sm_sad.gif" id: sad resize: 22x24 - file: "icons/sm_neutral.gif" id: neutral resize: 22x24 - file: "icons/sm_happy.gif" id: happy resize: 22x24 # Nokia 5110 Display display: - platform: pcd8544 id: my_display reset_pin: D0 cs_pin: D7 dc_pin: D3 contrast: 0x3f # Wichtig: zu hohe Werte zeigen schwarzes Display! # Mehrere Display-Seiten pages: - id: page1 lambda: |- it.image(0, 0, id(thermometer)); it.printf(14, 0, id(font_b), "%.1f°C", id(bme280_temperature).state); it.image(0, 20, id(water_percent)); it.printf(14, 20, id(font_b), "%.0f", id(bme280_humidity).state); it.printf(38, 22, id(font_a), "%.1f", id(wsabs).state); it.print(38, 30, id(font_a), "g/m3"); if ((id(bme280_humidity).state <= 55)) { it.image(63, 18, id(happy)); } if ((id(bme280_humidity).state >= 56) and (id(bme280_humidity).state <= 68)) { it.image(63, 18, id(neutral)); } if ((id(bme280_humidity).state >= 69)) { it.image(63, 18, id(sad)); } it.strftime(0, 40, id(font_a), "%H:%M-%d.%m.%y", id(homeassistant_time).now()); - id: page2 lambda: |- it.print(0, 0, id(font_a), " HK1 - FBH"); it.print(0, 6, id(font_a), "______________"); it.printf(0, 18, id(font_a), "FBH VL:%.1f C", id(fbh_vl).state); it.printf(0, 28, id(font_a), "FBH RL:%.1f C", id(fbh_rl).state); it.printf(0, 38, id(font_a), "Aussen:%.1f C", id(temp_aussen).state); - id: page3 lambda: |- it.print(0, 0, id(font_a), " HK2 - Wand"); it.print(0, 6, id(font_a), "______________"); it.printf(0, 18, id(font_a), "HK VL:%.1f C", id(fbh_vl).state); it.printf(0, 28, id(font_a), "HK RL:%.1f C", id(fbh_rl).state); it.printf(0, 38, id(font_a), "Aussen:%.1f C", id(temp_aussen).state); - id: page4 lambda: |- it.print(0, 0, id(font_a), " HK3 - Kamin"); it.print(0, 6, id(font_a), "______________"); it.printf(0, 18, id(font_a), "KAM VL:%.1f C", id(fbh_vl).state); it.printf(0, 28, id(font_a), "KAM RL:%.1f C", id(fbh_rl).state); it.printf(0, 38, id(font_a), "Aussen:%.1f C", id(temp_aussen).state); - id: page5 lambda: |- it.print(0, 0, id(font_a), " Puffer"); it.print(0, 6, id(font_a), "______________"); it.printf(0, 18, id(font_a), "Oben: %.1f C", id(fbh_vl).state); it.printf(0, 28, id(font_a), "Mitte: %.1f C", id(fbh_rl).state); it.printf(0, 38, id(font_a), "Unten: %.1f C", id(fbh_rl).state); - id: page6 lambda: |- it.print(0, 0, id(font_a), "Name: Technik"); it.print(0, 6, id(font_a), "______________"); it.printf(0, 16, id(font_a), "Up:%s", id(uptime_human).state.c_str()); it.printf(0, 24, id(font_a), "%s", id(my_ip).state.c_str()); it.printf(0, 32, id(font_a), "%s", id(my_mac).state.c_str()); it.printf(0, 40, id(font_a), "WLAN: %.0f dBm", id(wlan_signal).state); # Taster zum wechseln der Display-Pages binary_sensor: - platform: gpio pin: number: GPIO01 mode: INPUT_PULLUP # internen Pullup einschalten - spart einen Widerstand :-) inverted: True name: "Technik Taster" on_press: then: - display.page.show_next: my_display - component.update: my_display # Status des ESP an HA mitteilen (verbunden oder nicht) - platform: status name: "ESP Technik"
Code-Sprache: YAML (yaml)

Da ich die serielle Schnittstelle des ESP nicht benötige, schalte ich das Loggen dafür in Zeile 8 aus. Damit kann ich die beiden Pins als normale GPIOs nutzen.

Die wichtigsten Konfigurationen und Funktionen im Detail

Viel im Code sind Standardfunktionen, die man ganz einfach nachlesen kann. Ich möchte hier die interessanteren Teile kurz einzeln erklären.

light: # WS2812 LED Infostrip - platform: fastled_clockless chipset: WS2812B id: light_fastled pin: D6 num_leds: 8 rgb_order: GRB name: "Infostrip" effects: - pulse: # LEDs definieren - platform: partition name: "PL0" segments: - id: light_fastled from: 0 to: 0 effects: - pulse: ...
Code-Sprache: PHP (php)

Hier wird der WS2812 LED-Stripe mit 8 RGB-LEDs eingerichtet. Für jedes LED wird die Platform: partition angelegt. Damit kann jedes LED später individuell angesprochen werden. Aktuell ist dafür noch kein weiterer Code enthalten und die Nutzung dieser Funktion, wird erst später hinzukommen. So könnte man darüber etwa anzeigen, wenn man Lüften sollte oder wenn der Brenner der Heizung aktiv ist.

# Displaybeleuchtung - platform: monochromatic name: "Technik Display" output: technik_display output: - platform: esp8266_pwm id: technik_display pin: GPIO03 inverted: true
Code-Sprache: PHP (php)

Die Displaybeleuchtung ist an dem früheren RX-Pin angeschlossen, der nun auf GPIO03 hört. Damit kann das Display von HA aus gesteuert und gedimmt werden.

dallas: - pin: D4 # 1-Wire Sensoren einbinden sensor: - platform: dallas address: 0x42030297792CC028 resolution: 12 name: "Vorlauf FBH" id: fbh_vl - platform: dallas address: 0x16030297794F1A28 resolution: 12 name: "Rücklauf FBH" id: fbh_rl ...
Code-Sprache: PHP (php)

Die DS18D20 1-Wire Temperatursensoren werden hier definiert. Dazu benötigt man die eindeutige ID des jeweiligen Sensors. Entweder schließt man dazu jeden Sensor einmal einzeln an, notiert sich die ID und markiert sie am Sensor oder man schließt alle Sensoren gleichzeitig an, erwärmt jeden Sensor kurz und sieht im Log nach, welche ID gerade eine höhere Temperatur anzeigt.

# Uptime des ESP auslesen und menschenlesbar formatieren - platform: uptime name: Uptime ESP Technik id: uptime_sensor update_interval: 60s on_raw_value: then: - text_sensor.template.publish: id: uptime_human state: !lambda |- int seconds = round(id(uptime_sensor).raw_state); int days = seconds / (24 * 3600); seconds = seconds % (24 * 3600); int hours = seconds / 3600; seconds = seconds % 3600; int minutes = seconds / 60; seconds = seconds % 60; return ( (days ? String(days) + "d " : "") + (hours ? String(hours) + "h " : "") + (minutes ? String(minutes) + "m " : "") + (String(seconds) + "s") ).c_str();
Code-Sprache: PHP (php)

Hier wird die Zeit, die der ESP online ist, in ein menschenlesbares Format umgewandelt, sodass man es später schön im Display und in der HA Oberfläche anzeigen lassen kann.

# LCN-WIH Außentemperatursensor von HA holen - platform: homeassistant id: temp_aussen entity_id: sensor.wih_temp_aussen
Code-Sprache: CSS (css)

Natürlich kann man auch Sensoren aus HA holen. Hier lese ich den Außentemperatursensor meiner LCN-WIH Wetterstation aus, um die Werte im Display anzeigen zu lassen.

# Luftdruck mit Höhenkorrektur auf 516 Meter berechnen - platform: template name: "Technik Luftdruck" update_interval: 60s lambda: |- const float STANDARD_ALTITUDE = 516; // Höhe über Null am Einsatzort in Meter return id(bme280_pressure).state / powf(1 - ((0.0065 * STANDARD_ALTITUDE) / (id(bme280_temperature).state + (0.0065 * STANDARD_ALTITUDE) + 273.15)), 5.257); // in hPa unit_of_measurement: 'hPa' # Absolute Luftfeuchtigkeit in g/m3 berechnen - platform: template name: "Technik Absolute Luftfeuchtigkeit" lambda: |- const float mw = 18.01528; // molare Masse von Wasser g/mol const float r = 8.31447215; // universelle Gas-Konstante J/mol/K return (6.112 * powf(2.718281828, (17.67 * id(bme280_temperature).state) / (id(bme280_temperature).state + 243.5)) * id(bme280_humidity).state * mw) / ((273.15 + id(bme280_temperature).state) * r); // in Gramm/m^3 accuracy_decimals: 2 update_interval: 60s icon: 'mdi:water' unit_of_measurement: 'g/m³' id: wsabs # Taupunkt berechnen - platform: template name: "Technik Taupunkt" lambda: return (243.5*(log(id(bme280_humidity).state/100)+((17.67*id(bme280_temperature).state)/ (243.5+id(bme280_temperature).state)))/(17.67-log(id(bme280_humidity).state/100)- ((17.67*id(bme280_temperature).state)/(243.5+id(bme280_temperature).state)))); unit_of_measurement: °C icon: 'mdi:thermometer-alert'
Code-Sprache: PHP (php)

Hier wieder ein Einsatz für die Lambdas und etwas C-Code zur Berechnung der absoluten Luftfeuchtigkeit etc. Mit lambda: |- teilt man mit, dass alles, was danach kommt und eingerückt ist, als C-Code interpretiert wird. Die Formeln dafür stammen aus dem Internet. Beim Luftdruck ist darauf zu achten, dass man die richtige Höhenangabe einträgt. Der Luftdruck, den der BME280 direkt ausgibt, ist nicht höhenkompensiert.

Das Nokia 5110 Display – Fonts, Icons und Darstellung

# Display-Fonts definieren font: - file: "fonts/hd44780.ttf" id: font_a size: 8 - file: "fonts/VCR_OSD_MONO.ttf" id: font_b size: 20
Code-Sprache: PHP (php)

Für das Nokia 5110 PCD8544 Display müssen Schriftarten definiert werden. Grundsätzlich kann man jeden TrueType-Font (.ttf) dafür nutzen. Allerdings klappt das nur für große Texte und auch hier sieht nicht jeder Font gut aus. Für die kleinstmögliche leserliche Darstellung sind 7×5 (Pixel) Fonts ideal. So findet man z. B. bei wfonts.com die hd44780.ttf Schriftart, welche klar lesbar ist und 6 Zeilen zu 14 Zeichen erlaubt. Für großen Text habe ich mich für VCR_OSD_MONO.ttf bei dafont.com entschieden.

Fonts-Verzeichnis unter esphome im VScode Editor

Die Fonts lädt man in ein Verzeichnis unterhalb des esphome Verzeichnisses. Das geht ganz einfach per VSCode Integration in HA. Einfach einen Ordner fonts (der Name ist egal) anlegen, rechten Mausklick darauf und Upload auswählen.

# Icons definieren image: - file: "icons/water-percent.gif" id: water_percent - file: "icons/thermometer.gif" id: thermometer - file: "icons/sm_sad.gif" id: sad resize: 22x24 - file: "icons/sm_neutral.gif" id: neutral resize: 22x24 - file: "icons/sm_happy.gif" id: happy resize: 22x24
Code-Sprache: PHP (php)

Ich habe für den Haupt-Screen meines ESP einige Icons eingebaut. Ein Thermometer, Wassertropfen und 3 Smilies, die Auskunft über die Luftfeuchtigkeit geben. Auch hier legt man sich wieder ein Verzeichnis unterhalb von esphome an – in meinem Fall icons – und lädt die entsprechenden Grafiken hoch. Ich hatte allerdings nur mit GIF-Dateien Erfolg. PNGs, egal ob mit oder ohne Alphakanal, zeigten immer nur einen schwarzen Block an.

Das Hauptmenü meines Multisensors
# Nokia 5110 Display display: - platform: pcd8544 id: my_display reset_pin: D0 cs_pin: D7 dc_pin: D3 contrast: 0x3f # Wichtig: zu hohe Werte zeigen schwarzes Display! # Mehrere Display-Seiten pages: - id: page1 lambda: |- it.image(0, 0, id(thermometer)); it.printf(14, 0, id(font_b), "%.1f°C", id(bme280_temperature).state); it.image(0, 20, id(water_percent)); it.printf(14, 20, id(font_b), "%.0f", id(bme280_humidity).state); it.printf(38, 22, id(font_a), "%.1f", id(wsabs).state); it.print(38, 30, id(font_a), "g/m3"); if ((id(bme280_humidity).state <= 55)) { it.image(63, 18, id(happy)); } if ((id(bme280_humidity).state >= 56) and (id(bme280_humidity).state <= 68)) { it.image(63, 18, id(neutral)); } if ((id(bme280_humidity).state >= 69)) { it.image(63, 18, id(sad)); } it.strftime(0, 40, id(font_a), "%H:%M-%d.%m.%y", id(homeassistant_time).now());
Code-Sprache: PHP (php)

Nun wird das Display konfiguriert. Wichtig ist die contrast Einstellung. In der offiziellen Dokumentation wird hier der Wert contrast: 0x7f angegeben. Damit erhält man aber nur ein komplett schwarz gefülltes Display und glaubt erst einmal an einen Verkabelungsfehler. Tatsächlich handelt es sich aber nur um einen viel zu hohen Kontrast. Mit contrast: 0x3f wird die Schrift meiner Ansicht nach ideal dargestellt.

Bei den print– und image-Anweisungen bedeutet printf(14,20 … ), dass die Schrift 14 Pixel nach rechts und 20 Pixel nach unten, ausgehend von der linken oberen Ecke der Anzeige dargestellt werden soll.

Vor- und Rücklauf der Fußbodenheitung sowie Außentemperatur

Mit pages: und id: page1 nutze ich die Möglichkeit, Inhalte auf mehrere Displayseiten zu verteilen. Page1 ist mein Hauptscreen, der beim Start erscheint und Raumtemperatur sowie Luftfeuchtigkeit groß mit einem Icon davor darstellt. Neben der Luftfeuchtigkeit zeige ich noch kleiner die absolute Luftfeuchtigkeit an. Daneben, je nach Luftfeuchte, einen passenden Smilie und darunter die aktuelle Uhrzeit und das Datum.

Mit it.printf(14, 0, id(font_b), „%.1f°C“, id(bme280_temperature).state); wird die Temperatur im C-Stil auf eine Nachkommastelle formatiert (%.1f).

Mit den if-Anweisungen werden die Smilies nach einem Schwellwert geändert und zu guter Letzt die Uhrzeit angezeigt.

<meta charset="utf-8"/># Taster zum wechseln der Display-Pages binary_sensor: - platform: gpio pin: number: GPIO01 mode: INPUT_PULLUP # internen Pullup einschalten - spart einen Widerstand :-) inverted: True name: "Technik Taster" on_press: then: - display.page.show_next: my_display - component.update: my_display
Code-Sprache: YAML (yaml)

Hier wird der Taster am GPIO01 abgefragt. Mit INPUT_PULLUP kann man den internen Pullup aktivieren und man spart sich damit die externe Beschaltung mit einem Widerstand, der für einen definierten Logikpegel sorgt. Wenn der Taster gedrückt wird, sorgen die beiden letzten Zeilen dafür, dass die Seiten (Pages) nacheinander durchgeschaltet und anzeigt werden.

Eine Seite mit Systeminformationen

Tipps

Zum BME280 Sensor gibt es im Netz viele Diskussionen. Ursprünglich wurde der Sensor von Bosch entwickelt. Geht man nach dem Datenblatt der Firma Bosch, müssen die Sensoren in einem speziellen Prozess verlötet und dann bei definierten Bedingungen getrocknet und eingebrannt werden.

Bei den günstigen China-Sensoren kann man nicht wirklich sicher sagen, ob es sich um Bosch-Typen oder Kopien handelt und der Verarbeitungsprozess wird ganz sicher nicht eingehalten. Daher wird immer davon gesprochen, dass diese China-Varianten ungenau wären. Achtet man jedoch darauf, dass der Sensor möglichst weit von Wärmequellen wie dem ESP8266 entfernt montiert wird und die Zuleitungen möglichst lang (und dünn) sind, liefert der BME280 nach meinen Erfahrungen und auch Vergleichsmessungen mit gesättigten Salzlösungen (siehe auch: https://nachbelichtet.com/guenstige-xiaomi-mijia-ble-sensoren-mit-home-assistant-nutzen/) sehr genaue Werte.

Häufig ist auch die Erwartung an einen Messwert schlichtweg Unsinn. Es geht nicht darum, den besten und genausten Messwert zu erhalten, sondern den Messwert, der zur Anwendung passt. Die Lufttemperatur unterscheidet sich selbst in kleinen Räumen und je nach Messhöhe und Position im Raum nicht selten um 2 °C. Gleiches gilt für die Luftfeuchtigkeit. Sind also 22,7 °C richtiger als 23,4 °C? Nein! Denn verzichtet man auf die Nachkommastelle, kämen für diesen Einsatz vollkommen ausreichende 23 Grad als Messwert heraus.

Aqara Multisensoren für Temperatur, Luftfeuchtigkeit und Luftdruck
Aqara Multisensoren für Temperatur, Luftfeuchtigkeit und Luftdruck

Doch selbst hier sagt der Messwert noch nichts darüber aus, ob man sich bei dieser Temperatur auch wohlfühlt. Das Wohlfühlklima wird über die Temperatur, die Luftfeuchtigkeit und die Luftbewegung definiert. So nimmt die gefühlte Temperatur bei steigender Luftfeuchtigkeit zu und umgekehrt. 21 °C Lufttemperatur fühlen sich bei 55 % rel. Luftfeuchte schon wie 23 °C und bei 75 % wie 26 °C an. Daher fühlt sich auch recht warme, aber trockene Heizungsluft im Winter gar nicht so muggelich an, wie man oft erwarten würde. Kommt dann auch noch eine leichte Luftbewegung hinzu, können sich 23 °C wie 20 °C anfühlen.

Die DS18B20 Sensoren sollte man alle in einen Eimer Wasser mit hängen, dessen Temperatur mit einem vertrauenswürdigen Thermometer gemessen hat. So kann man die Sensoren nach Genauigkeit und Abweichung selektieren. Bei der Messung von Vor- und Rücklauf einer Niedrigtemperaturheizungen, macht 1 °C Abweichung schon etwas aus. Wenn dann die Rücklauftemperatur höher ist als der Vorlauf, kann man keine vernünftige Steuerung darauf aufbauen. Daher sollten beide Sensoren die gleichen relativen Messwerte liefern. Abweichungen vom tatsächlichen Messwert kann man dann ggf. auch noch per Software kompensieren.

Bauteile und Kosten

Das gesamte Projekt kostet weniger als 10 Euro. Die 5110 Displays bekommt man für weniger als 2 Euro bei diversen China-Versendern (auf die neuen Regelungen beim Versand aus China achten – siehe HIER !). Ein ESP Wemos Mini kostet auch nur 2 Euro. Bestellt man ihn aus Deutschland, muss man etwa 4,50 Euro rechnen. BME280 Sensor, Platine und die Klemmen sind für weitere 3-4 Euro zu haben.

Nicht in den Kosten enthalten sind die DS18B20 1-Wire Sensoren. Hier bekommt man 10 Stück für unter 20 Euro. Auf Basis dieses Grund-Codes kann man viele universelle Smarthome-Sensoren mit Display günstig herstellen. Da man sowohl einen I2C- als auch einen SPI-Bus zur Verfügung hat, kann man problemlos noch weitere Sensoren einbinden und damit den Funktionsumfang nach den eigenen Wünschen und Anforderungen erweitern.

Abonnieren
Benachrichtige mich bei
Das Kommentarformular speichert deine Namen, deine E-Mail-Adresse und den Inhalt, damit wir den Überblick über die auf der Website veröffentlichten Kommentare behalten können. Bitte lies und akzeptiere unsere Website-Bedingungen und Datenschutzerklärung, um einen Kommentar zu schreiben.
4 Kommentare
Inline Feedbacks
View all comments

Als Amazon-Partner verdiene ich an qualifizierten Verkäufen. Irrtümer und Preisfehler vorbehalten.