WiFi-Thermostat-Projekt-Repository mit Maschinencodes für die Zielplattform ESP8266 und ESP32: Github repo
Die Firmware WiFi_Thermostat und WiFi_Thermostat_mDNS ist in englischer Sprache für die Mikrocontroller ESP32 und ESP8266 (Espressif Systems) verfügbar. Die experimentelle Version der Basis-Firmware mit manueller Ausgabesteuerung ist nur in slowakischer Sprache verfügbar.
ESP8266 ESP32 WiFi DS18B20 OneWire Dallas HTML Webserver WebSocket JSON mDNS UART
Mikrocontroller steuern NodeMCU v2 / v3 Lolin - ESP8266-12E / ESP8266-12F
NodeMCU (ESP8266)
Mikrocontroller steuern Wemos D1 Mini - ESP8266-12E / ESP8266-12F
Wemos D1 Mini (ESP8266)
Mikrocontroller steuernr ESP32 Devkit V1 - ESP-WROOM-32 / ESP32-S
ESP32 DevKit

WiFi Thermostat - ESP8266 / ESP32


Die Softwareimplementierung ist für Mikrocontroller-Plattformen des Herstellers Espressif Systems mit WiFi-Konnektivität ausgelegt. Unterstützte WiFi (2,4 GHz) ESP8266- und ESP32-Mikrocontroller. Der WiFi-Thermostat ist über das LAN-Netzwerk, in dem er sich befindet, zugänglich, während er mit einer Weboberfläche ausgestattet ist, die dazu dient, alle Elemente des Thermostats zu konfigurieren und gleichzeitig die aktuellen Zustände zu visualisieren. Der Thermostat regelt den Kessel auf Basis der gemessenen Solltemperatur und Hysterese unabhängig von der Webapplikation, die zur Konfiguration und Entscheidungsschwelle des Thermostats dient. Neben der Verfügbarkeit des Thermostats unter einer bestimmten IP-Adresse kann der Thermostat mit einem mDNS-Record ergänzt werden, der innerhalb dieses Multicast-Dienstes eine nur im LAN-Netzwerk erreichbare lokale Domain (hostname.local) generiert. Die Konfiguration des Thermostats (aus Sicht der Konnektivität) im Heim-WLAN-LAN-Netzwerk wird durch den WiFiManager gesichert, der Daten über das WLAN-Netzwerk (SSID und Passwort) im Flash-Speicher des Mikrocontrollers speichert. Die Speicherung erfolgt einmalig und das Gerät merkt sich die Konfiguration dauerhaft. Nach dem Herstellen der Konnektivität (Zuweisung einer IP-Adresse vom Router Ihres WLAN-Heimnetzwerks) kann der Thermostat vollständig verwendet werden. Der HTTP-Webserver, der auf dem ESP8266 / ESP32-Mikrocontroller läuft, ermöglicht das Ausführen mehrerer unabhängiger HTML-Seiten, die informativ oder sogar funktional sein können.

