55#include < WiFiClient.h>
66#include < PubSubClient.h>
77#include < esp_task_wdt.h>
8+ #include " secrets.h"
89
910#define LED_ERROR 23
1011#define LED_MSG 22
1112#define LED_OK 19
1213#define ONE_WIRE_BUS 25
1314static byte debug = 0 ;
15+ static String lastError = " " ;
1416
1517// Sicherheitsfunktionen
1618int volatile hardwareError = 0 ; // Indikator, ob ein Sensordefekt erkannt wurde.
@@ -22,25 +24,18 @@ int volatile panicMode = 0; // Indikator für die Zwangsabschaltung - ab jet
2224#define PHASE_12V 18 // Steuerpin für Phase 5V Versorgung zum ESP32 Heizstabsteuerung
2325
2426// Definition der Zugangsdaten WiFi
25- #define HOSTNAME " ESP32_Heizung_PowerGuard2"
26- const char * ssid = " MyNETWORK" ;
27- const char * password = " MyPASSWORD" ;
2827WiFiClient myWiFiClient;
2928
3029// Definition der Zugangsdaten MQTT
31- #define MQTT_SERVER " MyIP"
32- #define MQTT_PORT 1883
33- #define MQTT_USER " My_ioBrokerUSER"
34- #define MQTT_PASSWORD " My_ioBrokerPASSWORD"
35- #define MQTT_CLIENTID " ESP32_PowerGuard2" // Name muss eineindeutig auf dem MQTT-Broker sein!
30+ #define MQTT_CLIENTID " ESP32_PowerGuard" // Name muss eineindeutig auf dem MQTT-Broker sein!
3631#define MQTT_KEEPALIVE 90
3732#define MQTT_SOCKETTIMEOUT 30
38- #define MQTT_SERIAL_PUBLISH_STATUS " SmartHome/Keller/Heizung/ESP32_PowerGuard2 /status"
39- #define MQTT_SERIAL_RECEIVER_COMMAND " SmartHome/Keller/Heizung/ESP32_PowerGuard2 /command"
40- #define MQTT_SERIAL_PUBLISH_DS18B20 " SmartHome/Keller/Heizung/ESP32_PowerGuard2 /Temperatur/"
41- #define MQTT_SERIAL_PUBLISH_STATE " SmartHome/Keller/Heizung/ESP32_PowerGuard2 /state/"
42- #define MQTT_SERIAL_PUBLISH_CONFIG " SmartHome/Keller/Heizung/ESP32_PowerGuard2 /config/"
43- #define MQTT_SERIAL_PUBLISH_BASIS " SmartHome/Keller/Heizung/ESP32_PowerGuard2 /"
33+ #define MQTT_SERIAL_PUBLISH_STATUS " SmartHome/Keller/Heizung/ESP32_PowerGuard /status"
34+ #define MQTT_SERIAL_RECEIVER_COMMAND " SmartHome/Keller/Heizung/ESP32_PowerGuard /command"
35+ #define MQTT_SERIAL_PUBLISH_DS18B20 " SmartHome/Keller/Heizung/ESP32_PowerGuard /Temperatur/"
36+ #define MQTT_SERIAL_PUBLISH_STATE " SmartHome/Keller/Heizung/ESP32_PowerGuard /state/"
37+ #define MQTT_SERIAL_PUBLISH_CONFIG " SmartHome/Keller/Heizung/ESP32_PowerGuard /config/"
38+ #define MQTT_SERIAL_PUBLISH_BASIS " SmartHome/Keller/Heizung/ESP32_PowerGuard /"
4439String mqttTopic;
4540String mqttJson;
4641String mqttPayload;
@@ -61,6 +56,10 @@ float tempHysterese = 2.0; //bei Unterschreitung von (tmpLimit-tempHysterese)
6156float deltaT = 2.0 ; // Limit des Betrags von Differenz zwischen tempTop1 tempTop2 (|tempTop1-tempTop2|)
6257float minTemp = 10.0 ; // untere Plausibilitätsgrenze für Temperatursignale. Bei Unterschreitung => Notabschaltung, da ggf. Sensor defekt
6358float maxTemp = 100.0 ; // obere Plausibilitätsgrenze für Temperatursignale. Bei Überschreitung => Notabschaltung, da ggf. Sensor defekt
59+ int volatile tempTSensorFail = 0 ; // Fehlercounter zur Temperaturmessung - Resilienz gegen gelegentliche Fehlauswertungen der Temperatursensoren
60+ int maxTSensorFail = 3 ; // maximal zulässige, hinereinander folgende Sensorfehler - danach panicStop
61+ float DS18B20_minValue = -55.0 ; // unterster Messwert im Messbereich [°C]
62+ float DS18B20_maxValue = 125.0 ; // unterster Messwert im Messbereich [°C]
6463
6564// Initialisiere OneWire und Thermosensor(en)
6665OneWire oneWire (ONE_WIRE_BUS);
@@ -307,7 +306,10 @@ void printStateMQTT() {
307306 mqttTopic = MQTT_SERIAL_PUBLISH_STATE;
308307 mqttTopic += " JSON" ;
309308 mqttJson = " {\" panicMode\" :\" " + String (panicMode) + " \" " ;
310- mqttJson += " ,\" thermalLimit\" :\" " + String (thermalLimit) + " \" }" ;
309+ mqttJson += " ,\" thermalLimit\" :\" " + String (thermalLimit) + " \" " ;
310+ mqttJson += " ,\" hardwareError\" :\" " + String (hardwareError) + " \" " ;
311+ mqttJson += " ,\" lastError\" :\" " + String (lastError) + " \" " ;
312+ mqttJson += " ,\" WiFi_Signal_Strength\" :\" " + String (WiFi.RSSI ()) + " \" }" ;
311313 if (debug > 2 ) Serial.println (" MQTT_JSON: " + mqttJson);
312314 mqttClient.publish (mqttTopic.c_str (), mqttJson.c_str ());
313315 // panicMode
@@ -317,20 +319,34 @@ void printStateMQTT() {
317319 mqttClient.publish (mqttTopic.c_str (), mqttPayload.c_str ());
318320 if (debug > 2 ) Serial.print (" MQTT panicmode: " );
319321 if (debug > 2 ) Serial.println (mqttPayload);
320- // thermalLimit
322+ // thermalLimit
321323 mqttTopic = MQTT_SERIAL_PUBLISH_STATE;
322324 mqttTopic += " thermalLimit" ;
323325 mqttPayload = String (thermalLimit);
324326 mqttClient.publish (mqttTopic.c_str (), mqttPayload.c_str ());
325327 if (debug > 2 ) Serial.print (" MQTT thermalLimit: " );
326328 if (debug > 2 ) Serial.println (mqttPayload);
327- // thermalLimit
329+ // hardware Error
328330 mqttTopic = MQTT_SERIAL_PUBLISH_STATE;
329331 mqttTopic += " hardwareError" ;
330332 mqttPayload = String (hardwareError);
331333 mqttClient.publish (mqttTopic.c_str (), mqttPayload.c_str ());
332334 if (debug > 2 ) Serial.print (" MQTT hardwareError: " );
333335 if (debug > 2 ) Serial.println (mqttPayload);
336+ // lastError
337+ mqttTopic = MQTT_SERIAL_PUBLISH_STATE;
338+ mqttTopic += " lastError" ;
339+ mqttPayload = lastError;
340+ mqttClient.publish (mqttTopic.c_str (), mqttPayload.c_str ());
341+ if (debug > 2 ) Serial.print (" LastError: " );
342+ if (debug > 2 ) Serial.println (mqttPayload);
343+ // WiFi Signalstärke
344+ mqttTopic = MQTT_SERIAL_PUBLISH_STATE;
345+ mqttTopic += " WiFi_Signal_Strength" ;
346+ mqttPayload = WiFi.RSSI ();
347+ mqttClient.publish (mqttTopic.c_str (), mqttPayload.c_str ());
348+ if (debug > 2 ) Serial.print (" WiFi Signalstärke: " );
349+ if (debug > 2 ) Serial.println (mqttPayload);
334350}
335351// MQTT Config und Parameter senden
336352void printConfigMQTT () {
@@ -402,14 +418,13 @@ void mqttConnect () {
402418 Serial.print (" wird aufgebaut " );
403419 while (!mqttClient.connected ()) {
404420 Serial.print (" ." );
405- i++;
406421 if (mqttClient.connect (MQTT_CLIENTID, MQTT_USER, MQTT_PASSWORD, MQTT_SERIAL_PUBLISH_STATUS, 0 , true , " false" )) {
407422 mqttClient.publish (MQTT_SERIAL_PUBLISH_STATUS, " true" , true );
408423 Serial.println (" " );
409424 Serial.print (" MQTT verbunden!" );
410425 }
411426 else {
412- if (i > 20 ) {
427+ if (++ i > 20 ) {
413428 Serial.println (" MQTT scheint nicht mehr erreichbar! Reboot!!" );
414429 ESP.restart ();
415430 }
@@ -454,6 +469,9 @@ static void MQTTwatchdog (void *args){
454469 // ticktime initialisieren
455470 ticktime = xTaskGetTickCount ();
456471
472+ er = esp_task_wdt_add (NULL ); // Task zur Überwachung hinzugefügt
473+ assert (er == ESP_OK);
474+
457475 for (;;){ // Dauerschleife des Tasks
458476 // Watchdog zurücksetzen
459477 esp_task_wdt_reset ();
@@ -471,8 +489,28 @@ static void MQTTwatchdog (void *args){
471489
472490// -------------------------------------
473491// Subfunktionen für den TempSensor-Task
492+ // Temperatursensorenwerte auf die Limits prüfen
493+ bool checkDS18B20Value (float t){
494+ bool res = true ; // true = im Messbereich; false = außerhalb des Messbereichs
495+ if ((t < DS18B20_minValue) || (t > DS18B20_maxValue)){
496+ // Sensorwert außerhalb des Messbereichs
497+ res = false ;
498+ }
499+ if (debug > 2 ) Serial.print (" Prüfe t-Wert auf Gültigkeit: " );
500+ if (debug > 2 ) Serial.print (t);
501+ if (debug > 2 ) Serial.print (" °C [" );
502+ if (debug > 2 ) Serial.print (DS18B20_minValue);
503+ if (debug > 2 ) Serial.print (" ," );
504+ if (debug > 2 ) Serial.print (DS18B20_maxValue);
505+ if (debug > 2 ) Serial.print (" ]; Ergebnis: " );
506+ if (debug > 2 ) Serial.println (res);
507+ return res;
508+ }
474509// Temperatursensoren auslesen
475510void readDS18B20 () {
511+ float t1 = 0.0 ;
512+ float t2 = 0.0 ;
513+ bool res = false ;
476514 if (debug > 2 ) Serial.print (" Anfrage der Temperatursensoren... " );
477515 myDS18B20.requestTemperatures (); // Anfrage zum Auslesen der Temperaturen
478516 if (debug > 2 ) Serial.println (" fertig" );
@@ -486,8 +524,41 @@ void readDS18B20() {
486524 Adresse += String (myDS18B20Address[j], HEX);
487525 if (j < 7 ) Adresse += " , " ;
488526 }
489- if (i == 0 ) temp1 = myDS18B20.getTempCByIndex (i);
490- if (i == 1 ) temp2 = myDS18B20.getTempCByIndex (i);
527+ if (i == 0 ) t1 = myDS18B20.getTempCByIndex (i);
528+ if (i == 1 ) t2 = myDS18B20.getTempCByIndex (i);
529+ }
530+ // Plausibilitätscheck
531+ if (checkDS18B20Value (t1)) {
532+ temp1 = t1;
533+ res = true ;
534+ }
535+ else {
536+ ++tempTSensorFail;
537+ res = false ;
538+ mqttTopic = MQTT_SERIAL_PUBLISH_STATE;
539+ mqttTopic += " lastError" ;
540+ mqttPayload = " Temperatursensor T1 außerhalb des Messbereichts: " + String (t1) + " [C]; Wiederholung: " + String (tempTSensorFail);
541+ mqttClient.publish (mqttTopic.c_str (), mqttPayload.c_str ());
542+ if (debug > 2 ) Serial.print (" LastError: " );
543+ if (debug > 2 ) Serial.println (mqttPayload); // (debug > 2)
544+ }
545+ if (checkDS18B20Value (t2)) {
546+ temp2 = t2;
547+ if (res) tempTSensorFail = 0 ; // t1 und t2 sind korrekt => Fehlercounter auf 0 gesetzt
548+ }
549+ else {
550+ ++tempTSensorFail;
551+ res = false ;
552+ mqttTopic = MQTT_SERIAL_PUBLISH_STATE;
553+ mqttTopic += " lastError" ;
554+ mqttPayload = " Temperatursensor T2 außerhalb des Messbereichts: " + String (t2) + " [C]; Wiederholung: " + String (tempTSensorFail);
555+ mqttClient.publish (mqttTopic.c_str (), mqttPayload.c_str ());
556+ if (debug > 2 ) Serial.print (" LastError: " );
557+ if (debug > 2 ) Serial.println (mqttPayload);
558+ }
559+ if (tempTSensorFail > maxTSensorFail) {
560+ Serial.println (" zu viele Fehler (out of range) beim Auslesen der DS18B20! Reboot!!" );
561+ ESP.restart ();
491562 }
492563}
493564// Thermale Limits prüfen und ggf. reagieren
@@ -504,6 +575,7 @@ void termalLimits () {
504575 if (debug) Serial.println (" °C am Top-Sensor #2)" );
505576 // Temperatursensoren liefern unplausible Werte gegeneinander -> Defekt!
506577 hardwareError = 1 ;
578+ lastError = " Zwangsabschaltung: unterschiedliche Sensorwerte (" + String (temp1) + " ; " + String (temp2) + " )" ;
507579 panicStop ();
508580 }
509581 }
@@ -518,6 +590,7 @@ void termalLimits () {
518590 if (debug) Serial.print (" [" );
519591 // Thermosensor 1 ist außerhalb des eingestellten Normbereichs -> Annahme Defekt!
520592 hardwareError = 1 ;
593+ lastError = " Zwangsabschaltung: Verletzung der thermischen Grenzen " + String (temp1) + " -> [" + String (minTemp) + " ... " + String (maxTemp) + " ]" ;
521594 panicStop ();
522595 }
523596 }
@@ -532,6 +605,7 @@ void termalLimits () {
532605 if (debug) Serial.print (" [" );
533606 // Thermosensor 2 ist außerhalb des eingestellten Normbereichs -> Annahme Defekt!
534607 hardwareError = 1 ;
608+ lastError = " Zwangsabschaltung: Verletzung der thermischen Grenzen " + String (temp2) + " -> [" + String (minTemp) + " ... " + String (maxTemp) + " ]" ;
535609 panicStop ();
536610 }
537611 }
@@ -544,6 +618,7 @@ void termalLimits () {
544618 if (debug) Serial.print (temp2);
545619 if (debug) Serial.println (" °C am Top-Sensor #2." );
546620 // thermalstop = 1 -> 12V wird abgeschalten, damit die Relais keine Versorgung mehr haben können.
621+ lastError = " Thermal Stop: 12V abgeschaltet (" + String (temp1) + " ; " + String (temp2) + " )" ;
547622 thermalStop ();
548623 }
549624 }
@@ -556,6 +631,7 @@ void termalLimits () {
556631 if (debug) Serial.println (" °C am Top-Sensor #2." );
557632 // thermalstop = 1 -> 12V wird abgeschalten, damit die Relais keine Versorgung mehr haben können.
558633 // panicMode = 1 -> 5V des ESP32 zur Steuerung des Heizstabs wird abgeschalten - damit alle Spannungsversorgungen
634+ lastError = " Thermal Stop: 5V und 12V abgeschaltet (" + String (temp1) + " ; " + String (temp2) + " )" ;
559635 panicStop ();
560636 }
561637 }
@@ -567,6 +643,7 @@ void termalLimits () {
567643 if (debug) Serial.print (" °C am Top-Sensor #1 bzw. " );
568644 if (debug) Serial.print (temp2);
569645 if (debug) Serial.println (" °C am Top-Sensor #2." );
646+ lastError = " zurück im Normalbereich der Temperatur: reset der Heizstabelektornik" ;
570647 Heizstab_reboot ();
571648 }
572649 }
@@ -579,6 +656,7 @@ void termalLimits () {
579656 if (debug) Serial.print (" °C am Top-Sensor #1 bzw. " );
580657 if (debug) Serial.print (temp2);
581658 if (debug) Serial.println (" °C am Top-Sensor #2." );
659+ lastError = " zurück im Normalbereich der Temperatur: reset der Heizstabelektornik" ;
582660 Heizstab_reboot ();
583661 }
584662 }
@@ -667,6 +745,9 @@ static void getTempFromSensor (void *args){
667745 // ticktime initialisieren
668746 ticktime = xTaskGetTickCount ();
669747
748+ er = esp_task_wdt_add (NULL ); // Task zur Überwachung hinzugefügt
749+ assert (er == ESP_OK);
750+
670751 for (;;){ // Dauerschleife des Tasks
671752 // Watchdog zurücksetzen
672753 esp_task_wdt_reset ();
@@ -719,8 +800,7 @@ void setup() {
719800 WiFi.begin (ssid,password);
720801 while (WiFi.status () != WL_CONNECTED)
721802 {
722- ++i;
723- if (i > 240 ) {
803+ if (++i > 240 ) {
724804 // Reboot nach 2min der Fehlversuche
725805 Serial.println (" WLAN scheint nicht mehr erreichbar! Reboot!!" );
726806 ESP.restart ();
@@ -777,7 +857,12 @@ void setup() {
777857 int app_cpu = xPortGetCoreID ();
778858 BaseType_t rc;
779859 esp_err_t er;
780- er = esp_task_wdt_init (300 ,true ); // restart nach 5min = 300s Inaktivität einer der 4 überwachten Tasks
860+ esp_task_wdt_config_t wdt_config = {
861+ .timeout_ms = 300000 , // 5 Minuten = 300000 ms
862+ .idle_core_mask = (1 << 1 ), // Nur Kerne 1 überwachen
863+ .trigger_panic = true
864+ };
865+ er = esp_task_wdt_reconfigure (&wdt_config); // restart nach 5min = 300s Inaktivität einer der 4 überwachten Tasks
781866 assert (er == ESP_OK);
782867 rc = xTaskCreatePinnedToCore (
783868 getTempFromSensor, // Taskroutine
@@ -788,12 +873,6 @@ void setup() {
788873 &htempSensor, // handler
789874 app_cpu); // CPU_ID
790875 assert (rc=pdPASS);
791- er = esp_task_wdt_status (htempSensor); // Check, ob der Task schon überwacht wird
792- assert (er == ESP_ERR_NOT_FOUND);
793- if (er == ESP_ERR_NOT_FOUND) {
794- er = esp_task_wdt_add (htempSensor); // Task zur Überwachung hinzugefügt
795- assert (er == ESP_OK);
796- }
797876 Serial.println (" TempSensor-Task gestartet." );
798877 rc = xTaskCreatePinnedToCore (
799878 MQTTwatchdog, // Taskroutine
@@ -804,12 +883,6 @@ void setup() {
804883 &hMQTTwatchdog, // handler
805884 app_cpu); // CPU_ID
806885 assert (rc=pdPASS);
807- er = esp_task_wdt_status (hMQTTwatchdog); // Check, ob der Task schon überwacht wird
808- assert (er == ESP_ERR_NOT_FOUND);
809- if (er == ESP_ERR_NOT_FOUND) {
810- er = esp_task_wdt_add (hMQTTwatchdog); // Task zur Überwachung hinzugefügt
811- assert (er == ESP_OK);
812- }
813886 Serial.println (" MQTT-Watchdog-Task gestartet." );
814887 rc = xTaskCreatePinnedToCore (
815888 MQTTstate, // Taskroutine
0 commit comments