Kühlschranktüren überwachen mit ESP8266 Wemos D1 Mini
Aus znilwiki
Vorwort
Unser Kühlschrank hat eine obere Tür für den Kühlschrankteil und eine untere Tür für den Gefrierschrankteil.
Die obere Tür löst einen Pieper aus wenn diese länger als 2 Minuten geöffnet ist.
Bei der Gefrierschranktür unten gibt es so etwas leider nicht. Es kommt wie es kommen musste - so ein bis zwei mal im Jahr wird die nicht richtig geschlossen. Die Folge ist das der Teil völlig vereist, man die Schubladen nicht mehr aufbekommt usw.
Da ich vor kurzen den Gefrierschrankteil deswegen abgetaut habe kam mir die Idee eine Überwachung zu bauen.
Eigentlich wollte ich auch noch ein OLED-Minidisplay mit einbauen welchen die Temperatur anzeigt - aber ich hatte einfach nicht genug GPIO-Pins mehr.
Features
- LED-Anzeige für obere und unterer Tür per RGB LED
- Grün = Tür geschlossen
- Rot = Tür offen
- Grüne LED erlischt nach ca. 10 Sekunden
- aktiver Buzzer
- ertönt wenn die untere Tür länger als 1 Minute geöffnet ist
- DHT22 Umweltsensor
- Misst die Temperatur und Luftfeuchtigkeit
- Resetschalter
- Stromversorgung per Micro-USB Kabel
- Zustand der Türen sowie Temperatur und Luftfeuchtigkeit sind per Webbrowser abrufbar
- Tür auf / zu sowie Temperatur und Luftfeuchtigkeit werden zusätzlich an Zabbix-Server gesendet
Bauteile
1x Wemos D1 Mini 2x RGB-LED 5mm mit gemeinsamer Anode 1x DHT22 Umweltsensor 4x Widerstand 100 Ω 3x Widerstand 10 kΩ 2x Magnetschalter - Normalzustand geschlossen 1x aktiver Buzzer 1x Taster
Schaltplan
Steckplatine
Sketch
Beim Start werden die LED zunächst auf Gelb geschaltet.
Sobald das WLAN verbunden ist piepst der Buzzer einmal.
Klappt das mit dem WLAN nicht so dauert es etwas länger (15 Sekunden) und er piepst 3 mal, macht dann aber weiter.
Dann läuft er in die Endlosschleife und die LED sollten sich in grün oder rot ändern.
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <ESP8266HTTPClient.h>
#include "DHT.h" // für DHT22 Sensor
#define DEBUG
// Zugangsdaten zum WLAN:
const char* ssid = "***************************";
const char* password = "*********************************";
//Damit der ESP nicht unnötig Zeit mit der DHCP-Aushandlung verbringt vergeben wir
//eine statische IP-Adresse.
IPAddress staticIP(192, 168, 1, 185);
IPAddress gateway(192, 168, 1, 200);
IPAddress subnet(255, 255, 255, 0);
IPAddress dns(192, 168, 1, 81);
// Maximalwartezeit auf das WLAN, sonst weitermachen:
int int_WLANmaxwaittime = 15000;
int int_WLANCounter = 0;
//Unter folgenden Namen meldet sich der ESP8266 im Netzwerk
const char* deviceName = "ESP8266-Cooler-185";
// Webserver vorbereiten
ESP8266WebServer WebServer ( 80 );
//HTTP-Client vorbereiten
HTTPClient http;
int httpCode = 0;
// Die möglichen Pin-Nummern.
// D1 = 5 D2 = 4 D3 = 0 D4 = 2
// TX = 1 RX = 3 D0 = 16 D5 = 14
// D6 = 12 D7 = 13 D8 = 15
// Passiver Piezo Buzzer
int int_BuzzerPin = 0; // D3
bool bool_BuzzerPassiv = false; // Aktiver oder passiver Buzzer?
int int_BuzzerFrequency = 128; // Startfrequenz des Tones
int int_BuzzerAddFrequency = 64;
float long_BuzzerDelay = 60000; // Millisekunden Verzögerung bevor der Buzzer angeht
bool bool_Buzzer_isOn = false;
// RGB-LEDs (gemeinsame Anode: https://www.amazon.de/gp/product/B071K9CV19)
// erste RGB-LED - obere Tür, Blau ist dauerhaft auf 3V3
int int_RGB1_RED = 16; // Rot = D0
int int_RGB1_GREEN = 14; // Grün = D5
// zweite RGB-LED - untere Tür, Blau ist dauerhaft auf 3V3
int int_RGB2_RED = 4; // Rot = D2
int int_RGB2_GREEN = 2; // Grün = D4
// Reed-Kontakte (es sollten schwarze sein) https://www.ebay.de/itm/PS-3150-Türschalter-Magnetschalter-Fenster-Reed-Switch-Türkontakt-P-3150-m-Kabel/123267796554
// Reed-Kontakt obere Tür
int int_PinREED1 = 12; // D6
int int_StateREED1 = 0;
int int_LastStateREED1 = 99; // letzten Zustand merken zum vergleichen, 99 damit er auch mindestens einmal nach dem booten durchläuft
// Reed-Kontakt untere Tür
int int_PinREED2 = 13; // D7
int int_StateREED2 = 0; // Normalzustand geschlossen = True, False = offen
int int_LastStateREED2 = 99; // letzten Zustand merken zum vergleichen, 99 damit er auch mindestens einmal nach dem booten durchläuft
// Timer: die grüne LED soll nach 10 Sekunden wieder ausgehen damit es nicht ständig leuchtet
unsigned long long_startMillisRGB1;
unsigned long long_startMillisRGB2;
unsigned long long_TurnOffLEDAfter = 10000; // nach 10 Sekunden ausschalten
unsigned long long_CurrentMillis;
bool bool_RGB1_Green_isOn = false;
bool bool_RGB2_Green_isOn = false;
bool bool_RGB1_Red_isOn = false;
bool bool_RGB2_Red_isOn = false;
// DHT22 Sensor für Temperatur und Luftfeuchtigkeit
#define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321
uint8_t DHT22Pin = D1; // PIN mit dem "Data" des DHT22 verbunden ist
DHT h_dht22(DHT22Pin, DHTTYPE);
float float_Temperature;
float float_Humidity;
unsigned long long_startMillisDHT22;
unsigned long long_SendValueIntervall = 60000; // wie oft sollen die Umweltdaten gesendet werden
// Zabbix-Server oder Proxy
String my_zabbixserver = "192.168.1.2";
String my_hostname = "ESP8266-Cooler-185";
// ####################################################################################################################
// _
// | |
// ___ ___| |_ _ _ _ __
// / __|/ _ \ __| | | | '_ \
// \__ \ __/ |_| |_| | |_) |
// |___/\___|\__|\__,_| .__/
// | |
// |_|
// ####################################################################################################################
void setup() {
// ####################################################################################################################
// Serielle Debugging-Ausgabe
#ifdef DEBUG
Serial.setTimeout(2000);
Serial.begin(115200);
delay(1000);
Serial.println(); // Einmal neue Zeile, nach einem reset steht da gerne mal Müll
Serial.println("Setup-Boot-Sequence");
Serial.println("-------------------");
#endif
// ####################################################################################################################
// LEDs initialisieren und auf blau setzen
#ifdef DEBUG
Serial.print("RGB-LED 1 ........ ");
#endif
pinMode(int_RGB1_RED, OUTPUT);
pinMode(int_RGB1_GREEN, OUTPUT);
// pinMode(int_RGB1_BLUE, OUTPUT);
// Auf Gelb schalten wegen Boot
digitalWrite(int_RGB1_RED, LOW); // LOW = an , HIGH = aus
digitalWrite(int_RGB1_GREEN, LOW);
// digitalWrite(int_RGB1_BLUE, LOW);
#ifdef DEBUG
Serial.println("ok");
delay(500); // Zu Testzwecken und mitlesen ###########################################################################
#endif
#ifdef DEBUG
Serial.print("RGB-LED 2 ........ ");
#endif
pinMode(int_RGB2_RED, OUTPUT);
pinMode(int_RGB2_GREEN, OUTPUT);
// pinMode(int_RGB2_BLUE, OUTPUT);
// Auf Gelb schalten wegen Boot
digitalWrite(int_RGB2_RED, LOW); // LOW = an , HIGH = aus
digitalWrite(int_RGB2_GREEN, LOW);
// digitalWrite(int_RGB2_BLUE, LOW);
#ifdef DEBUG
Serial.println("ok");
delay(500); // Zu Testzwecken und mitlesen ###########################################################################
#endif
// ####################################################################################################################
// Reed-Schalter einrichten
#ifdef DEBUG
Serial.print("Reed-Kontakt 1 ... ");
#endif
pinMode(int_PinREED1, INPUT);
#ifdef DEBUG
Serial.println("ok");
Serial.print("Reed-Kontakt 2 ... ");
#endif
pinMode(int_PinREED2, INPUT);
#ifdef DEBUG
Serial.println("ok");
delay(500); // Zu Testzwecken und mitlesen ###########################################################################
#endif
// ####################################################################################################################
// DHT22 Sensor einrichten
#ifdef DEBUG
Serial.print("DHT22 Sensor ... ");
#endif
pinMode(DHT22Pin, INPUT);
h_dht22.begin();
long_startMillisDHT22 = millis();
#ifdef DEBUG
Serial.println("ok");
delay(500); // Zu Testzwecken und mitlesen ###########################################################################
#endif
// ####################################################################################################################
// WLAN initialisieren
// 123456789012345678
#ifdef DEBUG
Serial.print("WiFi ............ ");
#endif
WiFi.hostname(deviceName);
WiFi.config(staticIP, dns, gateway, subnet);
WiFi.begin(ssid, password);
//WiFi.mode(WIFI_STA);
//Auf das WLAN warten
while (WiFi.status() != WL_CONNECTED) {
int_WLANCounter = int_WLANCounter + 50;
if (int_WLANCounter > int_WLANmaxwaittime) {
break;
}
delay(50);
}
#ifdef DEBUG
Serial.print("ok (");
Serial.print(WiFi.localIP());
Serial.println(")");
delay(500); // Zu Testzwecken und mitlesen ###########################################################################
#endif
// ####################################################################################################################
// Webserver starten
// 123456789012345678
#ifdef DEBUG
Serial.print("Webserver ....... ");
#endif
WebServer.on ( "/", handleRoot ); // Wenn die URL aufgerufen wird (ohne etwas hinter dem /) wird die Funktion "handleRoot" gestartet
WebServer.begin();
#ifdef DEBUG
Serial.println ( "ok (Port 80)" );
delay(500); // Zu Testzwecken und mitlesen ###########################################################################
#endif
// ####################################################################################################################
#ifdef DEBUG
Serial.print("Buzzer .......... ");
#endif
pinMode(int_BuzzerPin, OUTPUT);
#ifdef DEBUG
Serial.println("ok");
#endif
if ( bool_BuzzerPassiv == true ) {
tone(int_BuzzerPin, 4000, 500);
if (WiFi.status() != WL_CONNECTED) {
delay(250);
tone(int_BuzzerPin, 4000, 500);
delay(250);
tone(int_BuzzerPin, 4000, 500);
}
} else {
// Einmal piepen als Meldung das der Setupvorgang abgeschlossen ist
digitalWrite(int_BuzzerPin, HIGH);
delay(250);
digitalWrite(int_BuzzerPin, LOW);
if (WiFi.status() != WL_CONNECTED) {
// 3x Piepen wenn es mit dem WLAN nicht geklappt hat. Einmal haben wir schon, fehlen noch zweimal
delay(250);
digitalWrite(int_BuzzerPin, HIGH);
delay(250);
digitalWrite(int_BuzzerPin, LOW);
delay(250);
digitalWrite(int_BuzzerPin, HIGH);
delay(250);
digitalWrite(int_BuzzerPin, LOW);
}
}
// ####################################################################################################################
#ifdef DEBUG
Serial.println("------------------------------------------");
Serial.println("Setup abgeschlossen");
Serial.println("------------------------------------------");
Serial.println();
#endif
}
// ####################################################################################################################
// _
// | |
// | | ___ ___ _ __
// | |/ _ \ / _ \| '_ \
// | | (_) | (_) | |_) |
// |_|\___/ \___/| .__/
// | |
// |_|
// ####################################################################################################################
void loop() {
// Sich um den Webserver kümmern:
WebServer.handleClient();
// Sich um die Magnetschalter kümmern:
int_StateREED1 = digitalRead(int_PinREED1);
int_StateREED2 = digitalRead(int_PinREED2);
// nur wenn sich etwas ändert ....
if (int_StateREED1 != int_LastStateREED1) {
//Serial.println("REED1 ungleich");
long_startMillisRGB1 = millis();
int_LastStateREED1 = int_StateREED1;
if (int_StateREED1 == LOW) {
// LED1 auf Grün
#ifdef DEBUG
Serial.println("Obere Tür geschlossen");
#endif
digitalWrite(int_RGB1_RED, HIGH);
digitalWrite(int_RGB1_GREEN, LOW);
// digitalWrite(int_RGB1_BLUE, HIGH);
// Grüne LED ist an + Timer setzen
bool_RGB1_Green_isOn = true;
bool_RGB1_Red_isOn = false;
// Buzzer ausschalten
if (bool_BuzzerPassiv == true) {
noTone(int_BuzzerPin);
} else {
digitalWrite(int_BuzzerPin, LOW);
}
bool_Buzzer_isOn = false;
// An Zabbix Senden
ZabbixSender("esp8266.cooler.door.upper", "1"); // 0 = Offen, 1 = Geschlossen
} else {
// LED1 auf Rot
#ifdef DEBUG
Serial.println("Obere Tür offen!");
#endif
digitalWrite(int_RGB1_RED, LOW);
digitalWrite(int_RGB1_GREEN, HIGH);
// digitalWrite(int_RGB1_BLUE, HIGH);
bool_RGB1_Green_isOn = false;
bool_RGB1_Red_isOn = true;
ZabbixSender("esp8266.cooler.door.upper", "0");
}
}
if (int_StateREED2 != int_LastStateREED2) {
//Serial.println("REED2 ungleich");
long_startMillisRGB2 = millis();
int_LastStateREED2 = int_StateREED2;
if (int_StateREED2 == LOW) {
// LED2 auf Grün
#ifdef DEBUG
Serial.println("Untere Tür geschlossen");
#endif
digitalWrite(int_RGB2_RED, HIGH);
digitalWrite(int_RGB2_GREEN, LOW);
// digitalWrite(int_RGB2_BLUE, HIGH);
// Grüne LED ist an + Timer setzen
bool_RGB2_Green_isOn = true;
bool_RGB2_Red_isOn = false;
// Buzzer ausschalten
if (bool_BuzzerPassiv == true) {
noTone(int_BuzzerPin);
} else {
digitalWrite(int_BuzzerPin, LOW);
}
bool_Buzzer_isOn = false;
// An Zabbix Senden
ZabbixSender("esp8266.cooler.door.lower", "1"); // 0 = Offen, 1 = Geschlossen
} else {
// LED1 auf Rot
#ifdef DEBUG
Serial.println("Untere Tür offen!");
#endif
digitalWrite(int_RGB2_RED, LOW);
digitalWrite(int_RGB2_GREEN, HIGH);
// digitalWrite(int_RGB2_BLUE, HIGH);
bool_RGB2_Green_isOn = false;
bool_RGB2_Red_isOn = true;
ZabbixSender("esp8266.cooler.door.lower", "0"); // 0 = Offen, 1 = Geschlossen
}
}
//WebServer.send ( 200, "text/html", getPage() );
// ############################################################################
// Testen ob die LED Grün leuchtet, wenn ja nach 10 Sekunden wieder ausschalten
if (bool_RGB1_Green_isOn == true) {
long_CurrentMillis = millis() - long_startMillisRGB1;
if (long_CurrentMillis > long_TurnOffLEDAfter) {
bool_RGB1_Green_isOn = false;
digitalWrite(int_RGB1_GREEN, HIGH);
}
}
if (bool_RGB2_Green_isOn == true) {
long_CurrentMillis = millis() - long_startMillisRGB2;
if (long_CurrentMillis > long_TurnOffLEDAfter) {
bool_RGB2_Green_isOn = false;
digitalWrite(int_RGB2_GREEN, HIGH);
}
}
// ############################################################################
// Wenn Rot länger als long_BuzzerDelay leuchtet den Buzzer aktivieren
// Nur für den 2. Kontakt / untere Tür! Tür oben hat eingebauten Summer
if ((bool_RGB2_Red_isOn == true) && (bool_Buzzer_isOn == false)) {
long_CurrentMillis = millis() - long_startMillisRGB2;
if (long_CurrentMillis > long_BuzzerDelay) {
if (bool_BuzzerPassiv == true) {
tone(int_BuzzerPin, int_BuzzerFrequency);
} else {
digitalWrite(int_BuzzerPin, HIGH);
}
bool_Buzzer_isOn = true;
}
}
// ############################################################################
// Wenn der Buzzer an ist regelmäßig die Frequenz ändern (nur wenn er Typ Passiv ist)
if ((bool_Buzzer_isOn == true) && (bool_BuzzerPassiv == true)) {
int_BuzzerFrequency = int_BuzzerFrequency + 128;
tone(int_BuzzerPin, int_BuzzerFrequency);
if (int_BuzzerFrequency > 5000) {
int_BuzzerFrequency = 128;
}
}
// ############################################################################
// Temperatur abfragen
long_CurrentMillis = millis() - long_startMillisDHT22;
if (long_CurrentMillis > long_SendValueIntervall) {
float_Temperature = h_dht22.readTemperature(); // Gets the values of the temperature
float_Humidity = h_dht22.readHumidity(); // Gets the values of the humidity
#ifdef DEBUG
Serial.print("Temperatur: ");
Serial.print(float_Temperature);
Serial.println("°C");
Serial.print("Luftfeuchtigkeit: ");
Serial.print(float_Humidity);
Serial.println("%");
#endif
long_startMillisDHT22 = millis();
ZabbixSender("esp8266.DHT22.Temperature", String(float_Temperature));
ZabbixSender("esp8266.DHT22.Humidity", String(float_Humidity));
}
}
// ############################################################################
// Sendet die Daten an den Zabbix-Server per URL-Methode: https://znil.net/index.php?title=Zabbix_sender_per_Web_URL-Aufruf_nutzen
void ZabbixSender(String my_item, String my_value) {
http.setTimeout(4000);
http.begin("http://192.168.1.246:5002/" + my_zabbixserver + "/" + my_hostname + "/" + my_item + "/" + my_value);
httpCode = http.GET();
#ifdef DEBUG
Serial.print("ZabbixSender: http://192.168.1.246:5002/" + my_zabbixserver + "/" + my_hostname + "/" + my_item + "/" + my_value + " ==> ");
Serial.println(httpCode);
#endif
http.end();
}
// ############################################################################
// Hier folgt die Webseite als HTML-Code.
String getPage() {
// DHT22 Sensor abfragen
float_Temperature = h_dht22.readTemperature(); // Gets the values of the temperature
float_Humidity = h_dht22.readHumidity(); // Gets the values of the humidity
String page = "<html lang=de-DE><head>";
//page += "<meta http-equiv='refresh' content='5'/>";
page += "<title>ESP8266-Cooler-185</title>";
page += "<style> body { background-color: #fffff; font-family: Arial, Helvetica, Sans-Serif; Color: #000000; }";
page += ".button {display: inline-block; padding: 15px 15px; font-size: 25px; cursor: pointer; text-align: center; text-decoration: none;";
page += "outline: none; color: #ffffff; background-color: #4db2ec; border: none; border-radius: 5px;}";
page += ".button:hover {background-color: #4DCAEC; color:#ffffff;}";
page += ".button:active {background-color: #4DCAEC; box-shadow: 0 3px #666; transform: translateY(3px); }</style>";
page += "</head><body><center><h1>ESP8266-Cooler-185 - WebServer</h1>";
page += "<hr><h2>Obere Tür: ";
if ( bool_RGB1_Red_isOn == true ) {
page += "offen";
} else {
page += "geschlossen";
}
page += "</h1><hr>";
page += "<hr><h2>Untere Tür: ";
if ( bool_RGB2_Red_isOn == true ) {
page += "offen";
} else {
page += "geschlossen";
}
page += "</h1><hr>";
page += "<hr><h1>Temperatur: ";
page += (int)float_Temperature;
page += " Grad</h2><br>";
page += "<h1>Luftfeuchtigkeit: ";
page += (int)float_Humidity;
page += " %</h2><hr>";
page += "</center></body>";
return page;
}
// ############################################################################
// Wird immer aufgerufen wenn jemand die IP nur mit einem / am Ende aufruft
void handleRoot() {
// Einfach nur die Webseite ausliefern
WebServer.send ( 200, "text/html", getPage() );
}