In Bezug auf die Hardware verwendet das Projekt:
  • ESP8266 / ESP32
  • Temperatursensor DS18B20 am OneWire-Bus
  • Relais SRD-5VDC-SL-C / OMRON G3MB-202P zur Kesselschaltung (Active-LOW-Signal)

  • HTML-Seiten mit ESP8266 / ESP32:
  • / - Grundseite mit Formular, aktueller Logikausgang für das Relais, aktuelle und Solltemperatur, Hysterese
  • /action.html - verarbeitet Werte aus dem Formular, schreibt sie in den emulierten EEPROM-Speicher, leitet den Benutzer zurück zur Stammseite
  • /get_data.json - verteilt Daten zur aktuellen Temperatur, Referenztemperatur und Hysterese an Dritte (Computer, Mikrocontroller, anderer Client ...) im JSON-Format - kann mit dem Beispiel verwendet werden JSON-Client, der Daten an MQTT Broker senden kann, zum Beispiel an die Hausautomation

  • Erweitert mit HTML-Seiten in einer experimentellen Version mit manuellem Modus, falls vorhanden:
  • /on.html - Ausgabe im manuellen Modus dauerhaft einschalten
  • /vyp.html - Ausgabe im manuellen Modus dauerhaft deaktivieren
  • /automat.html - Modus auf Automatik ändern (verwendet Hysterese und Zieltemperatur)
  • /manual.html - Wechseln Sie in den manuellen Modus (permanente EIN / AUS-Hardsteuerung)

  • Die Auflösung des DS18B20 Sensors während der Messung beträgt 12 Bit, was durch die Temperaturauflösung bei 0,0625 °C angezeigt wird, was ebenfalls ein minimaler Schritt zwischen den verschiedenen Messwerten ist. Daten über den OneWire-Bus können bei Bedarf in 500 bis 1000 ms an den Mikrocontroller zurückgesendet werden, je nach Anzahl der Sensoren, Buslänge. Das im Projekt verwendete elektromagnetische Relais SRD-5VDC-SL-C ermöglicht das Schalten bis 10A bei 230V - Leistung 2300W. Beim Schalten eines Gleichstromkreises (Last) können 300W (10A bei 30V DC) geschaltet werden. Alternativ ist das OMRON G3MB-202P SSR-Relais voll kompatibel zum Schaltplan, der nur für nicht induktive Lasten und ausschließlich für Wechselstromkreise geeignet ist. Maximale Schaltleistung 460W (230V, 2A). Der Thermostat kann das ganze Jahr über verwendet werden. Im Falle einer unnötigen Steuerung ist es möglich, den Ausgang physisch zu trennen und den Thermostat als WLAN-Thermometer zu verwenden, um Daten aus dem Raum zu erhalten, in dem er sich befindet.


    Bei Firmware mit Unterstützung für die manuelle Steuerung des GPIO-Ausgangs des ESP-Mikrocontrollers kann der Thermostat physisch ausgeschaltet werden, ohne ihn von der Relaisklemme trennen zu müssen. Die Thermostatlogik wird unabhängig vom Webserver und angeschlossenen Clients alle 10 Sekunden ausgeführt, für die Ausführung ist keine Keep-Alive-Verbindung erforderlich. Bei jeder Ausführung der Logik schreibt der Thermostat auch Informationen über die aktuelle IP-Adresse oder den mDNS-Record (bei Verwendung mit mDNS-Firmware) auf den UART-Thermostat und gibt so dem Benutzer Auskunft darüber, wo der Thermostat mit seinem Webinterface im LAN erreichbar ist Netzwerk. Darüber hinaus listet es auch den dynamischen freien Speicher - HEAP, der von 40 bis 44 kB reicht, sowie den aktuellen Status der Ausgabe mit Benachrichtigung über die Änderung, falls sie auftritt -> (wenn die Entscheidungsschwelle nach + oder nach - fließt) ). Die 3V3-GPIO-Betriebslogik der ESP8266- und ESP32-Mikrocontroller reicht für ein digitales Änderungssignal aus, aber das Relais muss mit 5 V von VUSB bzw. VIN versorgt werden.

    Die Webschnittstelle des WiFi-Thermostats ermöglicht Ihnen:
  • Sehen Sie in Echtzeit die Temperatur des DS18B20-Sensors, die Betriebszeit des Geräts, den Ausgabewert mit dynamischer Änderung, die aktuell eingestellten Konfigurationsdaten für den Thermostat, d. Solltemperatur und Hysterese
  • Ändern Sie die Ziel-(Referenz-)Temperatur im Bereich von 5 bis 50 °C in Schritten von 0,25 °C
  • Ändern Hysterese von 0 bis 10 ° C in Schritten von 0,25 ° C
  • Die Programmimplementierung eines Thermostats mit automatischer und manueller Leistungsregelung ist experimentell!
    Kessel EIN / AUS-Steuerung - Automatikmodus:
  • Beispiel für EIN / AUS der Heizungssteuerung - VISUALISIERUNG IST NICHT TEIL DES PROJEKTS
  • Der Kessel ist aktiv, solange die Solltemperatur + Hysterese erreicht ist
  • Die Visualisierung von Wassertemperaturen zeigt die sogenannte Heizlauf und anschließendes Abkühlen des Wassers bis die Heizung wieder aktiviert wird, wenn die gemessene Temperatur unter der eingestellten Solltemperatur liegt - Hysterese
  • ZAP/VYP regulácia kotla s hysterézou

    In der Basisversion des WiFi-Thermostats (ohne mDNS-Aufzeichnung) wurde ein manueller Steuermodus (hart EIN / AUS) implementiert mit der Möglichkeit zwischen manuellem und automatischem Modus umzuschalten. Die Weboberfläche ist für größere und kleinere Bildschirme ausgelegt. Es ist reaktionsschnell und unterstützt hochauflösende Breitbild-Bildschirme sowie mobile Geräte. Die Schnittstelle verwendet importierte CSS-Stile des Bootstrap-Frameworks von einem externen CDN-Server, der das clientseitige Gerät lädt, wenn eine Seite geöffnet wird, die auf ESP ausgeführt wird. Durch den Import von CSS-Stilen von einem externen Server wird die Strom- und Speicherbelastung des Mikrocontrollers reduziert.


    Um die eingestellten Werte des Thermostats auch nach einem Stromausfall beizubehalten, werden diese im EEPROM-Speicher ESP gespeichert, der im Flash-Speicher emuliert wird, da die Plattform keinen physikalischen EEPROM-Chip (Speicher) besitzt. Referenztemperatur auf Offset 10, Hysterese auf Offset 100. Jeder der Werte belegt maximal 5B im EEPROM-Speicher + das Endezeichen. Die Daten werden erst beim Senden des HTML-Formulars überschrieben, der Betrieb des Thermostats schont den EEPROM-Speicher für maximale Haltbarkeit. Der Zustand des Ausgangs existiert nur im RAM-Speicher, wo er bei der Änderung überschrieben wird. Der Wert wird nicht im emulierten EEPROM-Speicher im Flash-Speicher abgelegt.


    Wenn das Gerät beim ersten Start nichts auf den genannten EEPROM-Offsets gespeichert hat, wird das automatische Schreiben mit Standardwerten durchgeführt - Referenz: 20,25 ° C, Hysterese 0,00 ° C. Dadurch wird sichergestellt, dass der Thermostat auf Mikrocontrollern arbeiten kann, die nichts im EEPROM-Speicher geschrieben haben - ausfallsichere Lösung. ESP8266 und ESP32 verwenden die Funktion EEPROM.put(), um in den EEPROM-Speicher zu schreiben, der jeden Datentyp unterstützt, und EEPROM.commit(), um das Schreiben in den Ziel-Offset zu bestätigen. Die Implementierung verwendet den Datentyp float() für eine 32-Bit-Zahl, die im EEPROM gespeichert wird und zur Referenz-(Soll-)Temperatur sowie Hysterese gehört. Mit dem Refresh-Meta-Tag aktualisiert der Webserver alle 30 Sekunden die gesamte HTML-Seite und die JavaScript-Zeit bis zum Refresh wird ebenfalls per Javascript in die HTML-Seite geschrieben. Zu diesem Zeitpunkt ist es notwendig, die Änderung für den Thermostaten zu schreiben, da sonst die Eingabefenster für numerische Eingaben in das Formular beim Aktualisieren der Seite zurückgesetzt werden. Da die eingebaute Ethernet-Bibliothek die Verwendung eines asynchronen Webservers nicht beinhaltet (der beispielsweise mit den Espressif ESP8266 / ESP32-Mikrocontrollern verwendet werden kann), ist es erforderlich, die gesamte Seite neu zu schreiben, da diese Implementierung 1:1 ist mit dem originalen Ethernet-Thermostat.


    Die sich hauptsächlich ändernden dynamischen Daten sind der aktuelle Wert der Ausgabe - EIN / AUS , die den Bediener über den aktuellen Zustand der Ausgabe zusammen mit der Farbcodierung informiert. Da die Systemlogik unabhängig vom Webserver ausgeführt wird, kann sich die Ausgabe bereits in einem anderen Zustand befinden als aktuell in der Webanwendung aufgelistet. Die Ausgabeänderung wird z. B. sofort auf den UART-Monitor geschrieben. Auf der Website des Thermostats findet der Benutzer auch Informationen über die Betriebszeit des Geräts (wie lange es in Betrieb war), d. Zeit in Tagen, Stunden, Minuten und Sekunden. Der Thermostat ist nur für Innentemperaturen gedacht! (über 0°C), an die die Systemlogik angepasst ist! Der Thermostat kann verwendet werden, um einen vorhandenen Raumthermostat zu ersetzen, die Heizung im Aquarium / Terrarium kann vorübergehend ersetzt werden, um eine konstante Temperatur zu halten.

    Der Autor des WiFi-Thermostats ist nicht verantwortlich für die Funktionalität des Thermostats, Kesselausfall, Stromschlag aufgrund einer unsachgemäßen Installation des Thermostats im Netzwerk. Der Thermostat wird unter der MIT-Lizenz vertrieben.
    Hauptseite zur Änderung der Zieltemperatur und der Hysterese - Demo auf:
    Beispieldaten
  • Zieltemperatur: 22.75 °C
  • Hysterese: 0.25 ° C
  • Messdaten: 22.49 ° C
  • Ausgabe: EIN

  • Der Thermostat heizt ab einer gemessenen Temperatur von 22.49 °C und darunter. Wenn die Temperatur 23.01 °C erreicht, wird der Ausgang ausgeschaltet, das Melderelais öffnet und der Gaskessel hört auf zu heizen. Das Aufheizen und Abkühlen des Raumes, in dem die Messungen durchgeführt werden, erfolgt. Der Thermostat wird erst wieder aktiviert, wenn die Temperatur 22.49 °C oder niedriger erreicht.

    Hauptseite zur Änderung der Solltemperatur und Hysterese: WiFi-Thermostat - Hauptübersicht mit Änderung von Solltemperatur und Hysterese Verarbeitungsprozess der eingegebenen Daten (Nutzerumleitung): WiFi-Thermostat - Datenverarbeitung aus HTML-Formular JSON-Webserverausgabe im Browser / Client über Websocket:
    WiFi thermostat - JSON output
    Ausgabe an UART-Monitor - Systemlogik + IP-Adresse einstellen, mDNS-Record:
    WiFi termostat - UART - ESP8266 - mDNS záznam WiFi termostat - UART - ESP32 - výstup - ovládanie kotla
    Eine erweiterte Version des WiFi-Thermostats umfasst:
  • Bearbeitbarer Quellcode (.ino)
  • Verfügbare Sensoren SHT21, SHT31, DHT22, BME280, BMP280 für die Kesselsteuerung
  • Kühlmodus (inverse Logik zum Heizthermostat)
  • Basic OTA, OTA Web Updater, Eleganter Remote OTA
  • Möglichkeit, die Ausgabe über Callbacks zu steuern, die von UDP-Datagrammen über UDP-Clients (Packet Sender) aufgerufen werden.
  • Interaktion mit Amazon Alexa Echo Dot mit der Möglichkeit der Sprachsteuerung des Thermostats (UDP-Rückrufe)
  • Möglichkeit zur Veröffentlichung von Daten an MQTT Broker / per HTTP / HTTPS-Anfrage an einen entfernten Webserver mit Datenspeicherung in einer MySQL-Datenbank (ohne JSON-Client)

  • Beispielanweisung im JSON-Format

  • Fähigkeit, JSON-Clients zu verarbeiten (mit kompatibler Firmware für Arduino + Ethernet / ESP8266 / ESP32 - im Repository verfügbar)
  • Möglichkeit, Daten an MQTT Broker zu senden und an andere Clients zu verteilen, die das Zielthema abonnieren können
  • Fähigkeit, das JSON-Format von anderen Clients zu lesen - JSON-Parser, Editor, Viewer und andere ...
  • {
    "Hysteresis":0.25,
    "Target_Temperature":21.75,
    "Actual_Temperature":21.43
    }

    Thermostat - Quellcode

  • Thermostatlogik in minimaler Implementierung, ohne Webserver, WiFi-Konnektivität und emuliertem EEPROM-Speicher - allgemeine Implementierung
  • Muster für Ethernet- und WiFi-Thermostat für alle Mikrocontroller - Arduino, ESP8266, ESP32 mit demselben Quellcode
  • //Projekt: Minimale Implementierung - Thermostat
    //Autor: Martin Chlebovec
    //Hardware: Arduino / ESP8266 / ESP32 + DS18B20 (1x OneWire-Bus)
    //Überprüfung: 23. Mar. 2020
    
    #include <OneWire.h>
    #include <DallasTemperature.h>
    
    #define ONE_WIRE_BUS 23 //datovy vovod OneWire zbernice na pin D23
    OneWire oneWire(ONE_WIRE_BUS);
    DallasTemperature sensorsA(&oneWire);
    float nastavena_teplota = 24.50;
    float hystereza = 0.50;
    //float hystereza2 = 0.50;
    const int rele = 6;
    //const int rele2 = 7;
    unsigned long timer = 0;
    unsigned long interval = 15000; //ako casto chceme logiku spustit --> v ms (milisekundy)
    void setup() {
      sensorsA.begin();
      Serial.begin(115200);
      Serial.println("UART ready");
      pinMode(rele, OUTPUT);
      // pinMode(rele2, OUTPUT);
    }
    
    void loop() {
      if ((millis() - timer) >= interval || timer == 0) {
        timer = millis();
        sensorsA.requestTemperatures();
        delay(2000); //cakame na teploty
        float  teplota1 = sensorsA.getTempCByIndex(0);
        //float  teplota2 = sensorsA.getTempCByIndex(1);
        float rozdiel = nastavena_teplota - teplota1;
        if (rozdiel > hystereza) {
          digitalWrite(rele, HIGH); //zopnutie rele
          Serial.println("Rele bolo zopnute - Vystup aktivny");
        } else if (rozdiel < (-1 * hystereza)) {
          digitalWrite(rele, LOW); //rozopnutie rele
          Serial.println("Rele bolo rozopnute - Vystup neaktivny");
        }
    
        /*
          float rozdiel2 = nastavena_teplota2 - teplota2;
          if (rozdiel2 > hystereza2) {
          digitalWrite(rele2, HIGH); //zopnutie rele
          } else if (rozdiel2 < (-1 * hystereza2)) {
          digitalWrite(rele2, LOW); //rozopnutie rele
          }
        */
      }
    }
    

    Quellcode zum Auflisten der aktuell gemessenen Daten - HTML-Code - ohne Backend

              Client handling  
              HTTP header
      int days = millis() / day ;                                //number of days
      unsigned int hours = (millis() % day) / hour;                       //the remainder from days division (in milliseconds) divided by hours, this gives the full hours
      unsigned int minutes = ((millis() % day) % hour) / minute ;         //and so on...
      unsigned int seconds = (((millis() % day) % hour) % minute) / second;
      String stranka = F("<!DOCTYPE html>");
      stranka += F("<html>");
      stranka += F("<head>");
      stranka += F("<meta charset='utf-8'>");
      stranka += F("<meta name='author' content='Martin Chlebovec'>");
      stranka += F("<meta http-equiv='Refresh' content='30'; />");
      stranka += F("<meta name='viewport' content='width=device-width, initial-scale=1'>");
      stranka += F("<link rel='stylesheet' href='https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css'>");
      stranka += F("<script type='text/javascript'>");
      stranka += F("var timeleft = 30;");
      stranka += F("var downloadTimer = setInterval(function(){");
      stranka += F("if(timeleft <= 0){");
      stranka += F("clearInterval(downloadTimer);");
      stranka += F("document.getElementById(\"countdown\").innerHTML = \"Refreshing...\";");
      stranka += F("} else {");
      stranka += F("document.getElementById(\"countdown\").innerHTML = timeleft + \" seconds to refresh\";");
      stranka += F("}");
      stranka += F("timeleft -= 1;");
      stranka += F("}, 1000);");
      stranka += F("</script>");
      stranka += F("<title>WiFi thermostat - ESP8266</title>");
      stranka += F("</head>");
      stranka += F("<body>");
      stranka += F("<center><h3>Enter datas for web server:</h3>");
      stranka += F("<form action='/action.html' method='post'>");
      stranka += "<b>Target temperature:</b><br><input type='text' id='fname' name='fname' min='5' max='50' step='0.25' value=" + String(read_String(10)) + "><br>";
      stranka += "<b>Hysteresis:</b><br><input type='text' id='fname2' name='fname2' min='0' max='10' step='0.25' value=" + String(read_String(100)) + "><br>";
      stranka += F("<input type='submit' class='btn btn-success' value='Send'>");
      stranka += F("</form><hr>");
      if (stav == "ON") {
        stranka += F("<b><font color='green'>Output: ON</font></b>");
      }
      if (stav == "OFF") {
        stranka += F("<b><font color='red'>Output: OFF</font></b>");
      }
      stranka += F("<div id=\"countdown\"></div>");
      stranka += F("<b>Current sensor DS18B20 temperature:</b> ");
      stranka += String(teplota);
      stranka += F(" °C");
      stranka += F("<hr>");
      stranka += F("<b>Uptime: </b>");
      stranka += String(days);
      stranka += F("d");
      stranka += F(" ");
      stranka += String(hours);
      stranka += F("h");
      stranka += F(" ");
      stranka += String(minutes);
      stranka += F("m");
      stranka += F(" ");
      stranka += String(seconds);
      stranka += F("s");
      stranka += F("<h3>Author: Martin Chlebovec - martinius96@gmail.com - https://martinius96.github.io/WiFi-termostat/</h3>");
      stranka += F("<h4>Free version - 1.0.4 build: 06. Oct. 2021</h4>");
      stranka += F("</center>");
      stranka += F("</body>");
      stranka += F("</html>");
    	  SEND TO CLIENT
    	  FLUSH CLIENT
    	  STOP CLIENT
    

    Ein Ausschnitt des HTML-Quellcodes einer Seite nach der Verarbeitung von Daten aus einem HTML-Formular

  • Verwendete die Weiterleitung des Benutzers zurück zur Hauptberichtsseite 5 Sekunden nach der Verarbeitung der in das Formular eingegebenen Daten.
  • Art der Ladefaulheit. Das Snippet enthält weder ein Backend zur Datenverarbeitung noch funktionale Teile der Website.
  • 	    Backend_Verarbeitung von Daten aus HTML-Formular
    	    .
    	    .
    	    .
                HTTP header
      String stranka = F("<!DOCTYPE html>");
      stranka += F("<html>");
      stranka += F("<head>");
      stranka += F("<meta charset='utf-8'>");
      stranka += F("<meta http-equiv='Refresh' content='5; url=/' />");
      stranka += F("<title>WiFi thermostat - ESP8266 - data processing</title>");
      stranka += F("</head>");
      stranka += F("<body>");
      stranka += F("<center><h3>Server received datas from HTML form:</h3>");
      stranka += "<li><b>Target temperature: </b>" + String(read_String(10)) + " °C</li>";
      stranka += "<li><b>Hysteresis: </b>" + String(read_String(100)) + " °C</li>";
      stranka += F("<b>Redirecting... Please wait</b></center>");
      stranka += F("</body>");
      stranka += F("</html>");
    	    SEND TO CLIENT
    	    FLUSH CLIENT
    	    STOP CLIENT