Aktionen

Kühlschranktüren überwachen mit ESP8266 Wemos D1 Mini

Aus znilwiki

Version vom 17. März 2019, 19:13 Uhr von BLinz (Diskussion | Beiträge) (Die Seite wurde neu angelegt: „==Vorwort== Unser Kühlschrank hat eine obere Tür für den Kühlschrankteil und eine untere Tür für den Gefrierschrankteil.<br> Die obere Tür löst einen P…“)
(Unterschied) ← Nächstältere Version | Aktuelle Version (Unterschied) | Nächstjüngere Version → (Unterschied)

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

Kuehlschrank Ueberwachung Schaltplan V3.png


Steckplatine

Kuehlschrank Ueberwachung Steckplatine V3.png


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&uuml;r: ";
  if ( bool_RGB1_Red_isOn == true ) {
    page += "offen";
  } else {
    page += "geschlossen";
  }
  page += "</h1><hr>";
  page += "<hr><h2>Untere T&uuml;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() );
}

Kommentare

Loading comments...