Die Idee: Mit einem E-Paper-Display die relevanten Informationen nur 1x oder 2x pro Stunde aktualisieren und den ESP32 zwischendurch schlafen legen. Das E-Paper-Display hält die Anzeige bis zum nächsten Update aktiv. Die Daten sollen wir schon im OLED-Beispiel beschrieben über MQTT über ioBroker abgerufen werden.
Das Projekt hat eine gewisse Komplexität und der fertige Zustand von Display und ESPHome-YAML hat einige Stunden testen und ausprobieren benötigt. Insbesondere die Platzierung der einzelnen Elemente auf dem Display über die x- und y-Koordinaten mit den Update-notwendigen Kompilierungen verschlingt Zeit.
Was benötigen wir für das Dashboard im Bilderrahmen und was müssen wir für die Umsetzung beachten:
Hardware:
- Waveshare E-Paper-Driver Board ESP32
- Wir benötigen auf jeden Fall die CPU-Power und den Speicher eines ESP32, der kleinere Bruder mit ESP8266 reicht für die meisten Anwendungsfälle nicht aus. Der Vorteil am Driver Board von Waveshare: Bei Nutzung eines Waveshare Displays kann dieses direkt auf dem Board mit dem flachen Kabel ohne weitere PinOuts angeschlossen werden.
- Waveshare E-Paper Display 7.5inch V2
- Dieses Display passt perfekt in 13cmx18cm Rahmen, um einigermaßen optisch ansprechend aufgestellt oder aufgehängt zu werden.
- 13cm x 18cm Bilderrahmen
-
17%Carrera RC LiFePo4 AKKU 6,4V 900mAH 9,5A (Artnr. 370600051), Lithium-Ionen17,99 € 10,41 €
-
Waveshare Universal e-Paper Driver Board with WiFi SoC ESP32 Onboard Supports Va...21,99 €
-
USB Cable 1A for LiFePo4 3,2V Batteries5,24 €
-
Carrera LiFePo4 Akku 3,2V 700mAH 7A RC, Farbe Colorato, 37060005015,06 €
-
Waveshare 7.5 Inch E-Paper Display Hat Module V2 Kit 800x480 Resolution 3.3v/5v ...69,99 €
-
VictoR Bilderrahmen Nolde Schwarz in 13x18 cm - Leiste 11x13mm - Holzrahmen - Ra...9,49 €
Mit allen Bestandteilen und Zubehör belaufen sich die Kosten auf ca. 100€.
ESPHome, YAML:
- Wetterdaten
- Wir müssen die Wetterdaten für unseren Standort über einen ioBroker-Adapter beziehen. Praktisch wäre die Vorschau über die nächsten Stunden des aktuellen Tages und auch die nächsten Tage.
- Die Vorschau soll nicht nur durch Text sondern auch durch Grafiken dargestellt werden können.
- Wir sind letztendlich bei Accuweather fündig geworden
- Problem: Accuweather bildet über knapp 40 Icons die grafische Wettervorhersage ab, wir benötigen eine smarte und ressourcenschonende Lösung für die Einbindung der Wetter-Grafiken.
- Vorhersage-Grafiken
- Nach einige Tests ist unserer Meinung nach der schnellste und ressourcenschonendste Weg die vorhandenen Accuweather-SVG-Grafiken in einen Webfont zu konvertieren und diesen in ESPHome einzubinden.
- Betrieb mit Akku/Batterie nur mit deepsleep des ESP32
- deepsleep zu aktivieren ist in ESPHime eine Kleinigkeit, die Logik den deepsleep zu unterbrechen, um Updates auf den ESP32 zu spielen, benötigt etwas mehr Auseinandersetzung mit dem Thema, um die Steuerung über MQTT abzubilden
- Auswahl der Batterie oder des Akkus
- Ein ESP32 wird typischerweise mit 3,3 Volt betrieben. LiPos liegen im Bereich von 3,7 bis 4,2 Volt, 3x AA-Batterien bei 4,5 Volt, 3x AA NiMh-Akkus bei 3,6 Volt. Spannung über 3,3 Volt muss im ESP32 auf 3,3 Volt kontinuierlich reduziert werden und bedeutet Akku-Kapazität-Ineffizienz. Nach einigen Test fällt unsere Empfehlung auf 3,2 Volt LiFePo4-Akkus.
- Berechnung und Bereitstellung der benötigten Informationen über Blockly-Script in ioBroker
Unser YAML für ESPHome bildet folgende logische Blöcke ab:
- Grundkonfiguration für WLAN, MQTT und Display
- MQTT-Topics
- Automatische Aktualisierung des E-Paper-Display bei Start
- Deepsleep-Logik inkl. Unterbrechung durch MQTT-Topic
- Batterie-Spannung Messen
- Definition der Schriftarten
- Mapping der Wettergrafiken-ID zu den Symbolen der Schriftart
- Platzierung der Dashboard Elemente und Variablen
Fangen wir mit 1. Grundkonfiguration an. Dies können wir wie bereits hier beschrieben 1:1 übernehmen.
Für die benötigten MQTT-Topics macht man sich am besten einen Plan, was alles auf dem Dashboard angezeigt werden soll. Dort können wir Platzierung und Bezeichnung der benötigten Variablen/Topics definieren. Unser erster Entwurf:
Das praktische an den MQTT-Topics in ESPHome ist die Tatsache, dass beim ersten Abonnement die Topics in den ioBroker-Objekten automatisch angelegt werden (um dann über ein Blockly-Script mit den entsprechenden Daten zu füllen). Hier ein Ausschnitt unserer abonnierten MQTT-Topics:
# MQTT Topics abonnieren text_sensor: - platform: mqtt_subscribe id: h_g topic: esphome/RahmenDashboard/h_g - platform: mqtt_subscribe id: h_t topic: esphome/RahmenDashboard/h_t - platform: mqtt_subscribe id: h_l topic: esphome/RahmenDashboard/h_l - platform: mqtt_subscribe id: h_txt topic: esphome/RahmenDashboard/h_txt - platform: mqtt_subscribe id: h_12_g topic: esphome/RahmenDashboard/h_12_g - platform: mqtt_subscribe id: h_12_t topic: esphome/RahmenDashboard/h_12_t - platform: mqtt_subscribe id: h_12_r topic: esphome/RahmenDashboard/h_12_r - platform: mqtt_subscribe id: h_12_w topic: esphome/RahmenDashboard/h_12_w
Auf Grund des deepsleep-Verhaltens und der Tatsache, dass der ESP32 möglichst batterieschonend schnell wieder in den Tiefschlaf versetzt werden soll, haben wir die Aktualisierung des Displays über ein Timeout geregelt. Nach dem Aufwachen des ESP32 muss dieser sich zunächst mit dem WLAN verbinden, den connect zum MQTT-Server herstellen und die Topics abrufen, danach erst kann das Display mit den aktualisierten Werten refreshed werden. Unsere Config sieht haben wir wie folgt definiert:
esphome: name: rahmendashboard friendly_name: RahmenDashboard on_boot: - delay: 20s - component.update: RDis - logger.log: "Update Screen"
20 Sekunden nach dem erfolgreichen Bootvorgang wird das Display aktualisiert, 30 Sekunden nach dem Bootvorgang der ESP32 für 30min in den Tiefschlaf versetzt:
# Deepsleep Konfiguration deep_sleep: id: deep_sleep_rahmen run_duration: 25s sleep_duration: 30min
Wird der ESP32 mit Strom versorgt, geht das Device also unweigerlich nach 30 Sekunden in den Tiefschlaf und ist z.B. für ein OTA-Update der YAML-Konfiguration nicht erreichbar.
Um eine aktive Deepsleep-Konfiguration zu unterbrechen, gibt es glücklicherweise in ESPHome den Befehl deep_sleep.prevent. Die Idee: Wir setzen ein MQTT-Topic auf einen bestimmten Wert, fragen den Wert bei Start des ESP32 ab und stoppen den deepsleep. Exakt derselbe Weg soll genutzt werden, um nach einem erfolgreichen OTA-Update den deepsleep wieder zu aktiveren.
In unserem Fall lösen wir dies über ein Topic OTA. Ist das Topic leer, dann bootet und schläft das Device wie definiert, enthält das Topic „OTA“ wird der deepsleep unterbrochen und das Device bleibt online. Um das Device wieder schlafen zu legen, setzen wir das Topic OTA auf SLEEP. Unmittelbar nach Übertragung des MQTT-Topics, fällt das Device in den Tiefschlaf, um den nächsten Bootvorgang nicht frühzeitig mit dem nächsten Tiefschlaf vorzeitig zu beenden, müssen wir das Topic OTA wieder leeren. Der entsprechende Code im MQTT-Bereich:
# MQTT Konfiguration mqtt: broker: ##IP-Adresse MQTT Server## username: !secret mqtt_user password: !secret mqtt_password client_id: RahmenDashboard topic_prefix: esphome on_message: # OTA Steuerung - topic: esphome/RahmenDashboard/ota payload: 'OTA' then: - deep_sleep.prevent: deep_sleep_rahmen - logger.log: deepsleep off - topic: esphome/RahmenDashboard/ota payload: 'SLEEP' then: - deep_sleep.enter: deep_sleep_rahmen - logger.log: deepsleep on
Schön wäre es außerdem, wenn wir die Spannung der Batterie bzw. des Akkus monitoren könnten. Hierzu dient die Komponente ADC in ESPHome. Wir müssen lediglich die +-Leitung des Akkus mit einem geeigneten GPIO des ESP32 verbinden, z.B. GPIO33. Die ermittelte Spannung wird per MQTT an ioBroker übertragen und wir können den Wert dort auswerten. Z.B. um ein low-battery-Alert mit Pushover abzusetzen. Unsere YAML-Config:
sensor: # Spannung der Batterie an GPIO33 messen - platform: adc pin: GPIO33 id: SpannungBatterie attenuation: auto update_interval: 20s accuracy_decimals: 2 on_value: - mqtt.publish: topic: esphome/RahmenDashboard/Batterie payload: !lambda |- return to_string(id(SpannungBatterie).state);
Etwas umständlich ist die Definition der benötigten Schriftarten. Entgegen der üblichen Erfahrung in WORD und ähnlichen Programmen, können wir nicht am eigentlichen Text selbst die Formatierung vornehmen. Dies wird übergreifend in einer FONT-Definition geregelt. Ressourcenschonend können außerdem nur die Zeichen angegeben und in die Firmware kompiliert werden, die wir benötigen. Dies wird insbesondere für Schriftarten mit Grafiken interessant:
# Schriftarten definieren font: - file: "Fonts/Verdana.ttf" id: Verdana25 glyphs: [';', '&', '@', '!', ',', '.', '?', '"', '%', '(', ')', '+', '-', '_', ':', '°', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', ' ', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z','å', 'Ä', 'ä', 'Ö', 'ö', 'Ü', 'ü', '/','ß'] size: 25 - file: "Fonts/Verdana.ttf" id: Verdana21 glyphs: [';', '&', '@', '!', ',', '.', '?', '"', '%', '(', ')', '+', '-', '_', ':', '°', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', ' ', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z','å', 'Ä', 'ä', 'Ö', 'ö', 'Ü', 'ü', '/','ß'] size: 21 - file: "Fonts/Verdana.ttf" id: Verdana35 glyphs: [';', '&', '@', '!', ',', '.', '?', '"', '%', '(', ')', '+', '-', '_', ':', '°', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', ' ', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z','å', 'Ä', 'ä', 'Ö', 'ö', 'Ü', 'ü', '/','ß'] size: 32 - file: "Fonts/Verdana.ttf" id: Verdana18 glyphs: [';', '&', '@', '!', ',', '.', '?', '"', '%', '(', ')', '+', '-', '_', ':', '°', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', ' ', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z','å', 'Ä', 'ä', 'Ö', 'ö', 'Ü', 'ü', '/','ß'] size: 20 - file: "Fonts/Verdana.ttf" id: Verdana12 glyphs: [';', '&', '@', '!', ',', '.', '?', '"', '%', '(', ')', '+', '-', '_', ':', '°', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', ' ', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z','å', 'Ä', 'ä', 'Ö', 'ö', 'Ü', 'ü', '/','ß'] size: 12 - file: "Fonts/Verdana.ttf" id: Verdana60 glyphs: [';', '&', '@', '!', ',', '.', '?', '"', '%', '(', ')', '+', '-', '_', ':', '°', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', ' ', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z','å', 'Ä', 'ä', 'Ö', 'ö', 'Ü', 'ü', '/','ß'] size: 40 # liste https://developer.accuweather.com/weather-icons - file: "Fonts/accuweathericons.ttf" id: Icon75 size: 170 glyphs: - "\ue900" - "\ue901" - "\ue90a" - "\ue911" - "\ue91a" - "\ue922" - "\ue927" - "\ue928" - "\ue929" - "\ue92a" - "\ue921" - "\ue92e" - "\ue936" - "\ue940" - "\ue942" - "\ue948" - "\ue950" - "\ue956" - "\ue958" - "\ue95e" - "\ue966" - "\ue96a" - "\ue972" - "\ue973" - "\ue977" - "\ue97d" - "\ue981" - "\ue983" - "\ue985" - "\ue986" - "\ue987" - "\ue98a" - "\ue98d" - "\ue990" - "\ue994" - "\ue996" - "\ue99c" - "\ue9a1" - "\ue9a5" - "\ue9a8" - "\ue9ab" - file: "Fonts/accuweathericons.ttf" id: Icon60 size: 60 glyphs: - "\ue900" - "\ue901" - "\ue90a" - "\ue911" - "\ue91a" - "\ue922" - "\ue927" - "\ue928" - "\ue929" - "\ue92a" - "\ue921" - "\ue92e" - "\ue936" - "\ue940" - "\ue942" - "\ue948" - "\ue950" - "\ue956" - "\ue958" - "\ue95e" - "\ue966" - "\ue96a" - "\ue972" - "\ue973" - "\ue977" - "\ue97d" - "\ue981" - "\ue983" - "\ue985" - "\ue986" - "\ue987" - "\ue98a" - "\ue98d" - "\ue990" - "\ue994" - "\ue996" - "\ue99c" - "\ue9a1" - "\ue9a5" - "\ue9a8" - "\ue9ab" - file: "Fonts/accuweathericons.ttf" id: Icon40 size: 50 glyphs: - "\ue900" - "\ue901" - "\ue90a" - "\ue911" - "\ue91a" - "\ue922" - "\ue927" - "\ue928" - "\ue929" - "\ue92a" - "\ue921" - "\ue92e" - "\ue936" - "\ue940" - "\ue942" - "\ue948" - "\ue950" - "\ue956" - "\ue958" - "\ue95e" - "\ue966" - "\ue96a" - "\ue972" - "\ue973" - "\ue977" - "\ue97d" - "\ue981" - "\ue983" - "\ue985" - "\ue986" - "\ue987" - "\ue98a" - "\ue98d" - "\ue990" - "\ue994" - "\ue996" - "\ue99c" - "\ue9a1" - "\ue9a5" - "\ue9a8" - "\ue9ab" - file: "Fonts/accuweathericons.ttf" id: Icon25 size: 45 glyphs: - "\ue900" - "\ue901" - "\ue90a" - "\ue911" - "\ue91a" - "\ue922" - "\ue927" - "\ue928" - "\ue929" - "\ue92a" - "\ue921" - "\ue92e" - "\ue936" - "\ue940" - "\ue942" - "\ue948" - "\ue950" - "\ue956" - "\ue958" - "\ue95e" - "\ue966" - "\ue96a" - "\ue972" - "\ue973" - "\ue977" - "\ue97d" - "\ue981" - "\ue983" - "\ue985" - "\ue986" - "\ue987" - "\ue98a" - "\ue98d" - "\ue990" - "\ue994" - "\ue996" - "\ue99c" - "\ue9a1" - "\ue9a5" - "\ue9a8" - "\ue9ab" - file: "Fonts/materialdesignicons.ttf" id: Icons_gross100 size: 100 glyphs: - "\U000F1A74" # Solar - "\U000F1904" # Haus - "\U000F1AAF" # Heizung - "\U000F058F" # WasserhahnF050F - "\U000F050F" # Thermometer - "\U000F054B" # Regenschirm - file: "Fonts/materialdesignicons.ttf" id: Icons_gross size: 25 glyphs: - "\U000F1A74" # Solar - "\U000F1904" # Haus - "\U000F1AAF" # Heizung - "\U000F058F" # WasserhahnF050F - "\U000F050F" # Thermometer - "\U000F054B" # Regenschirm - file: "Fonts/materialdesignicons.ttf" id: Icons_mittel size: 23 glyphs: - "\U000F1A74" # Solar - "\U000F1904" # Haus - "\U000F1AAF" # Heizung - "\U000F058F" # Wasserhahn - "\U000F050F" # Thermometer - "\U000F054B" # Regenschirm - "\U000F15FA" # Wind - file: "Fonts/materialdesignicons.ttf" id: Icons_klein size: 22 glyphs: - "\U000F1A74" # Solar - "\U000F1904" # Haus - "\U000F1AAF" # Heizung - "\U000F058F" # Wasserhahn - "\U000F050F" # Thermometer - "\U000F054B" # Regenschirm - "\U000F15FA" # Wind - "\U000F1A45" # Heizung - "\U000F0EB8" # Gas
Ein spannender Bestandteil ist das Mapping der Wettergrafiken. In den ioBroker-Daten werden Grafiken mit einem numerischen Index bereitgestellt, die wir dann auf unsere Symbole in der Schriftart mappen müssen. Dies erfolgt in der Display-Definition:
display: - platform: waveshare_epaper cs_pin: GPIO15 #D2 dc_pin: GPIO27 #D3 busy_pin: GPIO25 #D4 reset_pin: GPIO26 #D5 model: 7.50inV2 reset_duration: 2ms update_interval: never rotation: 180 id: RDis lambda: |- std::map<std::string, std::string> awi_map { {"1", "\ue900"}, {"2", "\ue901"}, {"3", "\ue90a"}, {"4", "\ue911"}, {"5", "\ue91a"}, {"6", "\ue922"}, {"7", "\ue927"}, {"8", "\ue928"}, {"11", "\ue929"}, {"12", "\ue92a"}, {"13", "\ue92e"}, {"14", "\ue936"}, {"15", "\ue940"}, {"16", "\ue942"}, {"17", "\ue948"}, {"18", "\ue950"}, {"19", "\ue956"}, {"20", "\ue958"}, {"21", "\ue95e"}, {"22", "\ue966"}, {"23", "\ue96a"}, {"24", "\ue972"}, {"25", "\ue973"}, {"26", "\ue977"}, {"29", "\ue97d"}, {"30", "\ue981"}, {"31", "\ue983"}, {"32", "\ue985"}, {"33", "\ue986"}, {"34", "\ue987"}, {"35", "\ue98a"}, {"36", "\ue98d"}, {"37", "\ue990"}, {"38", "\ue994"}, {"39", "\ue996"}, {"40", "\ue99c"}, {"41", "\ue9a1"}, {"42", "\ue9a5"}, {"43", "\ue9a8"}, {"44", "\ue9ab"} };
Hier werden alle numerischen Werte auf die Symbole der Schriftart gemapped. Aber welche Schriftart sollen wir nehmen? Ein Klassiker ist MaterialDesign-Webfont – der Font bietet aber bei weitem nicht so viele Wettersymbole, wie uns Accuweather dies in den numerischen Werten liefert, siehe in dieser Übersicht.
In den Objekten ist auch eine Verlinkung von SVG-Grafiken enthalten. Wir haben einen effizienten Weg für die Einbindung gefunden: Wir konvertieren auf https://icomoon.io/app/ alle SCG-Grafiken zu einem Font, binden diesen in ESPHome ein und mappen die numerischen Values auf die entsprechenden Symbole.
Wir downloaden den Font und definieren in den FONT-Deklarationen alle benötigten Symbole:
- file: "Fonts/accuweathericons.ttf" id: Icon25 size: 45 glyphs: - "\ue900" - "\ue901" - "\ue90a" - "\ue911" - "\ue91a" - "\ue922" - "\ue927" - "\ue928" - "\ue929" - "\ue92a" - "\ue921" - "\ue92e" - "\ue936" - "\ue940" - "\ue942" - "\ue948" - "\ue950" - "\ue956" - "\ue958" - "\ue95e" - "\ue966" - "\ue96a" - "\ue972" - "\ue973" - "\ue977" - "\ue97d" - "\ue981" - "\ue983" - "\ue985" - "\ue986" - "\ue987" - "\ue98a" - "\ue98d" - "\ue990" - "\ue994" - "\ue996" - "\ue99c" - "\ue9a1" - "\ue9a5" - "\ue9a8" - "\ue9ab"
Haben wir diese Vorarbeiten erledigt, kommen wir zum grafischen Teil der Umsetzung.
Der zeitlich aufwendigste Teil ist tatsächlich das Setzen der einzelnen grafischen Bestandteile auf dem Display. Jedes einzelne Element muss über die x- und y-Koordinaten auf dem Display platziert werden, im Fall des Waveshare E-Paper Display 7.5inch V2 stehen uns 800×480 Pixel zur Verfügung. Ein Auszug aus unserer YAML:
it.filled_rectangle(0, 326, 800, 55, COLOR_ON); it.strftime(0, 0, id(Verdana18), TextAlign::TOP_LEFT, "%H:%M", id(sntp_time).now()); it.printf(25, 170, id(Icon75), TextAlign::BOTTOM_LEFT, "%s", awi_map[id(h_g).state.c_str()].c_str()); it.printf(280, 30, id(Verdana60), TextAlign::TOP_CENTER, "%s", id(h_t).state.c_str()); it.printf(280, 80, id(Verdana35), TextAlign::TOP_CENTER, "%s", id(h_l).state.c_str()); it.printf(200, 160, id(Verdana18), TextAlign::TOP_CENTER, "%s", id(h_txt).state.c_str()); it.line(400, 5, 400, 190, grey); it.line(5, 190, 795, 190, grey); it.printf(456, 23, id(Icons_klein), TextAlign::TOP_RIGHT, "\U000F1A74"); it.printf(456, 46, id(Icons_klein), TextAlign::TOP_RIGHT, "\U000F1904"); it.printf(456, 69, id(Icons_klein), TextAlign::TOP_RIGHT, "\U000F058F"); it.printf(456, 92, id(Icons_klein), TextAlign::TOP_RIGHT, "\U000F1AAF"); it.printf(430, 115, id(Icons_klein), TextAlign::TOP_RIGHT, "\U000F1AAF"); it.printf(430, 138, id(Icons_klein), TextAlign::TOP_RIGHT, "\U000F1AAF"); it.printf(430, 161, id(Icons_klein), TextAlign::TOP_RIGHT, "\U000F1AAF"); it.printf(456, 115, id(Icons_klein), TextAlign::TOP_RIGHT, "\U000F058F"); it.printf(456, 138, id(Icons_klein), TextAlign::TOP_RIGHT, "\U000F1A74"); it.printf(456, 161, id(Icons_klein), TextAlign::TOP_RIGHT, "\U000F0EB8"); it.filled_rectangle(400, 2, 400, 23, COLOR_ON); it.printf(505, 0, id(Verdana18), COLOR_OFF, TextAlign::TOP_CENTER, "Heute"); it.printf(505, 23, id(Verdana18), TextAlign::TOP_CENTER, "%s", id(pv_h_p).state.c_str()); it.printf(505, 46, id(Verdana18), TextAlign::TOP_CENTER, "%skW", id(strom_h_p).state.c_str()); it.printf(505, 69, id(Verdana18), TextAlign::TOP_CENTER, "%sl", id(w_w_h).state.c_str()); it.printf(505, 92, id(Verdana18), TextAlign::TOP_CENTER, "%skW", id(hzg_h_h).state.c_str()); it.printf(505, 115, id(Verdana18), TextAlign::TOP_CENTER, "%skW", id(hzg_ww_h).state.c_str()); it.printf(505, 138, id(Verdana18), TextAlign::TOP_CENTER, "%skW", id(hzg_y_h).state.c_str()); it.printf(505, 161, id(Verdana18), TextAlign::TOP_CENTER, "%sqm", id(hzg_g_h).state.c_str());
Neben dem Setzen der grafischen Bestandteile ist die Befüllung der MQTT-Topics mit einigem Aufwand verbunden. Einige Werte können 1:1 aus bestehenden Objekten übernommen werden, andere Werte müssen zunächst berechnet werden.
Wir unterscheiden zwischen zwei Typen von Werten:
- Berechnung nur 1x pro Tag
- Dies betrifft vor allem Verbrauchswerte, die in der Vergangenheit liegen.
- Berechnung mehrfach über den Tag
- Dies betrifft vor allem Verbrauchswerte oder Wetterinformationen, die wir über den Tag hinweg aktualisieren wollen.
Uns kam in der Umsetzung dieses Projekts ein neues Blockly-Element gerade recht, das die Auswertung von historischen Werten eine Datenpunkts ermöglicht. So können wir maximale oder durchschnittliche Werte von Objekten grafisch einfach bestimmen und in das MQTT-Topic schreiben, z.B. der durchschnittliche tägliche Stromverbrauch über die letzten 7 Tage.
Das Ergebnis sind einige Inhalte auf 800 x 480 Pixel, die bei uns im 30-Minuten-Abstand regelmäßig aktualisiert werden.
Danke für die ausführliche Anleitung. Gerade der deep-sleep-Teil ist in vielen Seiten nur unvollständig beschrieben, hiermit habe ich es auch verstanden und umsetzen können. Wir nutzen gerade noch einen LiPo mit 3,7V und 2000mAh, wollen aber auch den Akku umstellen auf LiFePo4.
DANKE!
Danke für die tolle Anleitung, vor allem die Idee mit dem verhindern des Schlafens wenn ein Wert gesetzt wird ist klasse.
Ich habe etwas sehr ähnliches mit gleicher Hardware gebaut. Allerdings habe ich das Problem das der ESP32 nicht wieder aufwacht. Hast du vielleicht eine Idee was das sein kann?
Danke im Voraus
Ist die „Aufwachzeit“ korrekt angegeben?
Danke auch von mir. Ich würde das gerne nachbauen. Ich frage mich gerade nur, wie der LiFePo4 im Rahmen geladen wird.
Funktioniert das über die USB Buchse des ESP32?
Nein, hierfür wird ein LiFePo-Ladegerät benötigt und der Akku wird zum Laden entfernt.
Wie viele Aufwach- und Refresh-Zyklen hält der Akku denn durch? Ich stehe vor der Entscheidung, ob ich einen solchen Akku nebst Ladegerät anschaffe, oder ein Kabel auf der Wand akzeptiere. Wenn ich nur sehr selten wieder aufladen muss, würde ich die Akkulösung bevorzugen, bei einmal Laden pro Woche, wird aber der Aufwand schon recht hoch.