ESP8266 AM2302 (DHT22) Sensor für Akkubetrieb, ein Projekt zum Mitmachen! (3-1)

So heute beginnt der letzte Teil dieses Projektes, es geht jetzt um die „Produktiv-Software“.

Da die Programme jetzt sehr groß werden wird ein Programm nach dem anderen veröffentlicht und besprochen werden.

Doch zuerst einmal ein Bild wie die Ausgabe so eines Programmes dann im Browser aussehen kann.

Sensorwerte_im_Browser_mit_Favicon-226x300 ESP8266 AM2302 (DHT22) Sensor für Akkubetrieb, ein Projekt zum Mitmachen! (3-1)

Über folgendes Menü kann man zu den einzelnen Punkten dieses Teils der Anleitung springen.

Download der Software als ZIP-Archiv

Quellen der benutzen Libraries

Programm 1 (Webbrowser, Thingspeak und EEPROM)
Erklärung von Programm 1
Erweiterung von Programm 1 inkl. Erklärung (zusätzlich mit DNS-Server)
Erweiterung von Programm 1 inkl. Erklärung (zusätzlich mit autom. Update)
Final Version von Programm 1 (Die fertige Version inkl. Änderungen einiger Einstellungen online)

In Teil 3-2 wird folgendes veröffentlicht 🙂

Programm 2 (zusätzlich Deep-Sleep)
Erklärung von Programm 2
Programm 3 (zusätzlich Übertragung an PC-Client o. externen Server)
Erklärung von Programm 3

Im Download Archiv sind bereits alle Programme (teilweise Vorabversionen) enthalten, wer also schon einmal spicken will… 🙂


Den Anfang macht ein Programm wo der Sensor zum einen seine Daten an einen ThingSpeak Channel sendet und gleichzeitig eine Abfrage per Webbrowser möglich ist.

Die Konfiguration des Sensors erfolgt bei der Erst-Inbetriebnahme über den Webbrowser und alle Einstellungen werden im EEPROM gespeichert.

Und hier nun der Programmcode dazu.

/* EEPROM Aufteilung für Konfigurationsdaten
Position     Länge    Wert
0            1        Firststart Flag
1            1        Updateintervall
2            1        Connectiontimeout
3            1        Flag für zu viele Connection Timeouts -> SETUP Modus wird aktiviert bei 3 aufeinanderfolgenden Timeouts
4            1        IP Typ 0=DHCP, 1=Statisch
5            4        IP-Adresse
9            4        Gateway IP-Adresse
13           4        Subnet Mask
17           4        DNS-Server IP-Adresse
21-52        32       WLAN SSID
53-116       64       WLAN PWD
117-148      32       SENSORSSID
149-212      64       SENSORPWD
213-237      25       Standort
238          1        Thingspeak Übertragung 0=Deaktiviert, 1=Aktiviert
239-255      16       Thingspeak API-Key
*/

#include <ESP8266WiFi.h>
#include <EEPROM.h>
#include <DHT.h>

#define RESETPIN 2             
#define DHTPIN 4             
#define LEDPIN 5             
#define DHTPOWERPIN 14
#define DHTTYPE DHT22        

ADC_MODE(ADC_VCC);                                  //Der ADC wird so konfiguriert das er die Systemspannung misst, es darf nichts am ADC (TOUT) Pin angechlossen sein!

const String SOFTWAREVERSION="1.050216.u";

//Variablen werden mit EEPROM Konfiguration überschrieben wenn FirstStartFlag im EEPROM = 111 (bedeutet Sensor ist konfiguriert) ist!
byte FIRSTSTARTFLAG=0;                              // Flag zur Erkennung ob System im Setup Modus starten muss weil es keine Konfiguration im EEPROM hat
byte UPDATEINTERVAL=15;                             // Aktualisierungsinterval für den Thingspeak Channel in Minuten (Mindestens 15 lt. Thingspeak gewünscht 😉 )
byte CONNECTIONTIMEOUT=60;                          // Verbindungstimeout für die Verbindung mit unserem WLAN (Sekunden)
byte STATICIP=0;                                    // Art der IP-Adresszuteilung 0=IP per DHCP, 1=Statische IP
byte THINGSPEAKAKTIV=0;                             // Thingspeakübertragung 0=Deaktiviert, 1=Aktiviert (Standard 0)
String THINGSPEAKAPIKEY="";                         // Write Key des Thingspeak Channels
String WLANSSID="";                                 //Die SSID eures WLAN kommt hier rein
String WLANPWD="";                                  //Das WLAN Passwort eures WLAN kommt hier rein
String SENSORSSID="ESP8266-DHT22-SENSOR";           //Die Standard SSID für unser Sensor WLAN
String SENSORPWD="";                                //Das Passwort für unser Sensor WLAN
String SENSORSTANDORT="";                           //Standort des Sensors (Max 25 Zeichen)
IPAddress ip(0,0,0,0);                              //Sensor Server IP-Adresse bei statischer Konfiguration
IPAddress gw(0,0,0,0);                              //Gateway IP-Adresse bei statischer Konfiguration
IPAddress sub(255,255,255,0);                       //Subnet Mask bei statischer Konfiguration
IPAddress dns(0,0,0,0);                             //DNS Server IP-Adresse bei statischer Konfiguration

//Konstanten definieren, diese Werte können nur im Programm angepasst werden
const char* THINGSPEAKHOST = "api.thingspeak.com";  //Thingspeak API Host (NICHT ÄNDERN)
const int SHUTDOWNVCC=3300;                         //Systemabschaltschwelle in Volt ohne Dezimalpunkt 4 Stellen (z.B. 3,3 V = 3300)
const int MAXSENSORERRORCOUNT=5;                    //Maximale Anzahl Versuche vom Sensor zu lesen bevor das System resettet wird
const int MAXCONNECTIONTRIES=5;                     //Maximale Anzahl an WLAN Verbindungsversuchen bevor wieder in den Setup Modus gebootet wird

//Sonstige benötigte Variablen definieren 
String HTMLFORMULARWLAN;                            //Hilfsvariable für das Formular zur Auswahl des WLAN
float AKTUELLETEMPERATUR;                           //Variable für die aktuelle Temperatur
float AKTUELLELUFTFEUCHTE;                          //Variable für die aktuelle Luftfeuchte
float KORREKTURTEMPERATUR;                          //Korrekturwert für die Temperatur
float KORREKTURLUFTFEUCHTE;                         //Korrekturwert für die Luftfeuchte
byte TIMEOUTFLAG=0;                                 //Hilfsvariable zum zählen der Verbindungstimeouts
unsigned long STARTZEITPUNKTMESSUNG=0;              //Variable zum festhalten der STARTZEIT aus millis() für die Berechnung wann die nächste Messung fällig ist
unsigned long STARTZEITPUNKTTS=0;                   //Variable zum festhalten der STARTZEIT aus millis() für die Berechnung wann die nächste Übertragung fällig ist
unsigned long THINGSPEAKUPDATEINTERVAL=0;           //Variable für das berechnete Übertragungsintervall der Thingspeak Channel Datenübertragung
int step=0;                                         //Variable für den Setup-Wizzard

DHT dht(DHTPIN, DHTTYPE);

WiFiServer server(80);

void GetSensorData() {
  digitalWrite(LEDPIN, 1);
  delay(50);
  digitalWrite(LEDPIN, 0);

  int SENSORERRORCOUNT=0;

  AKTUELLELUFTFEUCHTE = dht.readHumidity();
  AKTUELLETEMPERATUR = dht.readTemperature();

  while (isnan(AKTUELLELUFTFEUCHTE) || isnan(AKTUELLETEMPERATUR)) {
    SENSORERRORCOUNT+=1;
    
    digitalWrite(LEDPIN, 1);
    delay(50);
    digitalWrite(LEDPIN, 0);
    
    delay(2450);
    
    AKTUELLELUFTFEUCHTE = dht.readHumidity();
    AKTUELLETEMPERATUR = dht.readTemperature();

    if (SENSORERRORCOUNT >= MAXSENSORERRORCOUNT) {
      Serial.println(F("Zuviele Sensorfehler in Folge, starte Sensor neu..."));
      Serial.println(F(""));
      
      WiFi.disconnect();

      delay (100);
      
      ESP.deepSleep(1, WAKE_RF_DEFAULT);
      delay(100);
    }
  }
  
  AKTUELLELUFTFEUCHTE+=KORREKTURLUFTFEUCHTE;
  AKTUELLETEMPERATUR+=KORREKTURTEMPERATUR;
}

void ShowSensorData() {
  Serial.print(F("Luftfeuchte: "));
  Serial.print(AKTUELLELUFTFEUCHTE);
  Serial.println(F(" %"));
  Serial.print(F("Temperatur: "));
  Serial.print(AKTUELLETEMPERATUR);
  Serial.println(F(" *C"));
  Serial.println(F(""));
}

String macToStr(const uint8_t* mac)
{
  String result;

  for (int i = 0; i < 6; ++i) {
    if(String(mac[i],16).length()==1){
      result += "0";
    }
    
    result += String(mac[i], 16);
 
    if (i < 5)
      result += ':';
  }

  result.toUpperCase();
  
  return result;
}

void ReadEEPROMConfig() {
  EEPROM.begin(512);

  EEPROM.get(0,FIRSTSTARTFLAG);
  
  Serial.print(F("FIRSTSTARTFLAG="));
  Serial.println(FIRSTSTARTFLAG);
  
  EEPROM.get(1,UPDATEINTERVAL);

  Serial.print(F("UPDATEINTERVAL="));
  Serial.println(UPDATEINTERVAL);

  EEPROM.get(2,CONNECTIONTIMEOUT);

  Serial.print(F("CONNECTIONTIMEOUT="));
  Serial.println(CONNECTIONTIMEOUT);

  EEPROM.get(3,TIMEOUTFLAG);

  Serial.print(F("TIMEOUTFLAG="));
  Serial.println(TIMEOUTFLAG);

  EEPROM.get(4,STATICIP);

  Serial.print(F("STATICIP="));
  Serial.println(STATICIP);

  ip[0]=EEPROM.read(5);
  ip[1]=EEPROM.read(6);
  ip[2]=EEPROM.read(7);
  ip[3]=EEPROM.read(8);
  
  gw[0]=EEPROM.read(9);
  gw[1]=EEPROM.read(10);
  gw[2]=EEPROM.read(11);
  gw[3]=EEPROM.read(12);
  
  sub[0]=EEPROM.read(13);
  sub[1]=EEPROM.read(14);
  sub[2]=EEPROM.read(15);
  sub[3]=EEPROM.read(16);

  dns[0]=EEPROM.read(17);
  dns[1]=EEPROM.read(18);
  dns[2]=EEPROM.read(19);
  dns[3]=EEPROM.read(20);

  Serial.print(F("IP="));
  Serial.println(ip);
  
  Serial.print(F("GATEWAY="));
  Serial.println(gw);
  
  Serial.print(F("SUBNET="));
  Serial.println(sub);
  
  Serial.print(F("DNS="));
  Serial.println(dns);
  
  WLANSSID="";
  
  for (int i = 21; i < 53; ++i)
  {
    WLANSSID += char(EEPROM.read(i));
  }

  Serial.print(F("WLANSSID="));
  Serial.println(WLANSSID.c_str());

  WLANPWD="";
  
  for (int i = 53; i < 117; ++i)
  {
    WLANPWD += char(EEPROM.read(i));
  }
  
  Serial.print(F("WLANPWD="));
  Serial.println(WLANPWD.c_str());

  SENSORSSID="";

  for (int i = 117; i < 149; ++i)
  {
    SENSORSSID += char(EEPROM.read(i));
  }
  
  Serial.print(F("SENSORSSID="));
  Serial.println(SENSORSSID.c_str());

  SENSORPWD="";

  for (int i = 149; i < 213; ++i)
  {
    SENSORPWD += char(EEPROM.read(i));
  }

  Serial.print(F("SENSORPWD="));
  Serial.println(SENSORPWD.c_str());

  SENSORSTANDORT="";

  for (int i = 213; i < 238; ++i)
  {
    SENSORSTANDORT += char(EEPROM.read(i));
  }

  Serial.print(F("SENSORSTANDORT="));
  Serial.println(SENSORSTANDORT.c_str());

  EEPROM.get(238, THINGSPEAKAKTIV);
  
  Serial.print(F("THINGSPEAKAKTIV="));
  Serial.println(THINGSPEAKAKTIV);

  THINGSPEAKAPIKEY="";

  for (int i = 239; i < 256; ++i)
  {
    THINGSPEAKAPIKEY += char(EEPROM.read(i));
  }

  Serial.print(F("THINGSPEAKAPIKEY="));
  Serial.println(THINGSPEAKAPIKEY.c_str());

  EEPROM.end();
}

void SendSensorData() {
  analogWrite(LEDPIN, 100);
  
  GetSensorData();
  
  Serial.print(F("Verbinde mit "));
  Serial.println(THINGSPEAKHOST);

  WiFiClient client;

  delay(2000);
  
  if (!client.connect(THINGSPEAKHOST, 80)) {
    Serial.println(F(""));
    Serial.println(F("Verbindung mit Thingspeak-Server fehlgeschlagen!"));
  } else {
    Serial.println(F("Verbindung mit Thingspeak-Server erfolgreich hergestellt"));
    Serial.println(F("Sende Daten an Thingspeak Channel..."));

    String POSTString ="api_key=";
    POSTString += THINGSPEAKAPIKEY.c_str();
    POSTString += "&field1=";
    POSTString += AKTUELLETEMPERATUR;
    POSTString += "&field2=";
    POSTString += AKTUELLELUFTFEUCHTE;
    POSTString += "&field3=";
    POSTString += String(ESP.getVcc()).substring(0,1);
    POSTString += ".";
    POSTString += String(ESP.getVcc()).substring(1);

    client.print(F("POST /update HTTP/1.1\n")); 
    client.print(F("HOST: "));
    client.print(THINGSPEAKHOST);
    client.print(F("\n"));
    client.print(F("X-THINGSPEAKAPIKEY:"));
    client.print(THINGSPEAKAPIKEY.c_str());
    client.print(F("\n"));
    client.print(F("Connection: close\n")); 
    client.print(F("Content-Type: application/x-www-form-urlencoded\n")); 
    client.print(F("Content-Length: "));
    client.print(POSTString.length()); 
    client.print(F("\n\n"));
    client.print(POSTString);

    delay(100);
    
    client.stop();
    
    Serial.println(F("Verbindung zum Server beendet"));
    Serial.println(F("Daten an Thingspeak Channel gesendet"));
  }  

  analogWrite(LEDPIN, 0);
}

void ShowSysInfo(int typ) {
  if (typ==1) {
    Serial.print(F("SDK-Version: "));
    Serial.println(ESP.getSdkVersion());
    Serial.print(F("ESP8266 Chip-ID: "));
    Serial.println(ESP.getChipId());
    Serial.print(F("ESP8266 Speed: "));  
    Serial.print(ESP.getCpuFreqMHz());
    Serial.println(F(" MHz"));
  }
  
  Serial.print(F("Free Heap Size: "));
  Serial.print(ESP.getFreeHeap());
  Serial.println(F(" Bytes"));
  Serial.print(F("Systemspannung: "));
  Serial.print(String(ESP.getVcc()).substring(0,1));
  Serial.print(F(","));
  Serial.print(String(ESP.getVcc()).substring(1));
  Serial.println(F(" Volt"));  
  Serial.println(F(""));
}

void ResetWiFi() {
  EEPROM.begin(512);
  EEPROM.write(0,0);
  EEPROM.end();

  delay(100);

  WiFi.disconnect();

  delay(100);
  
  ESP.deepSleep(1,WAKE_RF_DEFAULT);
  delay(100);
}

void setup() {
  Serial.begin(115200);

  Serial.println(F(""));  
  Serial.println(F(""));  
  Serial.println(F("Starte den ESP8266-DHT22-SENSOR..."));
  Serial.println(F(""));

  Serial.println(F("Teste Systemspannung..."));
  Serial.println(F(""));

  if (ESP.getVcc() <= SHUTDOWNVCC) {
      Serial.println(F("!!! Systemspannung zu niedrig, schalte Sensor ab !!!"));
      Serial.println(F(""));

      delay(100);
      
      ESP.deepSleep(0,WAKE_RF_DISABLED);
      delay(100);
  }
  
  Serial.print(String(ESP.getVcc()).substring(0,1));
  Serial.print(F(","));
  Serial.print(String(ESP.getVcc()).substring(1));
  Serial.println(F(" Volt ist OK"));
  Serial.println(F(""));

  pinMode(RESETPIN, INPUT_PULLUP);
  pinMode(LEDPIN, OUTPUT);
  pinMode(DHTPOWERPIN, OUTPUT);

  ShowSysInfo(1);

  Serial.println(F("Hole Konfiguration aus EEPROM..."));
  Serial.println(F(""));

  ReadEEPROMConfig();

  float TEMPTEMPERATUR1=0;
  float TEMPLUFTFEUCHTE1=0;
  float TEMPTEMPERATUR2=0;
  float TEMPLUFTFEUCHTE2=0;
  
  if (FIRSTSTARTFLAG==111) {
    digitalWrite(DHTPOWERPIN, 1);
  
    Serial.println(F(""));
    Serial.println(F("Sensorkalibrierung gestartet..."));
    Serial.println(F(""));
  
    for (int i=1; i<=5; i++) {
      delay(2000);
      
      GetSensorData();
      
      ShowSensorData();
  
      TEMPTEMPERATUR1+=AKTUELLETEMPERATUR;
      TEMPLUFTFEUCHTE1+=AKTUELLELUFTFEUCHTE;  
    }
  
    TEMPTEMPERATUR1/=5;
    TEMPLUFTFEUCHTE1/=5;
  
    Serial.print(F("Durchschnittliche Luftfeuchte: "));
    Serial.print(TEMPLUFTFEUCHTE1);
    Serial.println(F(" %"));
    Serial.print(F("Durchschnittliche Temperatur: "));
    Serial.print(TEMPTEMPERATUR1);
    Serial.println(F(" *C"));
  }
  
  Serial.println(F(""));
  Serial.println(F("WLAN-Netzwerk-Scan gestartet..."));
      
  WiFi.mode(WIFI_STA);
  WiFi.disconnect();

  int n = WiFi.scanNetworks();
    
  Serial.println(F("WLAN-Netzwerk-Scan abgeschlossen..."));
  Serial.println(F(""));

  if (n == 0) {
    Serial.println(F("Kein WLAN-Netzwerk gefunden!"));
  } else {
    Serial.print(n);

    if(n<=1) {
     Serial.println(F(" WLAN-Netzwerk gefunden"));
    } else {
      Serial.println(F(" WLAN-Netzwerke gefunden"));
    }
  
    Serial.println(F(""));

    for (int i = 0; i < n; ++i) { 
      Serial.print(i + 1);
      Serial.print(F(": "));
      Serial.print(WiFi.SSID(i));
      Serial.print(F(" ("));
      Serial.print(WiFi.RSSI(i));
      Serial.print(F(")"));
      Serial.println((WiFi.encryptionType(i) == ENC_TYPE_NONE)?" ":"*");
    }
  }

  HTMLFORMULARWLAN = "<b><u>WLAN-Netzwerk ausw&auml;hlen:</u></b>

";

  for (int i = 0; i < n; ++i) {
    // Erstelle Webseite mit allen SSID und RSSI Werten der gefundenen Netzwerke
    HTMLFORMULARWLAN += "<input type='radio' name='WLANSSID' value='"; HTMLFORMULARWLAN += WiFi.SSID(i); HTMLFORMULARWLAN += "'"; if (WiFi.SSID(i)==WLANSSID.substring(0, WiFi.SSID(i).length()+1)) { HTMLFORMULARWLAN += " checked"; } HTMLFORMULARWLAN += ">";
    HTMLFORMULARWLAN += WiFi.SSID(i);
    HTMLFORMULARWLAN += " (";
    HTMLFORMULARWLAN += WiFi.RSSI(i);
    HTMLFORMULARWLAN += ")";
    HTMLFORMULARWLAN += (WiFi.encryptionType(i) == ENC_TYPE_NONE)?" ":"*";
    HTMLFORMULARWLAN += "
";
  }
  
  Serial.println(F("")); 
  
  dht.begin();

  if (FIRSTSTARTFLAG==111) {
    Serial.print(F("Verbinde mit WLAN "));
    Serial.println(WLANSSID);
  
    if (STATICIP==1) {
      WiFi.config(ip, gw, sub, dns);
    }

    WiFi.begin(WLANSSID.c_str(), WLANPWD.c_str());
    
    int WLANTIMEOUT=0;
    
    while (WiFi.status() != WL_CONNECTED) {
      delay(1000);

      Serial.print(F("."));
      
      WLANTIMEOUT+=1;
  
      if (WLANTIMEOUT>=CONNECTIONTIMEOUT) {
        Serial.println(F(""));
        Serial.println(F("Timeout!"));  
        
        TIMEOUTFLAG+=1;

        if(TIMEOUTFLAG>=MAXCONNECTIONTRIES) {
          ResetWiFi();
        } else {
          EEPROM.begin(512);
          EEPROM.write(3, TIMEOUTFLAG);
          EEPROM.end();

          delay(100);
          
          WiFi.disconnect();

          delay(100);
          
          ESP.deepSleep(1000000,WAKE_RF_DEFAULT);
          delay(100);
        }
      }
    }
  
    EEPROM.begin(512);
    EEPROM.write(3, 0);
    EEPROM.end();

    Serial.println(F(""));
    Serial.println(F("Verbindung mit WLAN hergestellt"));  
    Serial.println(F(""));
    Serial.print(F("IP-Addresse: "));
    Serial.println(WiFi.localIP());
    Serial.println(F(""));
    Serial.println(F("Setze Sensorkalibrierung fort... "));
    Serial.println(F(""));
   
    for (int i=1; i<=5; i++) {
      delay(2000);

      GetSensorData();

      ShowSensorData();
      
      TEMPTEMPERATUR2+=AKTUELLETEMPERATUR;
      TEMPLUFTFEUCHTE2+=AKTUELLELUFTFEUCHTE;  
    }
  
    TEMPTEMPERATUR2/=5;
    TEMPLUFTFEUCHTE2/=5;
  
    Serial.print(F("Durchschnittliche Luftfeuchte: "));
    Serial.print(TEMPLUFTFEUCHTE2);
    Serial.println(F(" %"));
    Serial.print(F("Durchschnittliche Temperatur: "));
    Serial.print(TEMPTEMPERATUR2);
    Serial.println(F(" *C"));
    Serial.println(F(""));
  
    KORREKTURTEMPERATUR=TEMPTEMPERATUR1-TEMPTEMPERATUR2;
    KORREKTURLUFTFEUCHTE=TEMPLUFTFEUCHTE1-TEMPLUFTFEUCHTE2;
    
    Serial.print(F("Luftfeuchte Korrekturwert: "));
    Serial.println(KORREKTURLUFTFEUCHTE);
    Serial.print(F("Temperatur Korrekturwert: "));
    Serial.println(KORREKTURTEMPERATUR);
    Serial.println(F(""));
  
    GetSensorData();
    
    Serial.println(F("Starte im Normal-Modus"));
    WiFi.softAP(SENSORSSID.c_str(), SENSORPWD.c_str());
  
    delay(100);
    
    Serial.println(F(""));
    Serial.println(F("AP Modus gestartet"));
    Serial.print(F("SSID: "));
    Serial.println(SENSORSSID.c_str());
    Serial.print(F("AP IP-Adresse: "));
    Serial.println(WiFi.softAPIP());
    Serial.println(F(""));

    if (THINGSPEAKAKTIV == 1) {
      SendSensorData();
    }
  } else {
    digitalWrite(LEDPIN ,1);
    
    String SENSORSSIDSETUP = "ESP8266-DHT22-SENSOR-SETUP";
    SENSORPWD = "";
    FIRSTSTARTFLAG=1;
    
    Serial.println(F("Starte im Setup-Modus!!!"));
    WiFi.softAP(SENSORSSIDSETUP.c_str(), SENSORPWD.c_str());
  
    delay(100);
    
    Serial.println(F(""));
    Serial.println(F("AP Modus gestartet"));
    Serial.print(F("SSID: "));
    Serial.println(SENSORSSIDSETUP.c_str());
    Serial.print(F("AP IP-Adresse: "));
    Serial.println(WiFi.softAPIP());
  } 

  Serial.println(F(""));
  Serial.println(F("Starte Server"));

  server.begin();

  Serial.println(F("Server gestartet")); 
  Serial.println(F(""));

  Serial.println(F("...ESP8266-DHT22-SENSOR erfolgreich gestartet."));
  Serial.println(F(""));  

  STARTZEITPUNKTMESSUNG=0;
  STARTZEITPUNKTTS=0;
  
  THINGSPEAKUPDATEINTERVAL=UPDATEINTERVAL*60000;
}

void loop() {  
  unsigned long ISTZEITPUNKT=millis();
  
  //Wenn Systemspannung zu gering System abschalten
  if (ESP.getVcc() <= SHUTDOWNVCC) { Serial.println(F("Systemspannung zu gering, System wird abgeschaltet...")); Serial.println(F("")); delay(100); ESP.deepSleep(0, WAKE_RF_DISABLED); delay(100); } if (FIRSTSTARTFLAG == 111) { //Ist es an der Zeit zu messen? if ((unsigned long)(ISTZEITPUNKT-STARTZEITPUNKTMESSUNG) >= 2000) {
      GetSensorData();
      ShowSensorData();
    
      STARTZEITPUNKTMESSUNG=ISTZEITPUNKT;
    } else if (THINGSPEAKAKTIV == 1) {
      //Ist es an der Zeit Daten an Thingspeak zu senden?
      if ((unsigned long)(ISTZEITPUNKT-STARTZEITPUNKTTS) >= THINGSPEAKUPDATEINTERVAL) {
        SendSensorData();
        STARTZEITPUNKTTS=ISTZEITPUNKT;
      }
    }
  }
  
  WiFiClient client = server.available();

  if (digitalRead(RESETPIN)==0) {
    digitalWrite(LEDPIN, 1);
    
    delay(500);
    
    while (digitalRead(RESETPIN)==0) {
      delay(100);
    }

    digitalWrite(LEDPIN, 0);

    delay(500);
    
    ResetWiFi();
  }

  if(client) {
    while(client.connected() && !client.available()){
      delay(1);
    }

    String RequestString = client.readStringUntil('\r');

    int addr_start = RequestString.indexOf(' ');
    int addr_end = RequestString.indexOf(' ', addr_start + 1);

    if (addr_start == -1 || addr_end == -1) {
      Serial.print(F("Ungueltige Anfrage: "));
      Serial.println(RequestString);
      Serial.println(F(""));
      
      client.stop();
    } else {
      RequestString = RequestString.substring(addr_start + 1, addr_end);

      Serial.print(F("Gueltige Anfrage: "));
      Serial.println(RequestString);
      Serial.println(F(""));
      
      String HTMLSite="";
      String HTMLHeader="";
      
      if (RequestString.startsWith("/setwlanconfig?")) {
        FIRSTSTARTFLAG=0;
        step=2;

        EEPROM.begin(512);

        delay(10);
        
        //1. Wert extrahieren (WLAN SSID)
        int StartPosition=RequestString.indexOf('=');
        StartPosition++;
        
        int EndePosition=RequestString.indexOf("&");

        String NeueWLANSSID; 
        NeueWLANSSID = RequestString.substring(StartPosition,EndePosition);

        Serial.println(F(""));
        Serial.println(F("Schreibe neue WLANSSID ins EEPROM:"));
  
        for (int i = 0; i < NeueWLANSSID.length(); ++i){
          EEPROM.write(21+i, NeueWLANSSID[i]);
          
          Serial.print(F("schreibe: "));
          Serial.println(NeueWLANSSID[i]); 
        }    

        //2. Wert extrahieren (Netzwerk Passwort)
        StartPosition=RequestString.indexOf("=",EndePosition);
        StartPosition++;
        
        EndePosition=RequestString.indexOf("&",EndePosition+2);
        
        String NeuesWLANPWD;
        NeuesWLANPWD = RequestString.substring(StartPosition,EndePosition);

        Serial.println(F(""));
        Serial.println(F("Schreibe neues WLANPWD ins EEPROM:"));

        for (int i = 0; i < NeuesWLANPWD.length(); ++i){
          EEPROM.write(53+i, NeuesWLANPWD[i]);
          
          Serial.print(F("schreibe: "));
          Serial.println(NeuesWLANPWD[i]); 
        }    

        //3. Wert extrahieren (CONNECTIONTIMEOUT)
        int NeuesCONNECTIONTIMEOUT=0;
        NeuesCONNECTIONTIMEOUT=RequestString.substring(RequestString.lastIndexOf("=")+1).toInt();

        Serial.println(F(""));
        Serial.print(F("Schreibe neues CONNECTIONTIMEOUT ins EEPROM: "));

        Serial.print(F("schreibe: "));
        Serial.println(NeuesCONNECTIONTIMEOUT);
        
        EEPROM.write(2, NeuesCONNECTIONTIMEOUT);

        EEPROM.commit();
        EEPROM.end();
      }
      
      if (RequestString.startsWith("/setipconfig?")) {
        step=3;

        EEPROM.begin(512);

        delay(10);
        
        //1. Wert extrahieren (IP Typ)
        int StartPosition=RequestString.indexOf('=');
        StartPosition++;
        
        int EndePosition=RequestString.indexOf("&");

        int NeuerIPTYP; 
        NeuerIPTYP = RequestString.substring(StartPosition,EndePosition).toInt();

        Serial.println(F(""));
        Serial.println(F("Schreibe neuen IPTYP ins EEPROM:"));
  
        EEPROM.write(4, NeuerIPTYP);

        Serial.print(F("schreibe: "));
        Serial.println(NeuerIPTYP); 

        //2. Wert extrahieren (IP-Adresse Teil 1)
        StartPosition=RequestString.indexOf("=",EndePosition);
        StartPosition++;
        
        EndePosition=RequestString.indexOf("&",EndePosition+2);
        
        int NeueIP;
        NeueIP = RequestString.substring(StartPosition,EndePosition).toInt();

        Serial.println(F(""));
        Serial.println(F("Schreibe neue IP-Adresse Teil 1 ins EEPROM:"));

        EEPROM.write(5, NeueIP);
        
        Serial.print(F("schreibe: "));
        Serial.println(NeueIP); 

        //3. Wert extrahieren (IP-Adresse Teil 2)
        StartPosition=RequestString.indexOf("=",EndePosition);
        StartPosition++;
        
        EndePosition=RequestString.indexOf("&",EndePosition+2);
        
        NeueIP = RequestString.substring(StartPosition,EndePosition).toInt();

        Serial.println(F(""));
        Serial.println(F("Schreibe neue IP-Adresse Teil 2 ins EEPROM:"));

        EEPROM.write(6, NeueIP);
        
        Serial.print(F("schreibe: "));
        Serial.println(NeueIP); 

        //4. Wert extrahieren (IP-Adresse Teil 3)
        StartPosition=RequestString.indexOf("=",EndePosition);
        StartPosition++;
        
        EndePosition=RequestString.indexOf("&",EndePosition+2);
        
        NeueIP = RequestString.substring(StartPosition,EndePosition).toInt();

        Serial.println(F(""));
        Serial.println(F("Schreibe neue IP-Adresse Teil 3 ins EEPROM:"));

        EEPROM.write(7, NeueIP);
        
        Serial.print(F("schreibe: "));
        Serial.println(NeueIP); 

        //5. Wert extrahieren (IP-Adresse Teil 4)
        StartPosition=RequestString.indexOf("=",EndePosition);
        StartPosition++;
        
        EndePosition=RequestString.indexOf("&",EndePosition+2);
        
        NeueIP = RequestString.substring(StartPosition,EndePosition).toInt();

        Serial.println(F(""));
        Serial.println(F("Schreibe neue IP-Adresse Teil 4 ins EEPROM:"));

        EEPROM.write(8, NeueIP);
        
        Serial.print(F("schreibe: "));
        Serial.println(NeueIP); 

        //6. Wert extrahieren (Gateway IP-Adresse Teil 1)
        StartPosition=RequestString.indexOf("=",EndePosition);
        StartPosition++;
        
        EndePosition=RequestString.indexOf("&",EndePosition+2);
        
        NeueIP = RequestString.substring(StartPosition,EndePosition).toInt();

        Serial.println(F(""));
        Serial.println(F("Schreibe neue Gateway IP-Adresse Teil 1 ins EEPROM:"));

        EEPROM.write(9, NeueIP);
        
        Serial.print(F("schreibe: "));
        Serial.println(NeueIP); 

        //7. Wert extrahieren (Gateway IP-Adresse Teil 2)
        StartPosition=RequestString.indexOf("=",EndePosition);
        StartPosition++;
        
        EndePosition=RequestString.indexOf("&",EndePosition+2);
        
        NeueIP = RequestString.substring(StartPosition,EndePosition).toInt();

        Serial.println(F(""));
        Serial.println(F("Schreibe neue Gateway IP-Adresse Teil 2 ins EEPROM:"));

        EEPROM.write(10, NeueIP);
        
        Serial.print(F("schreibe: "));
        Serial.println(NeueIP); 

        //8. Wert extrahieren (Gateway IP-Adresse Teil 3)
        StartPosition=RequestString.indexOf("=",EndePosition);
        StartPosition++;
        
        EndePosition=RequestString.indexOf("&",EndePosition+2);
        
        NeueIP = RequestString.substring(StartPosition,EndePosition).toInt();

        Serial.println(F(""));
        Serial.println(F("Schreibe neue Gateway IP-Adresse Teil 3 ins EEPROM:"));

        EEPROM.write(11, NeueIP);
        
        Serial.print(F("schreibe: "));
        Serial.println(NeueIP); 

        //9. Wert extrahieren (Gateway IP-Adresse Teil 4)
        StartPosition=RequestString.indexOf("=",EndePosition);
        StartPosition++;
        
        EndePosition=RequestString.indexOf("&",EndePosition+2);
        
        NeueIP = RequestString.substring(StartPosition,EndePosition).toInt();

        Serial.println(F(""));
        Serial.println(F("Schreibe neue Gateway IP-Adresse Teil 4 ins EEPROM:"));

        EEPROM.write(12, NeueIP);
        
        Serial.print(F("schreibe: "));
        Serial.println(NeueIP); 

        //10. Wert extrahieren (Subnet Mask Teil 1)
        StartPosition=RequestString.indexOf("=",EndePosition);
        StartPosition++;
        
        EndePosition=RequestString.indexOf("&",EndePosition+2);
        
        NeueIP = RequestString.substring(StartPosition,EndePosition).toInt();

        Serial.println(F(""));
        Serial.println(F("Schreibe neue Subnet Mask Teil 1 ins EEPROM:"));

        EEPROM.write(13, NeueIP);
        
        Serial.print(F("schreibe: "));
        Serial.println(NeueIP); 

        //11. Wert extrahieren (Subnet Mask Teil 2)
        StartPosition=RequestString.indexOf("=",EndePosition);
        StartPosition++;
        
        EndePosition=RequestString.indexOf("&",EndePosition+2);
        
        NeueIP = RequestString.substring(StartPosition,EndePosition).toInt();

        Serial.println(F(""));
        Serial.println(F("Schreibe neue Subnet Mask Teil 2 ins EEPROM:"));

        EEPROM.write(14, NeueIP);
        
        Serial.print(F("schreibe: "));
        Serial.println(NeueIP); 

        //12. Wert extrahieren (Subnet Mask Teil 3)
        StartPosition=RequestString.indexOf("=",EndePosition);
        StartPosition++;
        
        EndePosition=RequestString.indexOf("&",EndePosition+2);
        
        NeueIP = RequestString.substring(StartPosition,EndePosition).toInt();

        Serial.println(F(""));
        Serial.println(F("Schreibe neue Subnet Mask Teil 3 ins EEPROM:"));

        EEPROM.write(15, NeueIP);
        
        Serial.print(F("schreibe: "));
        Serial.println(NeueIP); 

        //13. Wert extrahieren (Subnet Mask Teil 4)
        StartPosition=RequestString.indexOf("=",EndePosition);
        StartPosition++;
        
        EndePosition=RequestString.indexOf("&",EndePosition+2);
        
        NeueIP = RequestString.substring(StartPosition,EndePosition).toInt();

        Serial.println(F(""));
        Serial.println(F("Schreibe neue Subnet Mask Teil 4 ins EEPROM:"));

        EEPROM.write(16, NeueIP);
        
        Serial.print(F("schreibe: "));
        Serial.println(NeueIP); 

        //14. Wert extrahieren (DNS Server IP-Adresse Teil 1)
        StartPosition=RequestString.indexOf("=",EndePosition);
        StartPosition++;
        
        EndePosition=RequestString.indexOf("&",EndePosition+2);
        
        NeueIP = RequestString.substring(StartPosition,EndePosition).toInt();

        Serial.println(F(""));
        Serial.println(F("Schreibe neue DNS Server IP-Adresse Teil 1 ins EEPROM:"));

        EEPROM.write(17, NeueIP);
        
        Serial.print(F("schreibe: "));
        Serial.println(NeueIP); 

        //15. Wert extrahieren (DNS Server IP-Adresse Teil 2)
        StartPosition=RequestString.indexOf("=",EndePosition);
        StartPosition++;
        
        EndePosition=RequestString.indexOf("&",EndePosition+2);
        
        NeueIP = RequestString.substring(StartPosition,EndePosition).toInt();

        Serial.println(F(""));
        Serial.println(F("Schreibe neue DNS Server IP-Adresse Teil 2 ins EEPROM:"));

        EEPROM.write(18, NeueIP);
        
        Serial.print(F("schreibe: "));
        Serial.println(NeueIP); 

        //16. Wert extrahieren (DNS Server IP-Adresse Teil 3)
        StartPosition=RequestString.indexOf("=",EndePosition);
        StartPosition++;
        
        EndePosition=RequestString.indexOf("&",EndePosition+2);
        
        NeueIP = RequestString.substring(StartPosition,EndePosition).toInt();

        Serial.println(F(""));
        Serial.println(F("Schreibe neue DNS Server IP-Adresse Teil 3 ins EEPROM:"));

        EEPROM.write(19, NeueIP);
        
        Serial.print(F("schreibe: "));
        Serial.println(NeueIP); 

        //17. Wert extrahieren (DNS Server IP-Adresse Teil 4)
        NeueIP = RequestString.substring(RequestString.lastIndexOf("=")+1).toInt();
        
        Serial.println(F(""));
        Serial.println(F("Schreibe neue DNS Server IP-Adresse Teil 4 ins EEPROM:"));

        EEPROM.write(20, NeueIP);
        
        Serial.print(F("schreibe: "));
        Serial.println(NeueIP); 

        EEPROM.commit();
        EEPROM.end();
      }

      if (RequestString.startsWith("/settsconfig?")) {
        step=4;

        EEPROM.begin(512);

        delay(10);
        
        //1. Wert extrahieren (THINGSPEAKATIV)
        int StartPosition=RequestString.indexOf('=');
        StartPosition++;
        
        int EndePosition=RequestString.indexOf("&");

        int NeuTHINGSSPEAKAKTIV; 
        NeuTHINGSSPEAKAKTIV = RequestString.substring(StartPosition,EndePosition).toInt();

        Serial.println(F(""));
        Serial.println(F("Schreibe neuen THINGSPEAKATIV Status ins EEPROM:"));
  
        EEPROM.write(238, NeuTHINGSSPEAKAKTIV);
        
        Serial.print(F("schreibe: "));
        Serial.println(NeuTHINGSSPEAKAKTIV); 

        //2. Wert extrahieren (UPDATEINTERVAL)
        StartPosition=RequestString.indexOf('=', EndePosition);
        StartPosition++;
        
        EndePosition=RequestString.indexOf("&", EndePosition + 2);

        int NeuesUPDATEINTERVAL = 0;
        NeuesUPDATEINTERVAL = RequestString.substring(StartPosition,EndePosition).toInt();

        Serial.println(F(""));
        Serial.println(F("Schreibe neues UPDATEINTERVAL ins EEPROM:"));

        EEPROM.write(1, NeuesUPDATEINTERVAL);
        
        Serial.print(F("schreibe: "));
        Serial.println(NeuesUPDATEINTERVAL); 

        //3. Wert extrahieren (UPDATEINTERVAL)
        String NeuerTHINGSPEAKAPIKEY; 
        NeuerTHINGSPEAKAPIKEY = RequestString.substring(RequestString.lastIndexOf("=")+1);

        Serial.println(F(""));
        Serial.println(F("Schreibe neuen THINGSPEAKAPIKEY ins EEPROM:"));

        for (int i = 0; i < NeuerTHINGSPEAKAPIKEY.length(); ++i){
          EEPROM.write(239+i, NeuerTHINGSPEAKAPIKEY[i]);
          
          Serial.print(F("schreibe: "));
          Serial.println(NeuerTHINGSPEAKAPIKEY[i]); 
        }    

        EEPROM.commit();
        EEPROM.end();
      }

      if (RequestString.startsWith("/setsensorconfig?")) {
        step=5;

        EEPROM.begin(512);

        delay(10);
        
        //1. Wert extrahieren (STANDORT)
        int StartPosition=RequestString.indexOf('=');
        StartPosition++;
        
        int EndePosition=RequestString.indexOf("&");

        String NeuerSTANDORT; 
        NeuerSTANDORT = RequestString.substring(StartPosition,EndePosition);

        Serial.println(F(""));
        Serial.println(F("Schreibe neuen STANDORT ins EEPROM:"));
  
        for (int i = 0; i < NeuerSTANDORT.length(); ++i){
          EEPROM.write(213+i, NeuerSTANDORT[i]);
          
          Serial.print(F("schreibe: "));
          Serial.println(NeuerSTANDORT[i]); 
        }    

        //2. Wert extrahieren (SENSORSSID)
        StartPosition=RequestString.indexOf("=",EndePosition);
        StartPosition++;
        
        EndePosition=RequestString.indexOf("&",EndePosition+2);

        String NeueSENSORSSID = "";
        NeueSENSORSSID = RequestString.substring(StartPosition,EndePosition);

        Serial.println(F(""));
        Serial.println(F("Schreibe neue SENSORSSID ins EEPROM:"));

        for (int i = 0; i < NeueSENSORSSID.length(); ++i){
          EEPROM.write(117+i, NeueSENSORSSID[i]);
          
          Serial.print(F("schreibe: "));
          Serial.println(NeueSENSORSSID[i]); 
        }    

        //3. Wert extrahieren (SENSORPWD)
        StartPosition=RequestString.indexOf("=",EndePosition);
        StartPosition++;
        
        EndePosition=RequestString.indexOf("&",EndePosition+2);

        String NeuesSENSORPWD = "";
        NeuesSENSORPWD = RequestString.substring(RequestString.lastIndexOf("=")+1);

        Serial.println(F(""));
        Serial.println(F("Schreibe neues SENSORPWD ins EEPROM:"));

        for (int i = 0; i < NeuesSENSORPWD.length(); ++i){
          EEPROM.write(149+i, NeuesSENSORPWD[i]);
          
          Serial.print(F("schreibe: "));
          Serial.println(NeuesSENSORPWD[i]); 
        }    

        Serial.println(F("Schreibe neues FIRSTSTARTFLAG ins EEPROM:"));
        FIRSTSTARTFLAG=111;
        
        EEPROM.write(0, FIRSTSTARTFLAG);

        Serial.print(F("schreibe: "));
        Serial.println(FIRSTSTARTFLAG); 

        EEPROM.commit();
        EEPROM.end();
      }

      if (step==5) {
        Serial.println(F("Abschlussseite des Setup wird ausgegeben"));
        Serial.println(F(""));
        
        HTMLSite ="<!DOCTYPE html><html><head>";
        HTMLSite += "<title>";
        HTMLSite += SENSORSSID.c_str();
        HTMLSite += "</title>";
        HTMLSite += "</head><body style='font-family:Verdana, Arial, Sans-Serif'><center>";
        HTMLSite += SENSORSSID.c_str();
        HTMLSite += "<fieldset style='width:450px'>";
        HTMLSite += "<b>Das Setup des Sensors";
        HTMLSite += "ist abgeschlossen.";
        HTMLSite += "Der Sensor startet jetzt neu!";
        HTMLSite += "</fieldset></center></body></html>\r\n\r\n";

        HTMLHeader  = "HTTP/1.1 200 OK\r\n";
        HTMLHeader += "Content-Length: ";
        HTMLHeader += HTMLSite.length();
        HTMLHeader += "\r\n";
        HTMLHeader += "Content-Type: text/html\r\n";
        HTMLHeader += "Connection: close\r\n";
        HTMLHeader += "\r\n";
        
        client.print(HTMLHeader);
        delay(100);
        client.print(HTMLSite);
        delay(100);
        
        client.stop();

        WiFi.disconnect();

        ESP.deepSleep(1000,WAKE_RF_DEFAULT); //System neu starten über Deep-Sleep Timer
        delay(100);
      }
      
      if (RequestString.startsWith("/wlanconfig.htm") || step==1) {

        EEPROM.begin(512);

        delay(10);
        
        //Lösche alte Daten aus EEPROM
        for (int i=0; i<512; i++) {
          EEPROM.write(i,0);
        }

        EEPROM.commit();
        EEPROM.end();
        
        Serial.println(F("WLAN Konfigurationsseite wird ausgegeben"));
        Serial.println(F(""));

        HTMLSite ="<!DOCTYPE html><html><head><title>";
        HTMLSite += SENSORSSID.c_str();
        HTMLSite += "</title>";
        HTMLSite += "</head><body style='font-family:Verdana, Arial, Sans-Serif'><center>";
        HTMLSite += SENSORSSID.c_str();
        HTMLSite += "<fieldset style='width:450px'><legend>Sensor Setup Schritt 1</legend>";
        HTMLSite += "<form method='GET' action='setwlanconfig'>";
        HTMLSite += "<b>WLAN Einstellungen</b><hr />";
        HTMLSite += HTMLFORMULARWLAN;
        HTMLSite += "WLAN-Passwort: <input name='WLANPWD' type='text' size='30' maxlength='64' value='"; 
        HTMLSite += WLANPWD.c_str(); 
        HTMLSite += "'></input>";
        HTMLSite += "Verbindungs-Timeout: ";
        HTMLSite += "<select name='CONNECTIONTIMEOUT' size='1'>";

        if (CONNECTIONTIMEOUT==10) {
          HTMLSite += "<option value='10' selected>10</option><option value='30'>30</option><option value='60'>60</option>";
        } else if (CONNECTIONTIMEOUT==30) {
          HTMLSite += "<option value='10'>10</option><option value='30' selected>30</option><option value='60'>60</option>";
        } else {
          HTMLSite += "<option value='10'>10</option><option value='30'>30</option><option value='60' selected>60</option>";
        }
 
        HTMLSite += "</select> Sekunden";
        HTMLSite += "</fieldset>";
        HTMLSite += "<input type='submit' value='Einstellungen speichern und weiter zu Schritt 2...'></form>";
        HTMLSite += "</center></body></html>\r\n\r\n";
      }
      
      if (RequestString.startsWith("/ipconfig.htm") || step==2) {
        Serial.println(F("IP Konfigurationsseite wird ausgegeben"));
        Serial.println(F(""));

        HTMLSite ="<!DOCTYPE html><html><head><title>";
        HTMLSite += SENSORSSID.c_str();
        HTMLSite += "</title>";
        HTMLSite += "</head><body style='font-family:Verdana, Arial, Sans-Serif'><center>";
        HTMLSite += SENSORSSID.c_str();
        HTMLSite += "<fieldset style='width:450px'><legend>Sensor Setup Schritt 2</legend>";
        HTMLSite += "<form method='GET' action='setipconfig'>";
        HTMLSite += "<b>IP Einstellungen</b><hr />";
        HTMLSite += "IP-Adresstyp: ";
        HTMLSite += "<select name='STATICIP' size='1'>";
        
        if (STATICIP==0) {
          HTMLSite += "<option value='0' selected>DHCP</option><option value='1'>Statisch</option></select>";
        } else {
          HTMLSite += "<option value='0'>DHCP</option><option value='1' selected>Statisch</option></select>";
        }

        HTMLSite += "IP-Adresse: <input name='IP1' type='text' size='3' maxlength='3' value='"; 
        HTMLSite += String(ip[0]); 
        HTMLSite += "'></input>.";
        HTMLSite += "<input name='IP2' type='text' size='3' maxlength='3' value='"; 
        HTMLSite += String(ip[1]); 
        HTMLSite += "'></input>.";
        HTMLSite += "<input name='IP3' type='text' size='3' maxlength='3' value='"; 
        HTMLSite += String(ip[2]); 
        HTMLSite += "'></input>.";
        HTMLSite += "<input name='IP4' type='text' size='3' maxlength='3' value='"; 
        HTMLSite += String(ip[3]); 
        HTMLSite += "'></input>";
        HTMLSite += "Gateway IP-Adresse: <input name='GWIP1' type='text' size='3' maxlength='3' value='"; 
        HTMLSite += String(gw[0]); 
        HTMLSite += "'></input>.";
        HTMLSite += "<input name='GWIP2' type='text' size='3' maxlength='3' value='"; 
        HTMLSite += String(gw[1]); 
        HTMLSite += "'></input>.";
        HTMLSite += "<input name='GWIP3' type='text' size='3' maxlength='3' value='"; 
        HTMLSite += String(gw[2]); 
        HTMLSite += "'></input>.";
        HTMLSite += "<input name='GWIP4' type='text' size='3' maxlength='3' value='"; 
        HTMLSite += String(gw[3]); 
        HTMLSite += "'></input>";
        HTMLSite += "Subnet Mask: <input name='MASK1' type='text' size='3' maxlength='3' value='"; 
        HTMLSite += String(sub[0]); 
        HTMLSite += "'></input>.";
        HTMLSite += "<input name='MASK2' type='text' size='3' maxlength='3' value='"; 
        HTMLSite += String(sub[1]); 
        HTMLSite += "'></input>.";
        HTMLSite += "<input name='MASK3' type='text' size='3' maxlength='3' value='"; 
        HTMLSite += String(sub[2]); 
        HTMLSite += "'></input>.";
        HTMLSite += "<input name='MASK4' type='text' size='3' maxlength='3' value='"; 
        HTMLSite += String(sub[3]); 
        HTMLSite += "'></input>";
        HTMLSite += "DNS-Server IP-Adresse: <input name='DNSIP1' type='text' size='3' maxlength='3' value='"; 
        HTMLSite += String(dns[0]); 
        HTMLSite += "'></input>.";
        HTMLSite += "<input name='DNSIP2' type='text' size='3' maxlength='3' value='"; 
        HTMLSite += String(dns[1]); 
        HTMLSite += "'></input>.";
        HTMLSite += "<input name='DNSIP3' type='text' size='3' maxlength='3' value='"; 
        HTMLSite += String(dns[2]); 
        HTMLSite += "'></input>.";
        HTMLSite += "<input name='DNSIP4' type='text' size='3' maxlength='3' value='"; 
        HTMLSite += String(dns[3]); 
        HTMLSite += "'></input>";
        HTMLSite += "</fieldset>";
        HTMLSite += "<input type='submit' value='Einstellungen speichern und weiter zu Schritt 3...'></form>";
        HTMLSite += "</center></body></html>\r\n\r\n";
      } 
      
      if (RequestString.startsWith("/tsconfig.htm") || step==3) {
        Serial.println(F("Thingspeak Konfigurationsseite wird ausgegeben"));
        Serial.println(F(""));

        HTMLSite ="<!DOCTYPE html><html><head><title>";
        HTMLSite += SENSORSSID.c_str();
        HTMLSite += "</title>";
        HTMLSite += "</head><body style='font-family:Verdana, Arial, Sans-Serif'><center>";
        HTMLSite += SENSORSSID.c_str();
        HTMLSite += "<fieldset style='width:450px'><legend>Sensor Setup Schritt 3</legend>";
        HTMLSite += "<form method='GET' action='settsconfig'>";
        HTMLSite += "<b>Thingspeak Einstellungen</b><hr />";
        HTMLSite += "&Uuml;bertragung aktiv: ";
        HTMLSite += "<select name='THINGSPEAKAKTIV' size='1'>";

        if (THINGSPEAKAKTIV==0) {
          HTMLSite += "<option value='0' selected>NEIN</option><option value='1'>JA</option></select>";
        } else {
          HTMLSite += "<option value='0'>NEIN</option><option value='1' selected>JA</option></select>";
        }

        HTMLSite += "&Uuml;bertrag alle ";
        HTMLSite += "<select name='UPDATEINTERVAL' size='1'>";

        if (UPDATEINTERVAL==15) {
          HTMLSite += "<option value='15' selected>15</option><option value='30'>30</option><option value='45'>45</option><option value='60'>60</option>";
        } else if (UPDATEINTERVAL==30) {  
          HTMLSite += "<option value='15'>15</option><option value='30' selected>30</option><option value='45'>45</option><option value='60'>60</option>";
        } else if (UPDATEINTERVAL==30) {  
          HTMLSite += "<option value='15'>15</option><option value='30'>30</option><option value='45' selected>45</option><option value='60'>60</option>";
        } else {  
          HTMLSite += "<option value='15'>15</option><option value='30'>30</option><option value='45'>45</option><option value='60' selected>60</option>";
        }

        HTMLSite += "</select> Minuten";
        HTMLSite += "API Write-Key: <input name='THINGSPEAKAPIKEY' type='text' size='20' maxlength='16' value='"; 
        HTMLSite += THINGSPEAKAPIKEY.c_str(); HTMLSite += "'></input>";
        HTMLSite += "</fieldset>";
        HTMLSite += "<input type='submit' value='Einstellungen speichern und weiter zu Schritt 4...'></form>";
        HTMLSite += "</center></body></html>\r\n\r\n";
      } 
      
      if (RequestString.startsWith("/sensorconfig.htm") || step==4) {
        Serial.println(F("Sensor Konfigurationsseite wird ausgegeben"));
        Serial.println(F(""));

        HTMLSite ="<!DOCTYPE html><html><head><title>";
        HTMLSite += SENSORSSID.c_str();
        HTMLSite += "</title>";
        HTMLSite += "</head><body style='font-family:Verdana, Arial, Sans-Serif'><center>";
        HTMLSite += SENSORSSID.c_str();
        HTMLSite += "<fieldset style='width:450px'><legend>Sensor Setup Schritt 4</legend>";
        HTMLSite += "<form method='GET' action='setsensorconfig'>";
        HTMLSite += "<b>Sensor Einstellungen</b><hr />";
        HTMLSite += "Standort: <input name='SENSORSTANDORT' type='text' size='25' maxlength='25' value='"; 
        HTMLSite += SENSORSTANDORT.c_str(); 
        HTMLSite += "'></input>";
        HTMLSite += "SSID: <input name='SENSORSSID' type='text' size='32' maxlength='32' value='"; 
        HTMLSite += SENSORSSID.c_str(); 
        HTMLSite += "'></input>";
        HTMLSite += "Passwort: <input name='SENSORPWD' type='text' size='30' maxlength='64' value='"; 
        HTMLSite += SENSORPWD.c_str(); 
        HTMLSite += "'></input></fieldset>";
        HTMLSite += "<input type='submit' value='Einstellungen speichern und das Setup beenden'></form>";
        HTMLSite += "</center></body></html>\r\n\r\n";
      } 

      uint8_t mac[6];
      WiFi.macAddress(mac);
      IPAddress LOCALIPIST = WiFi.localIP();
      IPAddress GATEWAYIST = WiFi.gatewayIP();
      IPAddress SUBMASKIST = WiFi.subnetMask();
      IPAddress DNSIPIST = WiFi.dnsIP();
      
      String HTMLipStr = String(LOCALIPIST[0]) + '.' + String(LOCALIPIST[1]) + '.' + String(LOCALIPIST[2]) + '.' + String(LOCALIPIST[3]);
      String HTMLgwStr = String(GATEWAYIST[0]) + '.' + String(GATEWAYIST[1]) + '.' + String(GATEWAYIST[2]) + '.' + String(GATEWAYIST[3]);
      String HTMLsmStr = String(SUBMASKIST[0]) + '.' + String(SUBMASKIST[1]) + '.' + String(SUBMASKIST[2]) + '.' + String(SUBMASKIST[3]);
      String HTMLdnsStr = String(DNSIPIST[0]) + '.' + String(DNSIPIST[1]) + '.' + String(DNSIPIST[2]) + '.' + String(DNSIPIST[3]);

      if (RequestString.startsWith("/sensorinfo") && step==0 && FIRSTSTARTFLAG==111) {  
        HTMLSite ="<!DOCTYPE html><html><head><meta http-equiv='refresh' content='5'><title>";
        HTMLSite += SENSORSSID.c_str();
        HTMLSite += "</title>";
        HTMLSite += "</head><body style='font-family:Verdana, Arial, Sans-Serif'><center>";
        HTMLSite += SENSORSSID.c_str();
        HTMLSite += "<fieldset style='width:350px'><legend>Sensor Informationen</legend>";
        HTMLSite += "ESP8266 Chip-ID: ";
        HTMLSite += ESP.getChipId();
        HTMLSite += "ESP8266 Speed: ";
        HTMLSite += ESP.getCpuFreqMHz();
        HTMLSite += " MHz";
        HTMLSite += "Flash Chip-ID: ";
        HTMLSite += ESP.getFlashChipId();
        HTMLSite += "Flash Speed: ";
        HTMLSite += ESP.getFlashChipSpeed()/1000000;
        HTMLSite += " MHz";
        HTMLSite += "Flash Size: ";
        HTMLSite += ESP.getFlashChipSize();
        HTMLSite += " Bytes<hr />SDK-Version: ";
        HTMLSite += ESP.getSdkVersion();
        HTMLSite += "Boot Mode: ";
        HTMLSite += ESP.getBootMode();
        HTMLSite += "Free Heap Size: ";
        HTMLSite += ESP.getFreeHeap();
        HTMLSite += " Bytes<hr />";
        HTMLSite += "Systemspannung: ";
        HTMLSite += String(ESP.getVcc()).substring(0,1);
        HTMLSite += ",";
        HTMLSite += String(ESP.getVcc()).substring(1);
        HTMLSite += " Volt</fieldset><fieldset style='width:350px'><form action='index.htm'><input type='submit' value='Zur&uuml;ck zu den Sensorwerten'></form>";
        HTMLSite += "</fieldset></center></body></html>\r\n\r\n";
      } else if (RequestString.startsWith("/netinfo") && step==0 && FIRSTSTARTFLAG==111) {  
        HTMLSite ="<!DOCTYPE html><html><head><title>";
        HTMLSite += SENSORSSID.c_str();
        HTMLSite += "</title>";
        HTMLSite += "</head><body style='font-family:Verdana, Arial, Sans-Serif'><center>";
        HTMLSite += SENSORSSID.c_str();
        HTMLSite += "<fieldset style='width:350px'><legend>WLAN Netzwerk Informationen</legend>";
        HTMLSite += "WLAN SSID: ";
        HTMLSite += WiFi.SSID();
        HTMLSite += "WLAN Kanal: ";
        HTMLSite += WiFi.channel();
        HTMLSite += "WLAN Signalkst&auml;rke: ";
        HTMLSite += WiFi.RSSI();
        HTMLSite += " dBm";
        HTMLSite += "Router MAC Adresse: ";
        HTMLSite += WiFi.BSSIDstr();
        HTMLSite += "Eigene IP-Adresse: ";
        HTMLSite += HTMLipStr;
        HTMLSite += "Eigene MAC Adresse: ";
        HTMLSite += macToStr(mac);
        HTMLSite += "Gateway IP-Adresse: ";
        HTMLSite += HTMLgwStr;
        HTMLSite += "Subnet Mask: ";
        HTMLSite += HTMLsmStr;
        HTMLSite += "DNS Server IP-Adresse: ";
        HTMLSite += HTMLdnsStr;
        HTMLSite += "</fieldset><fieldset style='width:350px'><form action='index.htm'><input type='submit' value='Zur&uuml;ck zu den Sensorwerten'></form>";
        HTMLSite += "</fieldset></center></body></html>\r\n\r\n";
      } else if (RequestString.startsWith("/prginfo") && step==0 && FIRSTSTARTFLAG==111) {  
        HTMLSite ="<!DOCTYPE html><html><head><title>";
        HTMLSite += SENSORSSID.c_str();
        HTMLSite += "</title>";
        HTMLSite += "</head><body style='font-family:Verdana, Arial, Sans-Serif'>
<center>";
        HTMLSite += SENSORSSID.c_str();
        HTMLSite += "<fieldset style='width:350px'><legend>Programm Informationen</legend>";
        HTMLSite += "Version";
        HTMLSite += SOFTWAREVERSION;
        HTMLSite += "<hr />Author <a href='http://blog.thomasheldt.de' target=_blank'>Thomas Heldt</a> (Karlsbad, Germany)";
        HTMLSite += "<hr />Arduino ESP8266 Addon <a href='https://github.com/esp8266/Arduino' target='_blank'>ESP8266 Arduino Core auf Github</a>";
        HTMLSite += "<hr />DHT22 Library <a href='https://github.com/adafruit/DHT-sensor-library' target='_blank'>Adafruit DHT Library</a>";
        HTMLSite += "</fieldset><fieldset style='width:350px'><form action='index.htm'><input type='submit' value='Zur&uuml;ck zu den Sensorwerten'></form>";
        HTMLSite += "</fieldset></center></body></html>\r\n\r\n";
      } else if (RequestString.startsWith("/") && step==0 && FIRSTSTARTFLAG==111) {  
        String TEMPAKTUELLETEMPERATUR=String(AKTUELLETEMPERATUR, 2);
        TEMPAKTUELLETEMPERATUR.replace(".",",");
        
        String TEMPAKTUELLELUFTFEUCHTE=String(AKTUELLELUFTFEUCHTE, 2);
        TEMPAKTUELLELUFTFEUCHTE.replace(".",",");

        HTMLSite ="<!DOCTYPE html><html><head><meta http-equiv='refresh' content='5'><title>";
        HTMLSite += SENSORSSID.c_str();
        HTMLSite += "</title>";
        HTMLSite += "</head><body style='font-family:Verdana, Arial, Sans-Serif'>
<center>";
        HTMLSite += SENSORSSID.c_str();
        HTMLSite += "<fieldset style='width:350px'><legend>Sensor ";
        HTMLSite += SENSORSTANDORT.c_str();
        HTMLSite += "</legend>";
        HTMLSite += "<u>Aktuelle Sensorwerte</u>";
        HTMLSite += "Temperatur: ";
        HTMLSite += TEMPAKTUELLETEMPERATUR;
        HTMLSite += " &deg;C";
        HTMLSite += "Luftfeuchte: ";
        HTMLSite += TEMPAKTUELLELUFTFEUCHTE;
        HTMLSite += " %<hr />";
        HTMLSite += "Systemspannung: ";
        HTMLSite += String(ESP.getVcc()).substring(0,1);
        HTMLSite += ",";
        HTMLSite += String(ESP.getVcc()).substring(1);
        HTMLSite += " Volt";
        HTMLSite += "</fieldset><fieldset style='width:350px'><form action='sensorinfo.htm'><input type='submit' value='Sensor Informationen'></form>";
        HTMLSite += "<form action='netinfo.htm'><input type='submit' value='WLAN Netzwerk Informationen'></form>";
        HTMLSite += "<form action='prginfo.htm'><input type='submit' value='Programm Informationen'></form>";
        HTMLSite += "</fieldset></center></body></html>\r\n\r\n";
      } else if (HTMLSite=="") {
        step=1;
        
        Serial.println(F("Setup Startseite wird ausgegeben"));
        Serial.println(F(""));

        HTMLSite ="<!DOCTYPE html><html><head><title>";
        HTMLSite += SENSORSSID.c_str();
        HTMLSite += "</title>";
        HTMLSite += "</head><body style='font-family:Verdana, Arial, Sans-Serif'><center>";
        HTMLSite += SENSORSSID.c_str();
        HTMLSite += "<fieldset style='width:450px'>";
        HTMLSite += "<b>Herzlich Willkommen zum Setup";
        HTMLSite += "des ESP8266 DHT-22 Akku Sensors.";
        HTMLSite += "Sie werden jetzt Schritt f&uuml;r Schritt";
        HTMLSite += "durch das Setup gef&uuml;hrt.</fieldset>";
        HTMLSite += "<form method='GET' action='wlanconfig.htm'>";
        HTMLSite += "<input type='submit' value='Weiter zu Schritt 1...'></form>";
        HTMLSite += "</center></body></html>\r\n\r\n";
      }
          
      if (RequestString.startsWith("/favicon")) {  
        HTMLHeader  = "HTTP/1.1 403 FORBIDDEN\r\n";
        HTMLHeader += "Connection: close\r\n";
        HTMLHeader += "\r\n";
      } else {
        HTMLHeader  = "HTTP/1.1 200 OK\r\n";
        HTMLHeader += "Content-Length: ";
        HTMLHeader += HTMLSite.length();
        HTMLHeader += "\r\n";
        HTMLHeader += "Content-Type: text/html\r\n";
        HTMLHeader += "Connection: close\r\n";
        HTMLHeader += "\r\n";
      }
      
      client.print(HTMLHeader);
      delay(100);
      client.print(HTMLSite);
      delay(100);
      
      client.stop();
    }
  }

  delay(100);
}

Bevor ich nun den Programmcode erkläre vorab ein paar Worte zur Inbetriebnahme.

Ich bin mir sicher einige werden, ohne erst viel zu lesen, den Code direkt ausprobieren wollen 🙂

Wenn man die Software auf den ESP8266 übertragen hat startet dieser in einem Setup Modus, dies bedeutet das er einen Access Point mit der SSID ESP8266-DHT22-SENSOR-SETUP bereit stellt.

Dieser AP ist offen und man kann sich direkt mit ihm verbinden.

Ruft man jetzt in einem Webbrowser die IP 192.168.4.1 auf so erscheint die erste Seite eines kleinen Konfigurations-Wizzards.

Sensor_setup_Einstiegsseite-300x175 ESP8266 AM2302 (DHT22) Sensor für Akkubetrieb, ein Projekt zum Mitmachen! (3-1)
Jetzt klickt man einfach auf „Weiter zu Schritt 1…“ und landet auf der folgenden Seite.

Sensor_Setup_Schritt1-300x269 ESP8266 AM2302 (DHT22) Sensor für Akkubetrieb, ein Projekt zum Mitmachen! (3-1)
Die angezeigten WLANs werden natürlich abweichen. Also wählt man hier einfach sein heimisches WLAN aus und gibt ggf. das benötigte Passwort an, die Anzeige des Passwortes erfolgt sichtbar.

Nun kann man noch eine Zeit für das Verbindungstimeout wählen, dies ist die Zeit nach der der Sensor neu gestartet wird wenn keine Verbindung hergestellt werden kann.

Wichtig !
Das Programm ist so geschrieben das der Sensor automatisch wieder in den Setup Modus startet wenn X mal in Folge keine Verbindung mit dem gewählten Netzwerk hergestellt werden kann.

Diese Anzahl X kann nur direkt im Programm über die Variable MAXCONNECTIONTRIES geändert werden.
Klickt man jetzt auf „Einstellungen speichern und weiter zu Schritt 2…“ kommt man auf die folgende Seite.

Sensor_Setup_Schritt2-300x276 ESP8266 AM2302 (DHT22) Sensor für Akkubetrieb, ein Projekt zum Mitmachen! (3-1)

Hier kann man nun die Art der IP-Adresszuweisung einstellen, in der Regel teilt ein WLAN-Router (eigentlich ja Access Point) einem sich verbindenden Gerät die IP-Adresse per DHCP zu, wir können aber auch eine feste IP-Adresse vergeben indem wir auf Statisch umstellen und dann die benötigten Daten eingeben.

Hat man alles eingestellt so klickt man auf „Einstellungen speichern und weiter zu Schritt 3…“ und landet hier.

Sensor_Setup_Schritt3-300x220 ESP8266 AM2302 (DHT22) Sensor für Akkubetrieb, ein Projekt zum Mitmachen! (3-1)
Auf dieser Seite kann man nun die Daten eingeben die benötigt werden um unsere Sensordaten an den Thingspeak Channel zu übertragen. Je nach dem ob man dies wünscht oder nicht kann diese Übertragung hier aktiviert oder deaktiviert werden.

Ein Klick auf „Einstellungen speichern und weiter zu Schritt 4…“ bringt uns nun auf die letzte Konfigurationsseite.

Sensor_Setup_Schritt4-300x223 ESP8266 AM2302 (DHT22) Sensor für Akkubetrieb, ein Projekt zum Mitmachen! (3-1)

Als Informationen kann man hier einen Standortbezeichner für den Sensor vergeben, z.B. Küche oder Keller etc.

Wichtig sind die folgenden Angaben um auf den Sensor über sein aufgespanntes WLAN zuzugreifen. Zu beachten ist das man bei der SSID und dem Passwort KEINE Leerzeichen oder Sonderzeichen eingibt, dafür ist diese Software (noch) nicht ausgelegt.

Gibt man hier kein Passwort an so ist das Sensor NEtzwerk offen, ist ja auch nicht schlimm da man darüber keine bösen Dinge machen kann und ob nun der liebe Nachbar mal sieht wie die Temperatur in meiner Küche ist….. na wenn er Spaß daran hat 🙂

Klickt man nun auf „Einstellungen speichern und das Setup beenden“ erhalten wir abschließend eine kurze Meldung und der Sensor startet in den Normal Modus.

Sensor_Setup_Ende-300x132 ESP8266 AM2302 (DHT22) Sensor für Akkubetrieb, ein Projekt zum Mitmachen! (3-1)Geschafft !

Unser Sensor sollte nun starten, sein WLAN bereit stellen und uns wenn gewünscht die Daten an den Thingspeak Channel übertragen. Man kann die Bootmeldungen und Webbrowser Anfragen live über die Serielle Schnittstelle mitverfolgen wenn man wünscht.

Noch ein paar Worte zur grünen LED auf dem Sensorboard.

Sie signalisiert einige Zustände des Sensors. Zum einen blinkt sie kurz wenn eine Messung durchgeführt wird und zum anderen leuchtet sie schwach wenn Daten an Thingspeak übertragen werden.

Befindet man sich im Setup Modus leuchtet die solange LED hell.

Alle Programme kann man sich in einem ZIP-Archiv unten Downloaden.


So und nun fange ich mal an das 1. Programm Stück für Stück zu erklären.

Wie man oben im Programm schon sieht, da ist eine Aufteilung der Speicherplätze im EEPROM zu sehen, nutzen wir jetzt die Möglichkeit unsere Konfiguration im EEPROM zu speichern. Dazu binden wir jetzt eine weitere Library ein.

#include <EEPROM.h>

Die restlichen Variablen und Konstanten habe ich auch direkt im Programm erklärt, weiteres ergibt sich jetzt nach und nach.

Ich erkläre den Code nicht von oben nach unten sondern in der Reihenfolge wie er abläuft.

Starten wir also mit dem Bereich setup.

Zuerst wird die serielle Schnittstelle konfiguriert und uns eine Startmeldung ausgegeben, direkt im Anschluss machen wir etwas sehr wichtiges, wir kontrollieren die Systemspannung.

  Serial.begin(115200);

  Serial.println(F(""));  
  Serial.println(F(""));  
  Serial.println(F("Starte den ESP8266-DHT22-SENSOR..."));
  Serial.println(F(""));

  Serial.println(F("Teste Systemspannung..."));
  Serial.println(F(""));

  if (ESP.getVcc() <= SHUTDOWNVCC) {
      Serial.println(F("!!! Systemspannung zu niedrig, schalte Sensor ab !!!"));
      Serial.println(F(""));

      delay(100);
      
      ESP.deepSleep(0,WAKE_RF_DISABLED);
      delay(100);
  }
  
  Serial.print(String(ESP.getVcc()).substring(0,1));
  Serial.print(F(","));
  Serial.print(String(ESP.getVcc()).substring(1));
  Serial.println(F(" Volt ist OK"));
  Serial.println(F(""));

Ist die Systemspannung zu gering, also unser Akku fast leer, so geben wir eine Meldung aus und schalten das System ab. Dazu versetzen wir es einfach in einen endlosen Deep-Sleep. Der jetzt noch fliessende Strom sollte so gering sein das man genug Zeit hat den Akku wieder zu laden bevor er kaputt gehen kann.

Hier noch einmal mein Rat, nutzt einen Akku (eine Zelle) mit integrierter Schutzschaltung!

Weiter geht es mit der Konfiguration der GPIOs. Dies sollte eigentlich selbsterklärend sein.

Wichtig ist nur das wir den GPIO wo der Reset-Taster, bzw. Jumper, dran hängt mit aktiviertem PULL_UP Widerstand konfigurieren.

Wir schalten gegen GND und wenn wir den Taster loslassen, oder den Jumper abziehen, würde sonst kein HIGH erkannt werden weil der Pin offen floaten würde.

  pinMode(RESETPIN, INPUT_PULLUP);
  pinMode(LEDPIN, OUTPUT);
  pinMode(DHTPOWERPIN, OUTPUT);

Nun kommt etwas Neues, wir haben in den Testprogrammen uns hier die Systemkonfiguration anzeigen lassen, dies machen wir auch haben aber die Funktion zur Ausgabe der Daten in eine eigene Routine namens ShowSysInfo gepackt.

  ShowSysInfo(1);

Hier die Routine selber.

void ShowSysInfo(int typ) {
  if (typ==1) {
    Serial.print(F("SDK-Version: "));
    Serial.println(ESP.getSdkVersion());
    Serial.print(F("ESP8266 Chip-ID: "));
    Serial.println(ESP.getChipId());
    Serial.print(F("ESP8266 Speed: "));  
    Serial.print(ESP.getCpuFreqMHz());
    Serial.println(F(" MHz"));
  }
  
  Serial.print(F("Free Heap Size: "));
  Serial.print(ESP.getFreeHeap());
  Serial.println(F(" Bytes"));
  Serial.print(F("Systemspannung: "));
  Serial.print(String(ESP.getVcc()).substring(0,1));
  Serial.print(F(","));
  Serial.print(String(ESP.getVcc()).substring(1));
  Serial.println(F(" Volt"));  
  Serial.println(F(""));
}

Der Routine muss man einen Wert (0 oder 1) übergeben um eine kurze oder ausführliche Ausgabe zu erhalten.

Nun wird die Meldung ausgegeben das die Konfigurationsdaten geladen werden, dies erfolgt auch in einer neuen Routine mit dem Namen ReadEEPROMConfig.

  Serial.println(F("Hole Konfiguration aus EEPROM..."));
  Serial.println(F(""));

  ReadEEPROMConfig();

Die Routine selber sieht wie folgt aus.

void ReadEEPROMConfig() {
  EEPROM.begin(512);

  EEPROM.get(0,FIRSTSTARTFLAG);
  
  Serial.print(F("FIRSTSTARTFLAG="));
  Serial.println(FIRSTSTARTFLAG);
  
  EEPROM.get(1,UPDATEINTERVAL);

  Serial.print(F("UPDATEINTERVAL="));
  Serial.println(UPDATEINTERVAL);

  EEPROM.get(2,CONNECTIONTIMEOUT);

  Serial.print(F("CONNECTIONTIMEOUT="));
  Serial.println(CONNECTIONTIMEOUT);

  EEPROM.get(3,TIMEOUTFLAG);

  Serial.print(F("TIMEOUTFLAG="));
  Serial.println(TIMEOUTFLAG);

  EEPROM.get(4,STATICIP);

  Serial.print(F("STATICIP="));
  Serial.println(STATICIP);

  ip[0]=EEPROM.read(5);
  ip[1]=EEPROM.read(6);
  ip[2]=EEPROM.read(7);
  ip[3]=EEPROM.read(8);
  
  gw[0]=EEPROM.read(9);
  gw[1]=EEPROM.read(10);
  gw[2]=EEPROM.read(11);
  gw[3]=EEPROM.read(12);
  
  sub[0]=EEPROM.read(13);
  sub[1]=EEPROM.read(14);
  sub[2]=EEPROM.read(15);
  sub[3]=EEPROM.read(16);

  dns[0]=EEPROM.read(17);
  dns[1]=EEPROM.read(18);
  dns[2]=EEPROM.read(19);
  dns[3]=EEPROM.read(20);

  Serial.print(F("IP="));
  Serial.println(ip);
  
  Serial.print(F("GATEWAY="));
  Serial.println(gw);
  
  Serial.print(F("SUBNET="));
  Serial.println(sub);
  
  Serial.print(F("DNS="));
  Serial.println(dns);
  
  WLANSSID="";
  
  for (int i = 21; i < 53; ++i)
  {
    WLANSSID += char(EEPROM.read(i));
  }

  Serial.print(F("WLANSSID="));
  Serial.println(WLANSSID.c_str());

  WLANPWD="";
  
  for (int i = 53; i < 117; ++i)
  {
    WLANPWD += char(EEPROM.read(i));
  }
  
  Serial.print(F("WLANPWD="));
  Serial.println(WLANPWD.c_str());

  SENSORSSID="";

  for (int i = 117; i < 149; ++i)
  {
    SENSORSSID += char(EEPROM.read(i));
  }
  
  Serial.print(F("SENSORSSID="));
  Serial.println(SENSORSSID.c_str());

  SENSORPWD="";

  for (int i = 149; i < 213; ++i)
  {
    SENSORPWD += char(EEPROM.read(i));
  }

  Serial.print(F("SENSORPWD="));
  Serial.println(SENSORPWD.c_str());

  SENSORSTANDORT="";

  for (int i = 213; i < 238; ++i)
  {
    SENSORSTANDORT += char(EEPROM.read(i));
  }

  Serial.print(F("SENSORSTANDORT="));
  Serial.println(SENSORSTANDORT.c_str());

  EEPROM.get(238, THINGSPEAKAKTIV);
  
  Serial.print(F("THINGSPEAKAKTIV="));
  Serial.println(THINGSPEAKAKTIV);

  THINGSPEAKAPIKEY="";

  for (int i = 239; i < 256; ++i)
  {
    THINGSPEAKAPIKEY += char(EEPROM.read(i));
  }

  Serial.print(F("THINGSPEAKAPIKEY="));
  Serial.println(THINGSPEAKAPIKEY.c_str());

  EEPROM.end();
}

Was passiert nun in dieser Routine?

Zuerst starten wir die „Kommunikation“ mit dem EEPROM. Wir geben dabei an das 512 Byte genutzt werden sollen.

  EEPROM.begin(512);

Jetzt laden wir uns die Daten aus dem EEPROM nach und nach in unsere Variablen und geben dies über die serielle Schnittstelle, zur Kontrolle, mit aus.

Die Zuweisung der Werte aus dem EEPROM zu den Variablen ist eigentlich selbsterklärend, nur einen Punkt möchte ich besonders erwähnen.

  ip[0]=EEPROM.read(5);
  ip[1]=EEPROM.read(6);
  ip[2]=EEPROM.read(7);
  ip[3]=EEPROM.read(8);
  
  gw[0]=EEPROM.read(9);
  gw[1]=EEPROM.read(10);
  gw[2]=EEPROM.read(11);
  gw[3]=EEPROM.read(12);
  
  sub[0]=EEPROM.read(13);
  sub[1]=EEPROM.read(14);
  sub[2]=EEPROM.read(15);
  sub[3]=EEPROM.read(16);

  dns[0]=EEPROM.read(17);
  dns[1]=EEPROM.read(18);
  dns[2]=EEPROM.read(19);
  dns[3]=EEPROM.read(20);

  Serial.print(F("IP="));
  Serial.println(ip);
  
  Serial.print(F("GATEWAY="));
  Serial.println(gw);
  
  Serial.print(F("SUBNET="));
  Serial.println(sub);
  
  Serial.print(F("DNS="));
  Serial.println(dns);

Hier weisen wir den einzelnen „Plätzen“ in den Arrays für die IP-Adresse, dem Gateway, der Subnet Mask und des DNS-Servers einzeln Werte zu.

So kommen wir ohne große Probleme mit 4 Byte im EEPROM für jede Adresse aus und können im weiteren auf die einzelnen Teile der Adressen zugreifen.

Auch andere Funktionen, z.B. für den Verbindungsaufbau, benötigen die Adressen als Array.

Andere Werte belegen auch mehr als ein Byte im EEPROM, wir laden einfach die einzelnen Bytes in einer Schleife und „bauen“ uns so den endgültigen Wert der Variablen zusammen.

Hier ein Beispiel.

  WLANSSID="";
  
  for (int i = 21; i < 53; ++i)
  {
    WLANSSID += char(EEPROM.read(i));
  }

Sehr gut kann man hier wieder die Zuordnung der Variablen zu der Tabelle oben im Programm erkennen.

Sind wir fertig, und sind alle Werte geladen, beenden wir die Kommunikation mit dem EEPROM.

  EEPROM.end();

Weiter geht es im Ablauf mit folgenden Zeilen.

  float TEMPTEMPERATUR1=0;
  float TEMPLUFTFEUCHTE1=0;
  float TEMPTEMPERATUR2=0;
  float TEMPLUFTFEUCHTE2=0;
  
  if (FIRSTSTARTFLAG==111) {
    digitalWrite(DHTPOWERPIN, 1);
  
    Serial.println(F(""));
    Serial.println(F("Sensorkalibrierung gestartet..."));
    Serial.println(F(""));
  
    for (int i=1; i<=5; i++) {
      delay(2000);
      
      GetSensorData();
      
      ShowSensorData();
  
      TEMPTEMPERATUR1+=AKTUELLETEMPERATUR;
      TEMPLUFTFEUCHTE1+=AKTUELLELUFTFEUCHTE;  
    }
  
    TEMPTEMPERATUR1/=5;
    TEMPLUFTFEUCHTE1/=5;
  
    Serial.print(F("Durchschnittliche Luftfeuchte: "));
    Serial.print(TEMPLUFTFEUCHTE1);
    Serial.println(F(" %"));
    Serial.print(F("Durchschnittliche Temperatur: "));
    Serial.print(TEMPTEMPERATUR1);
    Serial.println(F(" *C"));
  }

Hier werden ein paar Hilfsvariablen definiert und dann kommt eine neue Zeile die erklärt werden muss.

  if (FIRSTSTARTFLAG==111) {

Die Variable FIRSTSTARTFLAG haben wir uns aus dem EEPROM geholt, ist der Sensor nicht konfiguriert oder haben wir diese Variable im EEPROM gezielt auf 0 gesetzt wird der nachfolgende Teil des Programmes nicht ausgeführt sondern es geht mit dem Code nach dieser IF Abfrage weiter.

Wir entscheiden über dieses „Flag“ also ob wir normal starten oder in den Setup-Modus booten.

Gehen wir also jetzt davon aus das der Sensor neu mit der Software bespielt wurde und zum ersten Mal startet.

Die Variable hat also einen Wert ungleich 111.

Es geht jetzt hier weiter.

  Serial.println(F(""));
  Serial.println(F("WLAN-Netzwerk-Scan gestartet..."));
      
  WiFi.mode(WIFI_STA);
  WiFi.disconnect();

  int n = WiFi.scanNetworks();
    
  Serial.println(F("WLAN-Netzwerk-Scan abgeschlossen..."));
  Serial.println(F(""));

  if (n == 0) {
    Serial.println(F("Kein WLAN-Netzwerk gefunden!"));
  } else {
    Serial.print(n);

    if(n<=1) {
     Serial.println(F(" WLAN-Netzwerk gefunden"));
    } else {
      Serial.println(F(" WLAN-Netzwerke gefunden"));
    }
  
    Serial.println(F(""));

    for (int i = 0; i < n; ++i) { 
      Serial.print(i + 1);
      Serial.print(F(": "));
      Serial.print(WiFi.SSID(i));
      Serial.print(F(" ("));
      Serial.print(WiFi.RSSI(i));
      Serial.print(F(")"));
      Serial.println((WiFi.encryptionType(i) == ENC_TYPE_NONE)?" ":"*");
    }
  }

  HTMLFORMULARWLAN = "<b><u>WLAN-Netzwerk ausw&auml;hlen:</u></b>

";

  for (int i = 0; i < n; ++i) {
    // Erstelle Webseite mit allen SSID und RSSI Werten der gefundenen Netzwerke
    HTMLFORMULARWLAN += "<input type='radio' name='WLANSSID' value='"; HTMLFORMULARWLAN += WiFi.SSID(i); HTMLFORMULARWLAN += "'"; if (WiFi.SSID(i)==WLANSSID.substring(0, WiFi.SSID(i).length()+1)) { HTMLFORMULARWLAN += " checked"; } HTMLFORMULARWLAN += ">";
    HTMLFORMULARWLAN += WiFi.SSID(i);
    HTMLFORMULARWLAN += " (";
    HTMLFORMULARWLAN += WiFi.RSSI(i);
    HTMLFORMULARWLAN += ")";
    HTMLFORMULARWLAN += (WiFi.encryptionType(i) == ENC_TYPE_NONE)?" ":"*";
    HTMLFORMULARWLAN += "
";
  }

Dieser Code ist zum Teil schon aus der Testsoftware bekannt, er dient dazu die WLAN Netzwerke in Reichweite zu finden und anzuzeigen.

Neu ist das wir uns hier gleich ein Formular zusammen basteln welches wir später für die Konfiguration über den Webbrowser benötigen.

Es wird nichts weiter als ein Teil einer HTML Seite erzeugt und in der Variablen HTMLFORMULARWLAN abgelegt.

Nun folgt dieser Code.

  dht.begin();

  if (FIRSTSTARTFLAG==111) {

Wir kennen bereits den Start des DHT Sensors, wir machen dies hier egal ob wir ihn benötigen oder nicht. Der Sensor wird hierbei noch nicht
abgefragt, es werden lediglich Konfigurationen durchgeführt.

Und nun kommt wieder eine Abfrage die unser FIRSTSTARTFLAG nutzt, nur wenn wir normal starten soll der nachfolgende Code ausgeführt werden.

Es wird dann die Verbindung zu unserem WLAN hergestellt, dies geht natürlich nicht wenn der Sensor noch nicht konfiguriert ist, daher diese Abfrage.

Nehmen wir also weiter an das der Sensor erstmalig gestartet wurde, oder wir ihn neu konfigurieren wollen (wie man das erreicht folgt später).

Wir landen also in folgendem Teil der IF-Abfrage.

  } else {
    digitalWrite(LEDPIN ,1);
    
    String SENSORSSIDSETUP = "ESP8266-DHT22-SENSOR-SETUP";
    SENSORPWD = "";
    FIRSTSTARTFLAG=1;
    
    Serial.println(F("Starte im Setup-Modus!!!"));
    WiFi.softAP(SENSORSSIDSETUP.c_str(), SENSORPWD.c_str());
  
    delay(100);
    
    Serial.println(F(""));
    Serial.println(F("AP Modus gestartet"));
    Serial.print(F("SSID: "));
    Serial.println(SENSORSSIDSETUP.c_str());
    Serial.print(F("AP IP-Adresse: "));
    Serial.println(WiFi.softAPIP());
  } 

Um optisch anzuzeigen das wir uns im Setup-Modus befindewn aktivieren wir die grüne LED.

Jetzt erstellen wir uns eine Variable für die SSID des Konfigurations-WLAN das uns der Sensor als Access-Point bereit stellen soll.

Ich habe hier sinnvoller Weise SETUP mit in die Bezeichnung aufgenommen 🙂

Um ein offenes WLAN zu bekommen darf kein Passwort für selbiges vergeben sein, wir setzen die Variable als auf einen leeren String und starten den Access-Point Modus des ESP8266.

    SENSORPWD = "";
    FIRSTSTARTFLAG=1;
    
    Serial.println(F("Starte im Setup-Modus!!!"));
    WiFi.softAP(SENSORSSIDSETUP.c_str(), SENSORPWD.c_str());

Wie man sieht haben wir hier unser Flag für den Startmodus, FIRSTSTARTFLAG, verändert. Wir benötigen diesen Wert später bei der Konfiguration über den Webbrowser.

Nach einer kurzen Wartezeit, damit der ESP8266 den AP-modus starten kann, lassen wir uns noch einmal die SSID und die IP-Adresse ausgeben.

In der Regel ist die IP-Adresse die 192.168.4.1, wir haben und werden sie für die Setup-Funktion nicht ändern.

    delay(100);
    
    Serial.println(F(""));
    Serial.println(F("AP Modus gestartet"));
    Serial.print(F("SSID: "));
    Serial.println(SENSORSSIDSETUP.c_str());
    Serial.print(F("AP IP-Adresse: "));
    Serial.println(WiFi.softAPIP());

Zu guter letzt starten wir nun einen Serverdienst damit wir unseren Sensor über einen Webbrowser erreichen können, dies geben wir auch gleich als Meldung aus.

[copde lang=“cpp“]
Serial.println(F(„“));
Serial.println(F(„Starte Server“));

server.begin();

Serial.println(F(„Server gestartet“));
Serial.println(F(„“));

Serial.println(F(„…ESP8266-DHT22-SENSOR erfolgreich gestartet.“));
Serial.println(F(„“));
[/code]

Jetzt belegen wir noch zwei Variablen mit später benötigten Werten.

  STARTZEITPUNKT=0;
  THINGSPEAKUPDATEINTERVAL=UPDATEINTERVAL*60000;

So das war der Start in den Setup-Modus. Schauen wir jetzt was passiert wenn wir nun in der Hauptprogrammschleife loop weiter machen.

  unsigned long ISTZEITPUNKT=millis();
  
  //Wenn Systemspannung zu gering System abschalten
  if (ESP.getVcc() <= SHUTDOWNVCC) {
    Serial.println(F("Systemspannung zu gering, System wird abgeschaltet..."));
    Serial.println(F(""));  

    delay(100);
    
    ESP.deepSleep(0, WAKE_RF_DISABLED);
    delay(100);
  }

Wir weisen einer Variablen immer die aktuell vergangene Zeit aus der Funktion millis() zu, diesen Wert benötigen wir später wenn der Sensor in Funktion ist, also Daten übertragen soll.

Nachfolgend sehen wir im Codeteil oben wieder die Kontrolle der Systemspannung, dies wird jetzt bei jedem Durchlauf der Schleife gemacht um den Sensor abschalten zu können wenn der Akku leer werden sollte wärend das System im Setup-Modus ist.

Nachfolgender Code wird nur dann ausgeführt wenn der Sensor im Normal-Modus läuft. Er macht nichts weiter als alle 2 Sekunden eine Messungs einzuleiten und wenn die ThingsSpeak-Übertragung aktiv ist diese wenn fällig zu starten.

  if (FIRSTSTARTFLAG == 111) {
    //Ist es an der Zeit zu messen?
    if ((unsigned long)(ISTZEITPUNKT-STARTZEITPUNKTMESSUNG) >= 2000) {
      GetSensorData();
      ShowSensorData();
    
      STARTZEITPUNKTMESSUNG=ISTZEITPUNKT;
    } else if (THINGSPEAKAKTIV == 1) {
      //Ist es an der Zeit Daten an Thingspeak zu senden?
      if ((unsigned long)(ISTZEITPUNKT-STARTZEITPUNKTTS) >= THINGSPEAKUPDATEINTERVAL) {
        SendSensorData();
        STARTZEITPUNKTTS=ISTZEITPUNKT;
      }
    }
  }

Weiter geht es jetzt an dieser Stelle.

  if (digitalRead(RESETPIN)==0) {
    digitalWrite(LEDPIN, 1);
    
    delay(500);
    
    while (digitalRead(RESETPIN)==0) {
      delay(100);
    }

    digitalWrite(LEDPIN, 0);

    delay(500);
    
    ResetWiFi();
  }

Auch dieser Code wird bei jedem Durchlauf ausgeführt, er schaut ob wir den WiFI-RESET-Taster gedrückt haben oder der Jumper gesetzt ist.

Ist dies der Fall wird zur Entprellung der tasters kurz gewartet und sobald dieser losgelassen wird springen wir in die Routine ResetWiFi. Dies ist an dieser Stelle, wir gehen ja davon aus das wir den Sensor schon im Setup-Modus gestartet haben sinnfrei weil wir kaum den Taster drücken um den Sensor zurück zu setzen wenn wir schon in der Konfiguration sind.

Er wird aber auch ausgeführt wenn wir uns später im Normalmodus befinden, also kann man so den Sensor immer wieder dazu bringen in den Setup-Modus zu booten.

Jetzt aber weiter im Code. Nachfolgend schauen wir nun bei jedem Durchlauf ob sich ein Client, ein Webbrowser, mit einer Anfrage an den Sensor gewendet hat.

  WiFiClient client = server.available();

  if(client) {
    while(client.connected() && !client.available()){
      delay(1);
    }

Ist dies der Fall warten wir bis die Verbindung korrekt aufgebaut ist.

Nun schauen wir uns die übertragenen Daten an. Dazu weisen wir diese Daten bis zum ersten \r einer Variablen zu.

    String RequestString = client.readStringUntil('\r');

Um zu schauen ob es sich um eine gültige Anfrage handelt schauen wir im erhaltenen String nach ob einige Voraussetzungen erfüllt sind, wenn nicht ist die Anfrage ungültig und wir beeden die Verbindung mit dem Client.

    int addr_start = RequestString.indexOf(' ');
    int addr_end = RequestString.indexOf(' ', addr_start + 1);

    if (addr_start == -1 || addr_end == -1) {
      Serial.print(F("Ungueltige Anfrage: "));
      Serial.println(RequestString);
      Serial.println(F(""));
      
      client.stop();

Da bei der Anfrage an uns in der Regel ein HTTP Header übertragen wird müssen sich mindestens zwei Leerzeichen im String befinden, nur dann ist die Anfrage gültig.

Bei einer gültigen Anfrage landen wir hier.

    } else {
      RequestString = RequestString.substring(addr_start + 1, addr_end);

      Serial.print(F("Gueltige Anfrage: "));
      Serial.println(RequestString);
      Serial.println(F(""));

Nun definieren wir uns ein paar Hilfsvariaben die unsere zu übertragene Webseite und den HTTP-Header aufnehmen.

      String HTMLSite="";
      String HTMLHeader="";

Jetzt müssen wir einen Sprung nach weiter unten im Programm machen da alle anderen Teile aufgrund unseres FIRSTSTARTFLAG=1 (siehe oben) übersprungen werden.

Egal welche URL wir im Browser aufrufen wir landen immer hier.

      } else if (HTMLSite=="") {
        step=1;
        
        Serial.println(F("Setup Startseite wird ausgegeben"));
        Serial.println(F(""));

        HTMLSite ="<!DOCTYPE html><html><head><title>";
        HTMLSite += SENSORSSID.c_str();
        HTMLSite += "</title>";
        HTMLSite += "</head><body style='font-family:Verdana, Arial, Sans-Serif'><center>";
        HTMLSite += SENSORSSID.c_str();
        HTMLSite += "<fieldset style='width:450px'>";
        HTMLSite += "<b>Herzlich Willkommen zum Setup";
        HTMLSite += "des ESP8266 DHT-22 Akku Sensors.";
        HTMLSite += "Sie werden jetzt Schritt f&uuml;r Schritt";
        HTMLSite += "durch das Setup gef&uuml;hrt.</fieldset>";
        HTMLSite += "<form method='GET' action='wlanconfig.htm'>";
        HTMLSite += "<input type='submit' value='Weiter zu Schritt 1...'></form>";
        HTMLSite += "</center></body></html>\r\n\r\n";
      }

Kurz erklärt, unsere Variable HTMLSite ist hier auf jeden Fall leer und wir erzeugen nun die erste Seite unseres Setup-Wizzards.

      if (RequestString.startsWith("/favicon")) {  
        HTMLHeader  = "HTTP/1.1 403 FORBIDDEN\r\n";
        HTMLHeader += "Connection: close\r\n";
        HTMLHeader += "\r\n";
      } else {
        HTMLHeader  = "HTTP/1.1 200 OK\r\n";
        HTMLHeader += "Content-Length: ";
        HTMLHeader += HTMLSite.length();
        HTMLHeader += "\r\n";
        HTMLHeader += "Content-Type: text/html\r\n";
        HTMLHeader += "Connection: close\r\n";
        HTMLHeader += "\r\n";
      }

Jetzt bauen wir uns noch einen HTTP-Header zusammen um eine gültige Webseite an den Client zurück zu liefern.

Achtung !!!
Einige Webbrowser fragen immer wieder ein Favicon an, um dies zu verhindern senden wir in diesem Fall einen Header zurück der dies verbietet.

Haben wir nun unsere Webseite und den HTTP-Header zusammen gebaut senden wir diese an den Client zurück und beenden dann die Verbindung.

      client.print(HTMLHeader);
      delay(100);
      client.print(HTMLSite);
      delay(100);
      
      client.stop();

Unsere Webseite sieht im Browser dann so aus.

Sensor_setup_Einstiegsseite-300x175 ESP8266 AM2302 (DHT22) Sensor für Akkubetrieb, ein Projekt zum Mitmachen! (3-1)
Was jetzt kommt ist klar, man drückt im Browser auf den Button „Weiter zu Schritt 1…“ und in unserer Programmschleife geht der Ablauf mit einer neuen Anfrage weiter.

Doch diesmal landen wir hier.

      if (RequestString.startsWith("/wlanconfig.htm") || step==1) {

Warum?

Weil unsere Client-Anfrage den Teil „/wlanconfig.htm“ im Header beinhaltet und zum Anderen weil wir bei der Erstellung unserer Setup-Startseite die Variable step=1 gesetzt haben..

Wir reagieren also auf die angefragte URL und fangen an unsere Setup-Schritte abzuarbeiten.

An den Browser senden wir jetzt die Webseite passend zur Anfrage.

        Serial.println(F("WLAN Konfigurationsseite wird ausgegeben"));
        Serial.println(F(""));

        HTMLSite ="<!DOCTYPE html><html><head><title>";
        HTMLSite += SENSORSSID.c_str();
        HTMLSite += "</title>";
        HTMLSite += "</head><body style='font-family:Verdana, Arial, Sans-Serif'><center>";
        HTMLSite += SENSORSSID.c_str();
        HTMLSite += "<fieldset style='width:450px'><legend>Sensor Setup Schritt 1</legend>";
        HTMLSite += "<form method='GET' action='setwlanconfig'>";
        HTMLSite += "<b>WLAN Einstellungen</b><hr />";
        HTMLSite += HTMLFORMULARWLAN;
        HTMLSite += "WLAN-Passwort: <input name='WLANPWD' type='text' size='30' maxlength='64' value='"; HTMLSite += WLANPWD.c_str(); 
        HTMLSite += "'></input>";
        HTMLSite += "Verbindungs-Timeout: ";
        HTMLSite += "<select name='CONNECTIONTIMEOUT' size='1'>";

        if (CONNECTIONTIMEOUT==10) {
          HTMLSite += "<option value='10' selected>10</option><option value='30'>30</option><option value='60'>60</option>";
        } else if (CONNECTIONTIMEOUT==30) {
          HTMLSite += "<option value='10'>10</option><option value='30' selected>30</option><option value='60'>60</option>";
        } else {
          HTMLSite += "<option value='10'>10</option><option value='30'>30</option><option value='60' selected>60</option>";
        }
 
        HTMLSite += "</select> Sekunden";
        HTMLSite += "</fieldset>";
        HTMLSite += "<input type='submit' value='Einstellungen speichern und weiter zu Schritt 2...'></form>";
        HTMLSite += "</center></body></html>\r\n\r\n";
      }

Ich möchte hier jetzt keinen HTML Kurs draus machen, nur soviel zur erzeugten Webseite, es wird ein Formular erzeugt und unsere Werte aus dem EEPROM werden als Vorgabewerte eingetragen. Bei einer späteren, Neukonfiguration, werden also die alten Werte angezeigt und wir können sie so einfach ändern oder bestätigen.

Wird nun folgendes Formular im Webbrowser über einen Klick auf den Button abgesendet…

Sensor_Setup_Schritt1-300x269 ESP8266 AM2302 (DHT22) Sensor für Akkubetrieb, ein Projekt zum Mitmachen! (3-1)

… geht es an dieser Stelle im Code weiter.

      if (RequestString.startsWith("/setwlanconfig?")) {
        FIRSTSTARTFLAG=0;
        step=2;

        EEPROM.begin(512);

        delay(10);
        
        //1. Wert extrahieren (WLAN SSID)
        int StartPosition=RequestString.indexOf('=');
        StartPosition++;
        
        int EndePosition=RequestString.indexOf("&");

        String NeueWLANSSID; 
        NeueWLANSSID = RequestString.substring(StartPosition,EndePosition);

        Serial.println(F(""));
        Serial.println(F("Schreibe neue WLANSSID ins EEPROM:"));
  
        for (int i = 0; i < NeueWLANSSID.length(); ++i){
          EEPROM.write(21+i, NeueWLANSSID[i]);
          
          Serial.print(F("schreibe: "));
          Serial.println(NeueWLANSSID[i]); 
        }    

        //2. Wert extrahieren (Netzwerk Passwort)
        StartPosition=RequestString.indexOf("=",EndePosition);
        StartPosition++;
        
        EndePosition=RequestString.indexOf("&",EndePosition+2);
        
        String NeuesWLANPWD;
        NeuesWLANPWD = RequestString.substring(StartPosition,EndePosition);

        Serial.println(F(""));
        Serial.println(F("Schreibe neues WLANPWD ins EEPROM:"));

        for (int i = 0; i < NeuesWLANPWD.length(); ++i){
          EEPROM.write(53+i, NeuesWLANPWD[i]);
          
          Serial.print(F("schreibe: "));
          Serial.println(NeuesWLANPWD[i]); 
        }    

        //3. Wert extrahieren (CONNECTIONTIMEOUT)
        int NeuesCONNECTIONTIMEOUT=0;
        NeuesCONNECTIONTIMEOUT=RequestString.substring(RequestString.lastIndexOf("=")+1).toInt();

        Serial.println(F(""));
        Serial.print(F("Schreibe neues CONNECTIONTIMEOUT ins EEPROM: "));

        Serial.print(F("schreibe: "));
        Serial.println(NeuesCONNECTIONTIMEOUT);
        
        EEPROM.write(2, NeuesCONNECTIONTIMEOUT);

        EEPROM.commit();
        EEPROM.end();
      }

In obigem Codeteil setzen wir unseren Setup-Wizzard-Schritt-Zähle 🙂 auf den nächsten Schritt, hier 2, weiter und gehen an die Auswertung der erhaltenen Daten.

Es sei angemerkt das ich KEINE Kontrolle auf Plausibilität der Daten eingebaut habe, ein bisschen darf man gerne selber noch hinzufügen.

Da ein abgesendetes Formular (per GET) uns immer eine Anfrage der Form VARIABLE=WERT&VARIABLE=WERT liefert suchen wir nun einfach nach dem ersten = im String und nehmen dessen Position +1 als Start unseres übertragenen Wertes.

Dann suchen wir das dazu gehörende & und setzen das Ende aud diesen Wert -1.

Dies alles geht so weiter bis wir alle Werte unseren Variablen zugeweisen und jeweils im EEPROM gespeichert haben.

Wichtig dabei ist das es so wie ich es mache nur geht weil die Anzahl der erhaltenen Werte durch unser Formular feststeht.

Das Ganze geht jetzt immer so weiter, Webseite mit Formular anzeigen, auswerten und Werte speichern etc. bis wir am Ende unseres Setup-Wizzard ankommen.

Jetzt wird noch eine Abschlussseite angezeigt…

Sensor_Setup_Ende-300x132 ESP8266 AM2302 (DHT22) Sensor für Akkubetrieb, ein Projekt zum Mitmachen! (3-1)

…und der Sensor über den Deep-Sleep Timer neu gestartet.

        WiFi.disconnect();

        ESP.deepSleep(1000,WAKE_RF_DEFAULT); //System neu starten über Deep-Sleep Timer
        delay(100);

So das war nun unser erstes Programm.

Oder NEIN da war doch noch der Ablauf wenn der Sensor schon konfiguriert ist und in den normalen Betriebsmodus startet 🙂

Also zurück auf setup und wir machen hier weiter.

  if (FIRSTSTARTFLAG==111) {
    digitalWrite(DHTPOWERPIN, 1);
  
    Serial.println(F(""));
    Serial.println(F("Sensorkalibrierung gestartet..."));
    Serial.println(F(""));
  
    for (int i=1; i<=5; i++) {
      delay(2000);
      
      GetSensorData();
      
      ShowSensorData();
  
      TEMPTEMPERATUR1+=AKTUELLETEMPERATUR;
      TEMPLUFTFEUCHTE1+=AKTUELLELUFTFEUCHTE;  
    }
  
    TEMPTEMPERATUR1/=5;
    TEMPLUFTFEUCHTE1/=5;

    Serial.print(F("Durchschnittliche Luftfeuchte: "));
    Serial.print(TEMPLUFTFEUCHTE1);
    Serial.println(F(" %"));
    Serial.print(F("Durchschnittliche Temperatur: "));
    Serial.print(TEMPTEMPERATUR1);
    Serial.println(F(" *C"));
  }

Ist der Sensor normal gestartet, also unser FIRSTSTARTFLAG ist 111, so wird der obige Teil im Bereich setup ausgeführt.

Es handelt sich dabei um eine kleine „Kalibrierung“ unserer Messwerte. Es hat sich gezeigt das bei manchen Platinenlayouts die Werte des AM2302 abweichen wenn direkt neben ihm ein Funkmodul sendet. In unserem Fall scheint dies aber nicht so zu sein, aber sicher ist sicher.

Wir werden jetzt einfach 5 Messungen durchführen und aus den Werten einen Mittelwert bilden, gleiches werden nach Aktivierung des WLAN machen.

Aus den Mittelwerten vor und nach Aktivierung bilden wir dann wieder einen Mittelwert und sollten so ziemlich genau auf den richtigen Wert kommen.

Oben im Code sieht man zwei neue Funktionen die wir aufrufen, dies ist zum einen eine Routine die die eigentliche Messung ausführt, GetSensorData(), und zum anderen die Werte über die serielle Schnittstelle ausgibt, ShowSensorData().

Schauen wir uns die Routine zur Sensorabfrage einmal genauer an.

void GetSensorData() {
  digitalWrite(LEDPIN, 1);
  delay(50);
  digitalWrite(LEDPIN, 0);

  int SENSORERRORCOUNT=0;

  AKTUELLELUFTFEUCHTE = dht.readHumidity();
  AKTUELLETEMPERATUR = dht.readTemperature();

  while (isnan(AKTUELLELUFTFEUCHTE) || isnan(AKTUELLETEMPERATUR)) {
    SENSORERRORCOUNT+=1;
    
    digitalWrite(LEDPIN, 1);
    delay(50);
    digitalWrite(LEDPIN, 0);
    
    delay(2450);
    
    AKTUELLELUFTFEUCHTE = dht.readHumidity();
    AKTUELLETEMPERATUR = dht.readTemperature();

    if (SENSORERRORCOUNT >= MAXSENSORERRORCOUNT) {
      Serial.println(F("Zuviele Sensorfehler in Folge, starte Sensor neu..."));
      Serial.println(F(""));
      
      WiFi.disconnect();

      delay (100);
      
      ESP.deepSleep(1, WAKE_RF_DEFAULT);
      delay(100);
    }
  }
  
  AKTUELLELUFTFEUCHTE+=KORREKTURLUFTFEUCHTE;
  AKTUELLETEMPERATUR+=KORREKTURTEMPERATUR;
}

Zu Beginn der Routine lassen wir die grüne LED kurz aufblitzen, dies zeigt uns später auch an das der Sensor aktiv ist.

Nun weisen wir unseren Variablen die aktuellen Werte über die Sensorfunktionen zu, liefert der Sensoir ungültige Daten (nan) an uns zurück
zählen wir eine Variable hoch SENSORERRORCOUNT.

Danach warten wir etwas da der Sensor nur alle ca. 2 Sekunden gültige Werte liefert, etwas länger schadet uns hier nicht, und messen erneut.

Dies wiederholen wir bei erneutem Fehler solange bis unser Fehlerzähler gleich dem MAXSENSORERRORCOUNT Wert ist. Erreichen wir diesen Wert so starten wir den Sensor komplett neu.

Wurden die Werte korrekt abgefragt so haben wir diese jetzt in unseren globalen Variablen vorliegen und machen weiter im jeweiligen Programmteil.

Doch wir machen weiter im Bereich setup. Es folgen nun ein paar Sachen die wir oben schon erklärt haben weil sie in beiden Betriebmodi ausgeführt werden, z.B. die Suche der WLANs.

Uns interessiert jetzt aber der weitere Ablauf beim Start in den Normal-Modus.

  if (FIRSTSTARTFLAG==111) {
    Serial.print(F("Verbinde mit WLAN "));
    Serial.println(WLANSSID);
  
    if (STATICIP==1) {
      WiFi.config(ip, gw, sub, dns);
    }

    WiFi.begin(WLANSSID.c_str(), WLANPWD.c_str());
    
    int WLANTIMEOUT=0;
    
    while (WiFi.status() != WL_CONNECTED) {
      delay(1000);
      Serial.print(F("."));
      WLANTIMEOUT+=1;
  
      if (WLANTIMEOUT>=CONNECTIONTIMEOUT) {
        Serial.println(F(""));
        Serial.println(F("Timeout!"));  
        
        TIMEOUTFLAG+=1;

        if(TIMEOUTFLAG>=MAXCONNECTIONTRIES) {
          ResetWiFi();
        } else {
          EEPROM.begin(512);
          EEPROM.write(3, TIMEOUTFLAG);
          EEPROM.end();

          delay(100);
          
          WiFi.disconnect();

          delay(100);
          
          ESP.deepSleep(1000000,WAKE_RF_DEFAULT);
          delay(100);
        }
      }
    }
  
    EEPROM.begin(512);
    EEPROM.write(3, 0);
    EEPROM.end();

    Serial.println(F(""));
    Serial.println(F("Verbindung mit WLAN hergestellt"));  
    Serial.println(F(""));
    Serial.print(F("IP-Addresse: "));
    Serial.println(WiFi.localIP());
    Serial.println(F(""));
    Serial.println(F("Setze Sensorkalibrierung fort... "));
    Serial.println(F(""));
   
    for (int i=1; i<=5; i++) {
      delay(2000);

      GetSensorData();

      ShowSensorData();
      
      TEMPTEMPERATUR2+=AKTUELLETEMPERATUR;
      TEMPLUFTFEUCHTE2+=AKTUELLELUFTFEUCHTE;  
    }
  
    TEMPTEMPERATUR2/=5;
    TEMPLUFTFEUCHTE2/=5;
  
    Serial.print(F("Durchschnittliche Luftfeuchte: "));
    Serial.print(TEMPLUFTFEUCHTE2);
    Serial.println(F(" %"));
    Serial.print(F("Durchschnittliche Temperatur: "));
    Serial.print(TEMPTEMPERATUR2);
    Serial.println(F(" *C"));
    Serial.println(F(""));
  
    KORREKTURTEMPERATUR=TEMPTEMPERATUR1-TEMPTEMPERATUR2;
    KORREKTURLUFTFEUCHTE=TEMPLUFTFEUCHTE1-TEMPLUFTFEUCHTE2;
    
    Serial.print(F("Luftfeuchte Korrekturwert: "));
    Serial.println(KORREKTURLUFTFEUCHTE);
    Serial.print(F("Temperatur Korrekturwert: "));
    Serial.println(KORREKTURTEMPERATUR);
    Serial.println(F(""));
  
    GetSensorData();
    
    Serial.println(F("Starte im Normal-Modus"));
    WiFi.softAP(SENSORSSID.c_str(), SENSORPWD.c_str());
  
    delay(100);
    
    Serial.println(F(""));
    Serial.println(F("AP Modus gestartet"));
    Serial.print(F("SSID: "));
    Serial.println(SENSORSSID.c_str());
    Serial.print(F("AP IP-Adresse: "));
    Serial.println(WiFi.softAPIP());
    Serial.println(F(""));

    SendSensorData();

Wir bauen jetzt eine Verbindung zum vorgegebenen WLAN auf, haben wir unsere Konfiguration der IP-Adresse auf statisch gesetzt erfolgt jetzt die Konfiguration dafür. Danach wird die Verbindung zum WLAN versucht, bei Überschreitung unserer definierten Timeoutzeit wird der Sensor ggf. einfach neu gestartet.

Diesen Neustart bei Timeout halten wir im EEPROM fest um nach einer maximalen Anzahl an Neustarts direkt wieder in den Setup-Modus booten zu können.

Wurde die Verbindung erfolgreich hergestellt geht es jetzt mit aktivem ESP8266 WiFi weiter mit der Sensorkalibrierung (wie oben beschrieben).

Zu guter letzt wird noch der Access Point eingerichtet damit man sich auch direkt mit dem Sensor verbinden kann, wieder über die IP 192.168.4.1.

Die IP-Adresse im eigenen WLAN richtet sich übrigens danach ob wir eine statische Konfiguration, dann haben wir die IP-Adresse ja vorgegeben, oder eine Zuweisung per DHCP gewählt haben. Bei DHCP sollte unser Sensor eine IP-Adresse vom WLAN-Router bekommen haben, in dessen Infoseiten sollte diese dann erischtlich sein.

Jetzt kommt noch zuletzt der wichtigste Teil unsere Daten müssen ja noch an ThingSpeak übertragen werden, dazu wird wenn es an der Zeit ist folgende Funktion aufgerufen.

SendSensorData();

Der Code dazu sieht so aus.

void SendSensorData() {
  analogWrite(LEDPIN, 100);
  
  GetSensorData();

  Serial.print(F("Verbinde mit "));
  Serial.println(THINGSPEAKHOST);

  WiFiClient client;

  delay(2000);

  if (!client.connect(THINGSPEAKHOST, 80)) {
    Serial.println(F(""));
    Serial.println(F("Verbindung mit Thingspeak-Server fehlgeschlagen!"));
  } else {
    Serial.println(F("Verbindung mit Thingspeak-Server erfolgreich hergestellt"));
    Serial.println(F("Sende Daten an Thingspeak Channel..."));

    String POSTString ="api_key=";
    POSTString += THINGSPEAKAPIKEY.c_str();
    POSTString += "&field1=";
    POSTString += AKTUELLETEMPERATUR;
    POSTString += "&field2=";
    POSTString += AKTUELLELUFTFEUCHTE;
    POSTString += "&field3=";
    POSTString += String(ESP.getVcc()).substring(0,1);
    POSTString += ".";
    POSTString += String(ESP.getVcc()).substring(1);

    client.print(F("POST /update HTTP/1.1\n")); 
    client.print(F("HOST: "));
    client.print(THINGSPEAKHOST);
    client.print(F("\n"));
    client.print(F("X-THINGSPEAKAPIKEY:"));
    client.print(THINGSPEAKAPIKEY.c_str());
    client.print(F("\n"));
    client.print(F("Connection: close\n")); 
    client.print(F("Content-Type: application/x-www-form-urlencoded\n")); 
    client.print(F("Content-Length: "));
    client.print(POSTString.length()); 
    client.print(F("\n\n"));
    client.print(POSTString);

    delay(100);
    
    client.stop();
    
    Serial.println(F("Verbindung zum Server beendet"));
    Serial.println(F("Daten an Thingspeak Channel gesendet"));
  }  

  analogWrite(LEDPIN, 0);
}

Über das Flag THINGSPEAKAKTIV entscheiden wir übrigens im Code ob wir überhaupt senden müssen oder nicht.

Müssen wir senden, so holen wir die aktuellen Sensordaten, bauen eine Verbindung zum ThingSpeak-Server auf und setzen eine Anfrage ab, welche wir in obigen Code, als String erzeugt haben.

Die Anfrage setzt sich wie, wie auch bei den Webseiten, aus einem HTTP-Header und einem Datenteil zusammen.

Um uns optisch anzeigen zu lassen das eine Übertragung gerade aktiv ist lassen wir die grüne LED schwach leuchten.


Heute erweitern wir unser erstes Programm noch etwas weil es müssig ist beim Zugriff auf das Setup, oder wenn man zur Anfrage direkt mit dem WLAN des Sensors verbunden ist, immer die IP-Adresse kennen zu müssen.

Wozu teilt uns der ESP8266 bei der Verbindung sich selber als DNS Server zu (gilt natürlich nur bei DHCP), nutzen wir doch einfach diese Möglichkeit und lösen alle Anfragen zu einer Webseite so auf das wir auf dem Sensor landen.

Um dies zu erreichen sind nur wenige Erweiterungen am Programm notwendig, hier im Einzelnen aufgelistet.

Zuerst binden wir eine weitere Library ein.

#include <DNSServer.h>

Diese bietet uns die Grundfunktionen eines kleinen DNS-Servers. Nun Geben wir als Konstante noch den Port des DNS-Servers an, die ist in der Regel 53.

const int DNSPORT = 53;                            //Der Port unseres DNS-Servers

Nun integrieren wir den DNS-Server in unser Programm….

DNSServer dnsServer;

…und starten ihn wenn der SoftAP gestartet wird.

  Serial.println(F("Starte DNS-Server"));
  
  dnsServer.start(DNSPORT, "*", WiFi.softAPIP());

  Serial.println(F("DNS-Server gestartet")); 

Wir nutzen dabei die IP-Adresse welche wir für den SoftAP erhalten haben.

Zu gutzer letzt müssen wir jetzt noch in unserer Hauptschleife schauen ob eine neue DNS Anfrage vorliegt .

  dnsServer.processNextRequest();

So das war es schon. Verbindet man sich jetzt mit dem WLAN des Sensor und gibt im Browser z.B. www.hallo-sensor.de ein, so landet man direkt auf der Seite des Sensors da unser DNS-Server alle Anfragen mit der IP-Adresse des Sensors beantwortet.

Ein kleiner Minuspunkt soll nicht verschwiegen werden, aktuell kommt dieser DNS-Server nicht mit HTTPS Anfragen klar!

Ich habe alle Versionen im Archiv bereits mit der Funktion des DNS-Servers erweitert, also ruhig das Archiv neu downloaden.

Neu hinzugekommen ist auch noch ein kleiner Plausibilitätscheck der Eingaben im Setup-Wizzard und der Einstellungsseite, auch wurde bzgl. der Löschung alter Daten wieder etwas geändert. Die Löschung erfolgt jetzt erst nach erfolgter Plausibilitätsprüfung.


Heute am 23.02.2016 habe ich die Software noch einmal erweitert, neu ist die automatische Update Funktion der Software.

Alle 24 Stunden schaut ein laufender Sensor hier auf dem Blog-Server nach ob ein neues Update bereit steht und installiert es ggf.

So erspart man sich die manuelle Installation wenn ich die Software doch noch erweitere und man nicht ins Blog schaut.

Somit ist es vollbracht die „Final Version“ steht.


Hier das endgültige Programm, inkl. Favicon und einem Logo auf den Seiten, so wie es unter dem Namen DHT22_SENSOR_THINGSPEAK_EEPROM_PWD_DNS_UPD.ino im Archiv zu finden ist.

/* EEPROM Aufteilung für Konfigurationsdaten
Position     Länge    Wert
0            1        Firststart Flag
1            1        Updateintervall
2            1        Connectiontimeout
3            1        Flag für zu viele Connection Timeouts -> SETUP Modus wird aktiviert bei 3 aufeinanderfolgenden Timeouts
4            1        IP Typ 0=DHCP, 1=Statisch
5            4        IP-Adresse
9            4        Gateway IP-Adresse
13           4        Subnet Mask
17           4        DNS-Server IP-Adresse
21-52        32       WLAN SSID
53-116       64       WLAN PWD
117-148      32       SENSORSSID
149-212      64       SENSORPWD
213-237      25       Standort
238          1        Thingspeak Übertragung 0=Deaktiviert, 1=Aktiviert
239-255      16       Thingspeak API-Key
256-265      10       Konfigurationspasswort
*/

#include <ESP8266WiFi.h>
#include <ESP8266httpUpdate.h>
#include <DNSServer.h>
#include <EEPROM.h>
#include <DHT.h>

#define RESETPIN 2             
#define DHTPIN 4             
#define LEDPIN 5             
#define DHTPOWERPIN 14
#define DHTTYPE DHT22        

ADC_MODE(ADC_VCC);                                  //Der ADC wird so konfiguriert das er die Systemspannung misst, es darf nichts am ADC (TOUT) Pin angechlossen sein!

const char* SOFTWAREVERSION="2.240216.F";           //Version der Software (X.YYYYYY.Z X = Build des Tages, Y = Datum, Z = Typ (Z=Zwischenversion, F=Finale Version))

//Variablen werden mit EEPROM Konfiguration überschrieben wenn FirstStartFlag im EEPROM = 111 (bedeutet Sensor ist konfiguriert) ist!
byte FIRSTSTARTFLAG=0;                              //Flag zur Erkennung ob System im Setup Modus starten muss weil es keine Konfiguration im EEPROM hat
byte UPDATEINTERVAL=15;                             //Aktualisierungsinterval für den Thingspeak Channel in Minuten (Mindestens 15 lt. Thingspeak gewünscht 😉 )
byte CONNECTIONTIMEOUT=60;                          //Verbindungstimeout für die Verbindung mit unserem WLAN (Sekunden)
byte STATICIP=0;                                    //Art der IP-Adresszuteilung 0=IP per DHCP, 1=Statische IP
byte THINGSPEAKAKTIV=0;                             //Thingspeakübertragung 0=Deaktiviert, 1=Aktiviert (Standard 0)
String THINGSPEAKAPIKEY;                            //Write Key des Thingspeak Channels
String WLANSSID;                                    //Die SSID eures WLAN kommt hier rein
String WLANPWD;                                     //Das WLAN Passwort eures WLAN kommt hier rein
String SENSORSSID="ESP8266-DHT22-SENSOR";           //Die Standard SSID für unser Sensor WLAN
String SENSORPWD;                                   //Das Passwort für unser Sensor WLAN
String SENSORSTANDORT;                              //Standort des Sensors (Max 25 Zeichen)
String KONFIGPWD;                                   //Passwort zur Änderung der Konfiguration über das Webinterface

IPAddress ip(0,0,0,0);                              //Sensor Server IP-Adresse bei statischer Konfiguration
IPAddress gw(0,0,0,0);                              //Gateway IP-Adresse bei statischer Konfiguration
IPAddress sub(255,255,255,0);                       //Subnet Mask bei statischer Konfiguration
IPAddress dns(0,0,0,0);                             //DNS Server IP-Adresse bei statischer Konfiguration

//Konstanten definieren, diese Werte können nur im Programm angepasst werden
const char* THINGSPEAKHOST = "api.thingspeak.com";  //Thingspeak API Host (NICHT ÄNDERN)
const int THINGSPEAKPORT=80;                        //Der Port zum zugriff auf Thingspeak
const int SHUTDOWNVCC=3100;                         //Systemabschaltschwelle in Volt ohne Dezimalpunkt 4 Stellen (z.B. 3,1 V = 3100)
const int MAXSENSORERRORCOUNT=5;                    //Maximale Anzahl Versuche vom Sensor zu lesen bevor das System resettet wird
const int MAXCONNECTIONTRIES=5;                     //Maximale Anzahl an WLAN Verbindungsversuchen bevor wieder in den Setup Modus gebootet wird
const int DNSPORT = 53;                             //Der Port unseres DNS-Servers

//Vorgaben für das automatische Update, diese Daten können für einen eigenen Updateserver angepasst werden
const char* UPDATESERVERFILE="/ESPARDUINOOTA/DHT22_SENSOR_THINGSPEAK_EEPROM_PWD_DNS_UPD_UPDATE.php";
const char* UPDATESERVER="blog.thomasheldt.de";
const int UPDATESERVERPORT=80;
const int SWUPDATEINTERVAL=1440;                     //Abstand zwischen 2 Softwareupdatekontrollen in Minuten

//Sonstige benötigte Variablen definieren 
String HTMLFORMULARWLAN;                            //Hilfsvariable für das Formular zur Auswahl des WLAN
float AKTUELLETEMPERATUR;                           //Variable für die aktuelle Temperatur
float AKTUELLELUFTFEUCHTE;                          //Variable für die aktuelle Luftfeuchte
float KORREKTURTEMPERATUR;                          //Korrekturwert für die Temperatur
float KORREKTURLUFTFEUCHTE;                         //Korrekturwert für die Luftfeuchte
byte TIMEOUTFLAG=0;                                 //Hilfsvariable zum zählen der Verbindungstimeouts
unsigned long STARTZEITPUNKTMESSUNG=0;              //Variable zum festhalten der STARTZEIT aus millis() für die Berechnung wann die nächste Messung fällig ist
unsigned long STARTZEITPUNKTTS=0;                   //Variable zum festhalten der STARTZEIT aus millis() für die Berechnung wann die nächste Übertragung fällig ist
unsigned long THINGSPEAKUPDATEINTERVAL=0;           //Variable für das berechnete Übertragungsintervall der Thingspeak Channel Datenübertragung
unsigned long STARTZEITPUNKTSWUPDATE=0;             //Variable zum festhalten der STARTZEIT aus millis() für die Berechnung wann nächste Updatekontrolle fällig ist

int step=0;                                         //Hilfsvariable für den Setup-Wizzard

DHT dht(DHTPIN, DHTTYPE);
WiFiServer server(80);
DNSServer dnsServer;

// Daten der auf den Webseiten genutzen Bilder (Logo.png und Favicon)
const byte logo[1742] = {
    0x89,0x50,0x4E,0x47,0x0D,0x0A,0x1A,0x0A,0x00,0x00,0x00,0x0D,0x49,0x48,0x44,0x52,
    0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x08,0x06,0x00,0x00,0x00,0x73,0x7A,0x7A,
    0xF4,0x00,0x00,0x06,0x95,0x49,0x44,0x41,0x54,0x58,0x85,0xB5,0x97,0x6B,0x8C,0x5D,
    0x55,0x15,0xC7,0x7F,0xFB,0x9C,0x73,0xEF,0x9D,0x7B,0xA7,0x9D,0xBE,0x1F,0xB4,0x92,
    0x86,0x8E,0xA4,0x28,0x01,0x8B,0x20,0x52,0x9A,0x5A,0x4D,0x49,0x8C,0xA1,0x4D,0x8B,
    0x14,0x0C,0x56,0xD1,0xA8,0x35,0xB1,0x88,0x7C,0x20,0x1A,0x45,0x31,0x88,0x89,0xF8,
    0x0A,0x92,0x46,0x6B,0xC0,0xE8,0x27,0x8D,0x51,0x04,0xDB,0x58,0x52,0x42,0xF8,0x50,
    0x1F,0x50,0x1B,0xA0,0xF6,0xA1,0x45,0xC9,0x4C,0xA5,0x0F,0xEA,0x4C,0x9D,0xC7,0xBD,
    0xF3,0xB8,0xE7,0x9E,0xB3,0xF7,0x5A,0xCB,0x0F,0x97,0x99,0xE1,0xF6,0x4E,0x69,0x0D,
    0x65,0x25,0x2B,0x39,0xC9,0x5A,0x7B,0xFD,0xFF,0xFB,0xBF,0xF6,0xEB,0x38,0xDE,0x60,
    0x0F,0x3E,0x39,0x7C,0x83,0xF7,0x6C,0xCB,0x02,0xD7,0x98,0x51,0x71,0x60,0x5C,0x04,
    0x33,0x70,0xCE,0x51,0x2F,0x26,0xFC,0xAD,0x94,0xB0,0xE3,0xFE,0x5B,0xE7,0xFC,0x75,
    0x22,0xE6,0x26,0x3E,0x1E,0x78,0x7C,0x78,0xE7,0xC9,0x21,0xDD,0xE8,0xC5,0xE1,0xDC,
    0xF4,0x85,0xDE,0x32,0x11,0x83,0x62,0x6C,0x2C,0x9D,0x1B,0xED,0xFA,0xD6,0x6D,0x73,
    0x36,0x4D,0x12,0xF8,0xE6,0x6F,0x87,0x76,0x1E,0xEB,0xD7,0x8D,0x71,0xE2,0x88,0xDE,
    0x26,0xF0,0x09,0x53,0x03,0x11,0x63,0xF9,0x82,0x68,0xD7,0x83,0x1F,0x9B,0xBB,0xC9,
    0xDD,0xFF,0x9B,0xA1,0x55,0x27,0x87,0xE4,0x79,0x53,0xC7,0xDB,0x8C,0x3D,0x69,0x06,
    0xB8,0xC8,0x78,0xC7,0xBC,0xF8,0xC6,0x24,0xF3,0x76,0x97,0xF7,0x46,0x12,0xBF,0xA1,
    0xE1,0x06,0xA9,0x57,0x7C,0x98,0x5A,0x02,0x91,0x83,0x28,0x72,0xC4,0x91,0x23,0x89,
    0x20,0x8E,0xDF,0x1A,0xDD,0xE0,0x8D,0x2C,0xB7,0xBB,0x92,0x86,0xB7,0x95,0x86,0x22,
    0x13,0x58,0x06,0xB5,0xD4,0xB8,0xE3,0xC6,0x4E,0xD6,0x5C,0xD1,0x41,0x50,0x23,0xCD,
    0x8C,0x6A,0x6A,0xF4,0x57,0x03,0xBD,0xFD,0x9E,0xBF,0x9F,0xF0,0xF4,0x8F,0x04,0x3A,
    0x0A,0x50,0x2A,0x44,0x24,0xF1,0xFF,0x4F,0x40,0x81,0x34,0x8F,0x56,0x26,0x5E,0xAC,
    0x6C,0x66,0x60,0xCD,0x19,0xA5,0xB9,0xF2,0xD1,0xEB,0x2B,0xDC,0xB1,0x7A,0xE6,0x9B,
    0x16,0x10,0x35,0xF6,0xFE,0x23,0x65,0xE7,0x0B,0xE3,0xF4,0xF6,0x7B,0xBA,0xCA,0x11,
    0x85,0xE4,0xC2,0x55,0x31,0x33,0x54,0xAD,0x9C,0x98,0x9A,0xA1,0x86,0xD9,0x84,0x34,
    0xCA,0xD5,0x97,0x16,0xCF,0x5B,0x20,0x8E,0x1C,0xEB,0xAE,0xAA,0xB0,0xEE,0xAA,0x0A,
    0xA7,0x87,0x3C,0x0F,0xEF,0xAE,0x72,0xF4,0x54,0xCE,0xEC,0x4A,0x44,0x74,0x21,0xDB,
    0xA8,0x49,0xC0,0xA2,0xA0,0x86,0x9A,0x21,0x34,0x3D,0x8E,0x1D,0xBB,0x0F,0x8C,0x5F,
    0xF0,0x4C,0x00,0x96,0xCC,0x2D,0xF0,0xC3,0x3B,0x17,0xF0,0xED,0xDB,0xE7,0x31,0x92,
    0x06,0x32,0xD1,0xC9,0x7A,0xE7,0x72,0x35,0x23,0xA8,0xE1,0x3E,0xB3,0xA3,0xAF,0x67,
    0xAC,0xEE,0xBB,0xDF,0xC8,0x7A,0x3C,0x13,0x56,0x2C,0x2D,0xF2,0xA1,0x2B,0x3B,0x49,
    0x62,0x47,0xA5,0xE4,0x58,0xD0,0x95,0xB0,0x7C,0x71,0x81,0x42,0x1C,0x9D,0x77,0x66,
    0x5B,0xB6,0xBF,0x46,0x9A,0x19,0xA5,0xE4,0xDC,0xB9,0x6A,0xC6,0x8C,0x4A,0xA1,0xD7,
    0x7D,0xFA,0xC7,0xA7,0x7B,0xC6,0x1A,0xBE,0xFB,0x6C,0xD5,0x42,0x30,0x72,0x69,0xB6,
    0xC6,0xAC,0xB9,0x7F,0x7D,0x30,0xE6,0x74,0xC6,0xAC,0x79,0x57,0x85,0xF5,0xD7,0xCD,
    0xA4,0x7B,0x71,0xE9,0x9C,0x00,0x77,0x6E,0x3F,0xC9,0x68,0xAA,0x14,0x0A,0xD3,0xB7,
    0xC3,0x0C,0x3A,0x3B,0x0A,0xBD,0xEE,0x93,0xDB,0x5F,0xEB,0xA9,0xA7,0xBE,0x3B,0xBA,
    0xC0,0x13,0x48,0xD4,0xF0,0xC1,0x18,0xCF,0x95,0x25,0x73,0x0A,0x7C,0x63,0xF3,0x7C,
    0x56,0x2C,0x2D,0x4F,0x07,0xC1,0x86,0x87,0x8E,0x53,0x8C,0xDC,0xB4,0x5B,0x56,0xD5,
    0xA8,0x94,0x0B,0xBD,0x91,0x88,0xA2,0xA6,0xA8,0xCA,0xA4,0xFB,0x20,0x0C,0x8F,0x7A,
    0xCE,0x54,0x33,0xCE,0x54,0x33,0x06,0x46,0x72,0xAA,0x63,0x9E,0xB1,0xD4,0xA3,0xA2,
    0x14,0x13,0x63,0x4E,0xC5,0x31,0x5A,0x0F,0x6C,0xDD,0x71,0x8A,0xEF,0x3D,0xD9,0x37,
    0x0D,0x01,0xC7,0xA3,0x9F,0x5F,0xC2,0x99,0x91,0x1C,0x11,0x69,0xA9,0xAF,0x2A,0xA8,
    0x29,0x22,0x4A,0x22,0x6A,0xA8,0x1A,0xF6,0x7A,0x0F,0x54,0x0D,0x33,0xE3,0xB1,0x6D,
    0x4B,0xB9,0x6C,0x51,0x07,0x60,0x8C,0xD4,0x85,0x63,0x7D,0x39,0x2F,0x1E,0xAB,0xF3,
    0xD4,0x8B,0x35,0x06,0x47,0x94,0xAE,0x72,0x4C,0x14,0x3B,0xE6,0xCD,0x4C,0x78,0xF6,
    0xD0,0x18,0x3D,0x7D,0xC7,0xF9,0xD9,0xB6,0x65,0x2D,0x14,0x96,0xCC,0x2B,0xB2,0xF9,
    0x86,0x59,0xEC,0x39,0x30,0x42,0xB9,0xD4,0x7A,0x58,0x98,0x19,0xA2,0x46,0xA4,0xA2,
    0xA0,0x53,0x3E,0x5E,0x0F,0x7C,0xED,0xD6,0x45,0xAF,0x83,0x37,0x67,0xD2,0x55,0x49,
    0x58,0xB9,0xBC,0xC2,0xE7,0x6E,0x9A,0xCF,0xEF,0xBF,0xDA,0xCD,0x0F,0x3E,0xB5,0x04,
    0x50,0xEA,0xA9,0x07,0x55,0x66,0x94,0x1C,0xC7,0xFB,0x32,0xEE,0xFD,0xC5,0xC9,0x36,
    0x1D,0xEE,0xD9,0xB0,0x90,0x46,0x26,0x98,0x48,0x0B,0x0E,0xDA,0x54,0xA0,0xD9,0x02,
    0x9D,0xF2,0x20,0xC2,0x82,0xAE,0x37,0x3F,0xDA,0xAE,0xBB,0xBC,0x93,0x5D,0x5F,0x7F,
    0x27,0xAB,0x56,0x74,0x32,0x34,0x92,0xA3,0xAA,0x94,0x8B,0x8E,0xFD,0xFF,0x1A,0x65,
    0xCF,0x8B,0xD5,0xB6,0xFC,0xCD,0xAB,0x67,0x31,0xDE,0x08,0x2D,0x38,0xAA,0x8A,0x4E,
    0x47,0xA0,0x98,0xC0,0x8E,0xA7,0xCE,0xBC,0x29,0x81,0x09,0x7B,0xE0,0xE3,0x4B,0x59,
    0xFF,0xBE,0x2E,0xAA,0x63,0x1E,0x55,0x65,0x56,0x39,0xE2,0xA1,0xC7,0x4F,0xB7,0xE5,
    0x7D,0xE2,0x03,0xF3,0x19,0xAD,0xB7,0x13,0x10,0x51,0xE2,0xCB,0xD7,0x7E,0xF1,0x4B,
    0xAA,0x32,0x77,0xA2,0x2F,0x71,0x04,0xA7,0x06,0x1B,0x3C,0xFE,0x97,0x21,0x7A,0xFE,
    0x53,0xE7,0x85,0x57,0xC6,0xE8,0xAF,0x05,0x96,0x2D,0x2C,0x4D,0x7B,0xD4,0xAE,0x7E,
    0x77,0x17,0x7B,0x0F,0x57,0xA9,0x8E,0x79,0xE2,0xC8,0x91,0x7B,0xA5,0xB3,0x23,0xE2,
    0xCA,0x65,0x95,0xC9,0x9C,0x8E,0x52,0xC4,0xD3,0x2F,0x0D,0x91,0x66,0x8A,0x73,0x4D,
    0x1C,0x33,0x03,0xA2,0xE1,0x48,0x44,0x50,0xD1,0x16,0x2F,0xC5,0x8E,0x3C,0x0B,0xEC,
    0x3D,0x54,0x63,0xF7,0xFE,0x41,0x1E,0x7E,0xE2,0x14,0xAB,0xEF,0x3D,0xC4,0x57,0x7E,
    0xFE,0xEA,0xB4,0x4A,0xFC,0xE4,0x0B,0x97,0x31,0x58,0xCB,0x91,0xA0,0x94,0x12,0xF8,
    0xF5,0xDE,0x76,0x05,0xD7,0x5E,0xD9,0x45,0x23,0x0B,0x2D,0x38,0x22,0x42,0xE4,0x43,
    0x73,0x81,0xA8,0x84,0x16,0x77,0x08,0x89,0x53,0x0A,0x91,0x51,0x29,0x1A,0x0B,0x67,
    0x46,0xEC,0x3B,0x3A,0xCC,0xDA,0x2F,0x1F,0xE2,0xEC,0x97,0xDA,0x8C,0x72,0xC2,0xBA,
    0xAB,0xBB,0x68,0x64,0x39,0x11,0xC2,0xAB,0xA7,0xEB,0x8C,0xA7,0xD2,0x92,0xF3,0xDE,
    0xEE,0x4E,0xF2,0xCC,0x4F,0xD6,0x37,0x69,0x6E,0xF7,0x28,0x04,0x41,0x54,0x09,0x62,
    0x2D,0x5E,0x1B,0x0B,0x0C,0x54,0x1B,0xD4,0xB3,0xC0,0x99,0xE1,0x9C,0xCC,0x0B,0xC5,
    0xC4,0x21,0x21,0xB0,0xE5,0xBB,0x2F,0xB7,0xCD,0x70,0xF3,0x9A,0x05,0x8C,0xD7,0x03,
    0x41,0x8C,0x42,0x0C,0xFB,0xFF,0x59,0x6B,0x89,0xAF,0xB8,0xB4,0x4C,0x23,0x9F,0xC2,
    0x11,0x55,0x42,0x10,0x22,0xF1,0x82,0x4A,0x53,0x85,0x09,0x1F,0x18,0x4E,0xF9,0xEC,
    0x87,0x17,0x73,0xE0,0xA7,0xEF,0xE7,0xB9,0x1F,0x5D,0xCB,0x33,0x0F,0xBD,0x87,0x52,
    0x01,0xF2,0xDC,0x53,0x8C,0xE1,0x70,0x4F,0x8D,0x43,0xC7,0x46,0x5B,0x00,0xAE,0xBF,
    0xA2,0x8B,0xF1,0xCC,0x63,0x41,0x70,0x28,0x2F,0x9F,0x18,0x6B,0x89,0xCF,0x9F,0x55,
    0x24,0xCF,0xFD,0x24,0x86,0x8A,0x20,0x7E,0x42,0x01,0x99,0xF2,0xB1,0x7A,0xCE,0x2D,
    0xAB,0xE7,0xB3,0xF5,0xE6,0xA5,0x93,0x83,0x17,0xCC,0x2E,0xF2,0xF4,0x77,0xAE,0x61,
    0xB0,0x96,0x11,0x42,0xA0,0xA3,0x08,0x4F,0xFC,0xA9,0xFD,0xF4,0x5B,0xDC,0x55,0x20,
    0xF7,0x01,0x53,0xE1,0xD4,0x40,0xA3,0x2D,0xDE,0x51,0x70,0x78,0x1F,0x26,0xB1,0x42,
    0x10,0xA2,0xE0,0x03,0x22,0xCD,0xFD,0x1F,0x44,0x18,0x6F,0x78,0x6E,0xFF,0xE0,0xE2,
    0xB6,0xC1,0xCE,0x39,0xAE,0xED,0x9E,0x41,0x23,0x0F,0x44,0x28,0x47,0x7A,0x47,0xDA,
    0x72,0x16,0xCD,0x4E,0xF0,0x21,0x60,0x26,0x0C,0xD5,0xB2,0xB6,0x78,0x67,0xD1,0x08,
    0xA1,0x89,0x23,0xA2,0x84,0x10,0x48,0x7C,0x08,0x24,0x4E,0x27,0xD7,0x95,0xFA,0x80,
    0xF7,0xD2,0x36,0x18,0xA0,0xDE,0xC8,0xB1,0x10,0x70,0x0E,0x6A,0xA3,0x69,0x5B,0xBC,
    0x54,0x30,0xC4,0x7B,0x0C,0xF0,0xDE,0xB7,0xC5,0x23,0x27,0x68,0x50,0x9C,0x3A,0xCC,
    0x81,0xF7,0x11,0x51,0x08,0xE2,0x44,0x84,0xA0,0x4A,0x50,0xA5,0x94,0x18,0xDB,0x7F,
    0xD7,0xDB,0x36,0x78,0xA0,0x9A,0x71,0xE0,0x95,0x21,0x1C,0x86,0x9A,0x72,0xAA,0xBF,
    0x9D,0xC0,0x91,0x9E,0x1A,0x98,0xE1,0x4C,0x39,0xFA,0xEF,0x76,0x85,0x4E,0xF4,0xA5,
    0x98,0x35,0x71,0x44,0x04,0x0D,0xE2,0xA2,0x10,0x24,0x6D,0x2E,0xC2,0x80,0x49,0xA0,
    0x10,0x1B,0x7F,0x3E,0xF8,0x5F,0xEE,0x7E,0xE4,0x20,0xA3,0xF5,0x00,0xC0,0x73,0x87,
    0x07,0x58,0x7B,0xF7,0x1F,0x99,0x53,0x89,0x31,0x0D,0xA0,0x42,0x31,0x31,0xB6,0x7E,
    0xFF,0x25,0xB2,0x5C,0xC8,0xBC,0x72,0xCF,0x23,0x07,0x49,0xB3,0x1C,0x47,0x73,0x11,
    0xD6,0x46,0x1A,0xDC,0xF7,0xE8,0x11,0xD2,0x86,0x30,0x30,0x9C,0x71,0xCB,0x7D,0xFB,
    0x98,0xD1,0x01,0xA6,0x4D,0x2C,0x15,0x21,0x0F,0x92,0xBA,0xE5,0xB7,0x3D,0xF3,0xCB,
    0xD9,0x9D,0x6C,0xD1,0xB3,0xD8,0x36,0x32,0x61,0x3C,0x0D,0xA8,0x41,0xB1,0xE0,0x98,
    0x59,0x2E,0x10,0x9D,0x75,0xAF,0x67,0xB9,0x4C,0x92,0x9C,0x51,0x4E,0xE8,0x38,0xEB,
    0xC6,0x4B,0xB3,0x40,0x3D,0x15,0x9C,0x83,0x99,0x95,0x84,0x42,0x61,0x2A,0x1E,0x01,
    0xD5,0x71,0x7E,0xE5,0x2E,0xD9,0xB0,0x67,0xD5,0xFC,0x59,0xF6,0x7C,0xE4,0xA2,0x8B,
    0xF4,0x27,0x78,0x01,0xE6,0x40,0x4D,0x19,0x1C,0xE1,0x46,0x07,0x70,0xC9,0xFA,0xA7,
    0x76,0x2E,0x9C,0x6D,0x1B,0xD5,0xCE,0xF3,0xDE,0xBB,0x48,0x16,0x39,0xA5,0xBF,0xEA,
    0x76,0xF5,0xED,0xBE,0x79,0xD3,0xA4,0xA6,0x8B,0x3E,0xF2,0x87,0x9D,0x73,0xBB,0x6C,
    0x63,0x12,0x47,0xCD,0x77,0xE0,0x45,0x06,0x75,0x80,0x73,0x10,0x44,0x19,0x1C,0x71,
    0xBB,0xCE,0xEC,0xD9,0x30,0xF5,0x73,0x3A,0x61,0x73,0x6F,0xDA,0xB5,0x2A,0x89,0x6D,
    0x5B,0x21,0x61,0x25,0x8E,0xCA,0xC5,0x6A,0x8A,0x82,0xC3,0xA8,0xFB,0xC0,0xC1,0x20,
    0xEC,0x18,0x7A,0x76,0xD3,0xBE,0x89,0xD8,0xFF,0x00,0xA6,0x43,0x59,0xF4,0x94,0x71,
    0x65,0xDF,0x00,0x00,0x00,0x00,0x49,0x45,0x4E,0x44,0xAE,0x42,0x60,0x82};

const byte favicon[777] = {
    0x89,0x50,0x4E,0x47,0x0D,0x0A,0x1A,0x0A,0x00,0x00,0x00,0x0D,0x49,0x48,0x44,0x52,
    0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x10,0x08,0x06,0x00,0x00,0x00,0x1F,0xF3,0xFF,
    0x61,0x00,0x00,0x02,0xD0,0x49,0x44,0x41,0x54,0x38,0x8D,0x85,0x93,0xCD,0x6B,0x9C,
    0x65,0x14,0xC5,0x7F,0xCF,0xF3,0xBC,0xF3,0x4E,0xA6,0xD3,0x71,0x3A,0xCD,0x80,0x3A,
    0xA5,0x25,0x58,0xA4,0x50,0xB4,0x08,0x0A,0x21,0xB8,0x11,0x1B,0xDC,0x68,0x6B,0xB1,
    0xA9,0x42,0x50,0xD1,0xA5,0x10,0xA8,0x94,0x89,0x5F,0x20,0x15,0x89,0x74,0x91,0x42,
    0x05,0x0B,0xFE,0x01,0xEA,0xA2,0x28,0x7E,0xD0,0x9D,0x28,0x52,0x2B,0xEE,0x94,0x88,
    0xB6,0x55,0x92,0x94,0x40,0x63,0xD2,0x90,0xCC,0xB4,0x93,0xC9,0xFB,0xF5,0x7C,0xBA,
    0x88,0x8C,0x74,0xA1,0x1E,0xB8,0xAB,0x7B,0xCE,0xB9,0xE7,0x2C,0xAE,0x00,0x78,0xF7,
    0x2B,0xD3,0x5E,0xBF,0xD5,0x9F,0xF2,0x9E,0x3A,0xE0,0xF9,0x6F,0x48,0x29,0xE8,0x35,
    0x1B,0xD5,0xF3,0xA7,0x8F,0x95,0xCF,0x8A,0xD3,0x5F,0xE8,0xF6,0xFC,0x72,0x6F,0x36,
    0x92,0x02,0xE3,0x02,0x3E,0x04,0xA4,0x10,0x28,0xB9,0xCD,0xFC,0x37,0x58,0x17,0xB8,
    0xAF,0x55,0x9B,0x8E,0x56,0x37,0x7A,0x53,0x52,0x78,0x92,0x22,0x30,0xBA,0x3F,0xA6,
    0x5A,0x56,0xDC,0x4A,0x1D,0xF3,0x37,0x0D,0x1B,0x9B,0x9E,0x4A,0x2C,0x18,0x8A,0x05,
    0x52,0xDC,0x69,0x26,0x45,0x60,0xBD,0xDB,0x9F,0x8A,0xAC,0xF5,0x75,0x5D,0x78,0x1E,
    0x1A,0x29,0x31,0x7D,0xB4,0x71,0x07,0x49,0x5B,0xC7,0xC5,0x9F,0x52,0x3E,0xBA,0xD4,
    0x27,0x8E,0x04,0xE5,0x92,0x1C,0xEC,0x42,0x00,0x63,0x7C,0x5D,0x5A,0xEB,0x3C,0x38,
    0xAE,0x2C,0xE5,0x2C,0xDC,0x2C,0x58,0xBB,0x6D,0xF0,0x21,0x00,0x10,0x47,0x8A,0xE3,
    0xA3,0x35,0xBE,0x7C,0xED,0x5E,0x46,0x9A,0x8A,0x5E,0xA2,0x71,0xCE,0xFD,0x3D,0x16,
    0xEB,0x9C,0x17,0x93,0xE7,0x96,0x3B,0xC6,0xBA,0xDD,0x3E,0x40,0xA7,0xEF,0x70,0x3E,
    0x10,0x02,0xB4,0x1A,0x11,0x4F,0x3E,0x52,0xE3,0xC5,0xC7,0xFE,0x49,0xF5,0xC6,0xC7,
    0xAB,0x5C,0xBB,0xA1,0x19,0x8A,0x25,0x21,0x04,0x4A,0x91,0xEA,0x8A,0x13,0xB3,0x4B,
    0x1D,0x63,0xDD,0xEE,0x5C,0x07,0x9E,0x7D,0x74,0x17,0x42,0xC0,0xC2,0x4A,0xC1,0xE5,
    0xDF,0x13,0x08,0x81,0x4A,0xAC,0xF8,0xE4,0xD4,0x3E,0x86,0x6B,0x25,0x00,0x8E,0xCC,
    0x5C,0x47,0x29,0x90,0x02,0xA2,0x48,0x75,0xA5,0x35,0x8E,0x3C,0x37,0x8C,0x3F,0x58,
    0xE5,0xE5,0xC3,0xC3,0xBC,0xF4,0xF8,0x30,0x33,0xCF,0xB7,0xB8,0x34,0x73,0x3F,0xE3,
    0x87,0x76,0x92,0xA4,0x9A,0x89,0x33,0x8B,0xC0,0x76,0xAD,0x57,0x8F,0x0E,0xB3,0xB9,
    0x65,0x70,0xD6,0x61,0x8D,0x43,0x1A,0x63,0x21,0x78,0xBE,0x9D,0xBB,0xCD,0x0F,0x57,
    0x7B,0x5C,0xBB,0x91,0x0D,0x22,0xBF,0xFD,0x5C,0x8B,0xA7,0x47,0xEF,0x22,0x2B,0x0C,
    0x67,0x3E,0x5D,0x01,0xE0,0xF0,0xA1,0x3A,0x5A,0x5B,0x8C,0xB5,0x18,0x63,0x91,0x46,
    0x1B,0x82,0x73,0x58,0x63,0x38,0xF9,0xE1,0x75,0x4E,0xBC,0x77,0x95,0xB1,0x53,0x73,
    0x2C,0xAE,0x6C,0x1B,0xB5,0x9F,0xD9,0x43,0x2C,0x1C,0x9F,0x7D,0xBF,0x36,0x30,0x7E,
    0x78,0x7F,0x99,0x3C,0x33,0x18,0x6D,0x90,0x3A,0x37,0x18,0x5D,0xD0,0xED,0xA5,0x4C,
    0x8C,0x35,0x78,0x7D,0x62,0x0F,0x26,0x2F,0x38,0xF6,0xCE,0x2F,0x03,0xC1,0x91,0xD1,
    0x06,0x49,0x52,0xB0,0xB8,0x9A,0x02,0x70,0xA0,0x55,0x26,0xCB,0x73,0x74,0x6E,0x90,
    0xB9,0x2E,0x48,0xB6,0x34,0x63,0x07,0x76,0xF2,0xE6,0xE4,0x08,0x2F,0x8C,0xDF,0xC3,
    0x5B,0x93,0xFB,0x48,0xB6,0x0A,0xBE,0xF9,0x79,0x03,0x80,0x83,0x7B,0x87,0xD0,0xB9,
    0xE6,0xCF,0xF5,0x1C,0x80,0x66,0x4D,0x51,0xA4,0x86,0x5C,0x17,0x44,0x3A,0x2B,0xA4,
    0x0F,0x96,0x7E,0x12,0x0F,0x2E,0x26,0xA9,0xC1,0xD9,0x8C,0x6E,0x6F,0x5B,0x10,0x49,
    0xD0,0x3A,0xA5,0x28,0x2C,0x00,0xDE,0x39,0xB4,0xCE,0x90,0xC4,0x52,0x35,0x1F,0x98,
    0x7C,0x25,0x92,0xEC,0x5A,0x5C,0xEE,0x73,0x65,0xA9,0xC7,0xAF,0x8B,0x9B,0xBC,0x7F,
    0xE1,0x0F,0xEA,0x3B,0x14,0x3F,0xFE,0xD6,0x41,0x1B,0xCF,0xB9,0x0B,0xF3,0x94,0x55,
    0xE0,0xF2,0xDC,0x06,0xFD,0xCC,0xF2,0xC1,0xE7,0x0B,0xC4,0x0A,0x8C,0x75,0x6B,0x62,
    0xEF,0xF1,0xEF,0xDA,0xCD,0x6A,0x3A,0xEB,0xBC,0xA4,0xD0,0x0E,0x17,0x02,0x3B,0xE2,
    0x08,0x04,0x78,0x1F,0xC8,0xB5,0xA3,0x1C,0x2B,0x94,0x14,0x38,0x1F,0x28,0x8C,0xA3,
    0x12,0x2B,0x94,0x0A,0x74,0xD2,0xCA,0xB4,0x00,0xB8,0xFB,0xA9,0xAF,0xDB,0xD5,0x52,
    0x36,0x25,0x24,0x75,0xC2,0xFF,0xBC,0xB3,0x40,0x06,0x4F,0x2F,0xB3,0x95,0xF3,0xAB,
    0x17,0x9F,0x38,0xFB,0x17,0xEA,0x38,0x7E,0x72,0x8E,0x98,0xFE,0x68,0x00,0x00,0x00,
    0x00,0x49,0x45,0x4E,0x44,0xAE,0x42,0x60,0x82}; 

void GetSensorData() {
  digitalWrite(LEDPIN, 1);
  delay(50);
  digitalWrite(LEDPIN, 0);

  int SENSORERRORCOUNT=0;

  AKTUELLELUFTFEUCHTE = dht.readHumidity();
  AKTUELLETEMPERATUR = dht.readTemperature();

  while (isnan(AKTUELLELUFTFEUCHTE) || isnan(AKTUELLETEMPERATUR)) {
    SENSORERRORCOUNT+=1;
    
    digitalWrite(LEDPIN, 1);
    delay(50);
    digitalWrite(LEDPIN, 0);
    
    delay(2450);
    
    AKTUELLELUFTFEUCHTE = dht.readHumidity();
    AKTUELLETEMPERATUR = dht.readTemperature();

    if (SENSORERRORCOUNT >= MAXSENSORERRORCOUNT) {
      Serial.println(F("Zuviele Sensorfehler in Folge, starte Sensor neu..."));
      Serial.println(F(""));
      
      WiFi.disconnect();

      delay (100);
      
      ESP.deepSleep(1, WAKE_RF_DEFAULT);
      delay(100);
    }
  }
  
  AKTUELLELUFTFEUCHTE+=KORREKTURLUFTFEUCHTE;
  AKTUELLETEMPERATUR+=KORREKTURTEMPERATUR;
}

void ShowSensorData() {
  Serial.print(F("Luftfeuchte: "));
  Serial.print(AKTUELLELUFTFEUCHTE, 1);
  Serial.println(F(" %"));
  Serial.print(F("Temperatur: "));
  Serial.print(AKTUELLETEMPERATUR, 1);
  Serial.println(F(" *C"));
  Serial.println(F(""));
}

String macToStr(const uint8_t* mac)
{
  String result;

  for (int i = 0; i < 6; ++i) {
    if(String(mac[i],16).length()==1){
      result += "0";
    }
    
    result += String(mac[i], 16);
 
    if (i < 5)
      result += ':';
  }

  result.toUpperCase();
  
  return result;
}

void ReadEEPROMConfig() {
  EEPROM.begin(512);

  delay(10);
  
  EEPROM.get(0,FIRSTSTARTFLAG);
  
  Serial.print(F("FIRSTSTARTFLAG="));
  Serial.println(FIRSTSTARTFLAG);
  
  EEPROM.get(1,UPDATEINTERVAL);

  Serial.print(F("UPDATEINTERVAL="));
  Serial.println(UPDATEINTERVAL);

  EEPROM.get(2,CONNECTIONTIMEOUT);

  Serial.print(F("CONNECTIONTIMEOUT="));
  Serial.println(CONNECTIONTIMEOUT);

  EEPROM.get(3,TIMEOUTFLAG);

  Serial.print(F("TIMEOUTFLAG="));
  Serial.println(TIMEOUTFLAG);

  EEPROM.get(4,STATICIP);

  Serial.print(F("STATICIP="));
  Serial.println(STATICIP);

  ip[0]=EEPROM.read(5);
  ip[1]=EEPROM.read(6);
  ip[2]=EEPROM.read(7);
  ip[3]=EEPROM.read(8);
  
  gw[0]=EEPROM.read(9);
  gw[1]=EEPROM.read(10);
  gw[2]=EEPROM.read(11);
  gw[3]=EEPROM.read(12);
  
  sub[0]=EEPROM.read(13);
  sub[1]=EEPROM.read(14);
  sub[2]=EEPROM.read(15);
  sub[3]=EEPROM.read(16);

  dns[0]=EEPROM.read(17);
  dns[1]=EEPROM.read(18);
  dns[2]=EEPROM.read(19);
  dns[3]=EEPROM.read(20);

  Serial.print(F("IP="));
  Serial.println(ip);
  
  Serial.print(F("GATEWAY="));
  Serial.println(gw);
  
  Serial.print(F("SUBNET="));
  Serial.println(sub);
  
  Serial.print(F("DNS="));
  Serial.println(dns);
  
  WLANSSID="";
  
  for (int i = 21; i < 53; ++i)
  {
    WLANSSID += char(EEPROM.read(i));
  }

  Serial.print(F("WLANSSID="));
  Serial.println(WLANSSID.c_str());

  WLANPWD="";
  
  for (int i = 53; i < 117; ++i)
  {
    WLANPWD += char(EEPROM.read(i));
  }
  
  Serial.print(F("WLANPWD="));
  Serial.println(WLANPWD.c_str());

  SENSORSSID="";

  for (int i = 117; i < 149; ++i)
  {
    SENSORSSID += char(EEPROM.read(i));
  }
  
  Serial.print(F("SENSORSSID="));
  Serial.println(SENSORSSID.c_str());

  SENSORPWD="";

  for (int i = 149; i < 213; ++i)
  {
    SENSORPWD += char(EEPROM.read(i));
  }

  Serial.print(F("SENSORPWD="));
  Serial.println(SENSORPWD.c_str());

  SENSORSTANDORT="";

  for (int i = 213; i < 238; ++i)
  {
    SENSORSTANDORT += char(EEPROM.read(i));
  }

  Serial.print(F("SENSORSTANDORT="));
  Serial.println(SENSORSTANDORT.c_str());

  EEPROM.get(238, THINGSPEAKAKTIV);
  
  Serial.print(F("THINGSPEAKAKTIV="));
  Serial.println(THINGSPEAKAKTIV);

  THINGSPEAKAPIKEY="";

  for (int i = 239; i < 256; ++i)
  {
    THINGSPEAKAPIKEY += char(EEPROM.read(i));
  }

  Serial.print(F("THINGSPEAKAPIKEY="));
  Serial.println(THINGSPEAKAPIKEY.c_str());

  KONFIGPWD="";

  for (int i = 256; i < 266; ++i)
  {
    KONFIGPWD += char(EEPROM.read(i));
  }

  Serial.print(F("KONFIGPWD="));
  Serial.println(KONFIGPWD.c_str());

  EEPROM.end();
}

void SendSensorData() {
  analogWrite(LEDPIN, 100);
  
  GetSensorData();
  
  Serial.print(F("Verbinde mit "));
  Serial.println(THINGSPEAKHOST);

  WiFiClient client;

  delay(2000);
  
  if (!client.connect(THINGSPEAKHOST, THINGSPEAKPORT)) {
    Serial.println(F(""));
    Serial.println(F("Verbindung mit Thingspeak-Server fehlgeschlagen!"));
  } else {
    Serial.println(F("Verbindung mit Thingspeak-Server erfolgreich hergestellt"));
    Serial.println(F("Sende Daten an Thingspeak Channel..."));

    String POSTString ="api_key=";
    POSTString += THINGSPEAKAPIKEY.c_str();
    POSTString += "&field1=";
    POSTString += AKTUELLETEMPERATUR;
    POSTString += "&field2=";
    POSTString += AKTUELLELUFTFEUCHTE;
    POSTString += "&field3=";
    POSTString += String(ESP.getVcc()).substring(0,1);
    POSTString += ".";
    POSTString += String(ESP.getVcc()).substring(1);
    
    client.print(F("POST /update HTTP/1.1\n")); 
    client.print(F("HOST: "));
    client.print(THINGSPEAKHOST);
    client.print(F("\n"));
    client.print(F("X-THINGSPEAKAPIKEY:"));
    client.print(THINGSPEAKAPIKEY.c_str());
    client.print(F("\n"));
    client.print(F("Connection: close\n")); 
    client.print(F("Content-Type: application/x-www-form-urlencoded\n")); 
    client.print(F("Content-Length: "));
    client.print(POSTString.length()); 
    client.print(F("\n\n"));
    client.print(POSTString);

    delay(1000);
    
    client.stop();
    
    Serial.println(F("Verbindung zum Server beendet"));
    Serial.println(F("Daten an Thingspeak Channel gesendet"));
  }  

  analogWrite(LEDPIN, 0);
}

void ShowSysInfo(int typ) {
  if (typ==1) {
    Serial.print(F("Software-Version: "));
    Serial.println(SOFTWAREVERSION);
    Serial.print(F("SDK-Version: "));
    Serial.println(ESP.getSdkVersion());
    Serial.print(F("ESP8266 Chip-ID: "));
    Serial.println(ESP.getChipId());
    Serial.print(F("ESP8266 Speed: "));  
    Serial.print(ESP.getCpuFreqMHz());
    Serial.println(F(" MHz"));
  }
  
  Serial.print(F("Free Heap Size: "));
  Serial.print(ESP.getFreeHeap());
  Serial.println(F(" Bytes"));
  Serial.print(F("Systemspannung: "));
  Serial.print(String(ESP.getVcc()).substring(0,1));
  Serial.print(F(","));
  Serial.print(String(ESP.getVcc()).substring(1));
  Serial.println(F(" Volt"));  
  Serial.println(F(""));
}

void ResetWiFi() {
  EEPROM.begin(512);
  
  delay(10);
  
  EEPROM.write(0,0);
  
  EEPROM.commit();
  EEPROM.end();

  delay(100);

  WiFi.disconnect();

  delay(100);
  
  ESP.deepSleep(1,WAKE_RF_DEFAULT);
  delay(100);
}

void CheckForUpdate() {
    t_httpUpdate_return ret = ESPhttpUpdate.update(UPDATESERVER, UPDATESERVERPORT, UPDATESERVERFILE, SOFTWAREVERSION);

    switch(ret) {
        case HTTP_UPDATE_FAILED:
            Serial.println(F("UPDATE FEHLGESCHLAGEN!"));
            Serial.println(F(""));
            break;

        case HTTP_UPDATE_NO_UPDATES:
            Serial.println(F("KEIN UPDATE VORHANDEN!"));
            Serial.println(F(""));
            break;

        case HTTP_UPDATE_OK:
            Serial.println(F("UPDATE ERFOLGREICH!"));
            break;
    }
}

void setup() {
  Serial.begin(115200);

  Serial.println(F(""));  
  Serial.println(F(""));  
  Serial.println(F("Starte den ESP8266-DHT22-SENSOR..."));
  Serial.println(F(""));
  Serial.println(F("Teste Systemspannung..."));
  Serial.println(F(""));

  if (ESP.getVcc() <= SHUTDOWNVCC) {
      Serial.println(F("!!! Systemspannung zu niedrig, schalte Sensor ab !!!"));
      Serial.println(F(""));

      delay(100);
      
      ESP.deepSleep(0,WAKE_RF_DISABLED);
      delay(100);
  }
  
  Serial.print(String(ESP.getVcc()).substring(0,1));
  Serial.print(F(","));
  Serial.print(String(ESP.getVcc()).substring(1));
  Serial.println(F(" Volt ist OK"));
  Serial.println(F(""));

  pinMode(RESETPIN, INPUT_PULLUP);
  pinMode(LEDPIN, OUTPUT);
  pinMode(DHTPOWERPIN, OUTPUT);

  ShowSysInfo(1);

  Serial.println(F("Hole Konfiguration aus EEPROM..."));
  Serial.println(F(""));

  ReadEEPROMConfig();

  float TEMPTEMPERATUR1=0;
  float TEMPLUFTFEUCHTE1=0;
  float TEMPTEMPERATUR2=0;
  float TEMPLUFTFEUCHTE2=0;
  
  if (FIRSTSTARTFLAG==111) {
    digitalWrite(DHTPOWERPIN, 1);
  
    Serial.println(F(""));
    Serial.println(F("Sensorkalibrierung gestartet..."));
    Serial.println(F(""));
  
    for (int i=1; i<=5; i++) {
      delay(2000);
      
      GetSensorData();
      
      ShowSensorData();
  
      TEMPTEMPERATUR1+=AKTUELLETEMPERATUR;
      TEMPLUFTFEUCHTE1+=AKTUELLELUFTFEUCHTE;  
    }
  
    TEMPTEMPERATUR1/=5;
    TEMPLUFTFEUCHTE1/=5;
  
    Serial.print(F("Durchschnittliche Luftfeuchte: "));
    Serial.print(TEMPLUFTFEUCHTE1, 1);
    Serial.println(F(" %"));
    Serial.print(F("Durchschnittliche Temperatur: "));
    Serial.print(TEMPTEMPERATUR1, 1);
    Serial.println(F(" *C"));
  }
  
  Serial.println(F(""));
  Serial.println(F("WLAN-Netzwerk-Scan gestartet..."));
      
  WiFi.mode(WIFI_STA);
  WiFi.disconnect();

  int n = WiFi.scanNetworks();
    
  Serial.println(F("WLAN-Netzwerk-Scan abgeschlossen..."));
  Serial.println(F(""));

  if (n == 0) {
    Serial.println(F("Kein WLAN-Netzwerk gefunden!"));
  } else {
    Serial.print(n);

    if(n<=1) {
     Serial.println(F(" WLAN-Netzwerk gefunden"));
    } else {
      Serial.println(F(" WLAN-Netzwerke gefunden"));
    }
  
    Serial.println(F(""));

    for (int i = 0; i < n; ++i) { 
      Serial.print(i + 1);
      Serial.print(F(": "));
      Serial.print(WiFi.SSID(i));
      Serial.print(F(" ("));
      Serial.print(WiFi.RSSI(i));
      Serial.print(F(")"));
      Serial.println((WiFi.encryptionType(i) == ENC_TYPE_NONE)?" ":"*");
    }
  }

  HTMLFORMULARWLAN = "<b><u>WLAN-Netzwerk ausw&auml;hlen:</u></b><br /><br />";

  for (int i = 0; i < n; ++i) {
    // Erstelle Webseite mit allen SSID und RSSI Werten der gefundenen Netzwerke
    HTMLFORMULARWLAN += "<input type='radio' name='WLANSSID' value='";
    HTMLFORMULARWLAN += WiFi.SSID(i);
    HTMLFORMULARWLAN += "'";

    if (WiFi.SSID(i)==WLANSSID.substring(0, WiFi.SSID(i).length()+1)) {
      HTMLFORMULARWLAN += " checked";
    } 

    HTMLFORMULARWLAN += ">";
    HTMLFORMULARWLAN += WiFi.SSID(i);
    HTMLFORMULARWLAN += " (";
    HTMLFORMULARWLAN += WiFi.RSSI(i);
    HTMLFORMULARWLAN += ")";
    HTMLFORMULARWLAN += (WiFi.encryptionType(i) == ENC_TYPE_NONE)?" ":"*";
    HTMLFORMULARWLAN += "<br />";
  }
  
  Serial.println(F("")); 
  
  dht.begin();

  if (FIRSTSTARTFLAG==111) {
    Serial.print(F("Verbinde mit WLAN "));
    Serial.println(WLANSSID);
  
    if (STATICIP==1) {
      WiFi.config(ip, gw, sub, dns);
    }

    WiFi.begin(WLANSSID.c_str(), WLANPWD.c_str());
    
    int WLANTIMEOUT=0;
    
    while (WiFi.status() != WL_CONNECTED) {
      delay(1000);

      Serial.print(F("."));
      
      WLANTIMEOUT+=1;
  
      if (WLANTIMEOUT>=CONNECTIONTIMEOUT) {
        Serial.println(F(""));
        Serial.println(F("Timeout!"));  
        
        TIMEOUTFLAG+=1;

        if(TIMEOUTFLAG>=MAXCONNECTIONTRIES) {
          ResetWiFi();
        } else {
          EEPROM.begin(512);

          delay(10);
          
          EEPROM.write(3, TIMEOUTFLAG);
          
          EEPROM.commit();
          EEPROM.end();

          delay(100);
          
          WiFi.disconnect();

          delay(100);
          
          ESP.deepSleep(1000000,WAKE_RF_DEFAULT);
          delay(100);
        }
      }
    }
  
    EEPROM.begin(512);

    delay(10);
    
    EEPROM.write(3, 0);
    
    EEPROM.commit();
    EEPROM.end();

    Serial.println(F(""));
    Serial.println(F("Verbindung mit WLAN hergestellt"));  
    Serial.println(F(""));
    Serial.print(F("IP-Addresse: "));
    Serial.println(WiFi.localIP());
    Serial.println(F(""));
    Serial.println(F("Update-Check gestartet..."));
    
    CheckForUpdate();

    Serial.println(F("Setze Sensorkalibrierung fort... "));
    Serial.println(F(""));
   
    for (int i=1; i<=5; i++) {
      delay(2000);

      GetSensorData();

      ShowSensorData();
      
      TEMPTEMPERATUR2+=AKTUELLETEMPERATUR;
      TEMPLUFTFEUCHTE2+=AKTUELLELUFTFEUCHTE;  
    }
  
    TEMPTEMPERATUR2/=5;
    TEMPLUFTFEUCHTE2/=5;
  
    Serial.print(F("Durchschnittliche Luftfeuchte: "));
    Serial.print(TEMPLUFTFEUCHTE2, 1);
    Serial.println(F(" %"));
    Serial.print(F("Durchschnittliche Temperatur: "));
    Serial.print(TEMPTEMPERATUR2, 1);
    Serial.println(F(" *C"));
    Serial.println(F(""));
  
    KORREKTURTEMPERATUR=TEMPTEMPERATUR1-TEMPTEMPERATUR2;
    KORREKTURLUFTFEUCHTE=TEMPLUFTFEUCHTE1-TEMPLUFTFEUCHTE2;
    
    Serial.print(F("Luftfeuchte Korrekturwert: "));
    Serial.println(KORREKTURLUFTFEUCHTE, 2);
    Serial.print(F("Temperatur Korrekturwert: "));
    Serial.println(KORREKTURTEMPERATUR, 2);
    Serial.println(F(""));
  
    GetSensorData();
    
    Serial.println(F("Starte im Normal-Modus"));
    WiFi.softAP(SENSORSSID.c_str(), SENSORPWD.c_str());
  
    delay(100);
    
    Serial.println(F(""));
    Serial.println(F("AP Modus gestartet"));
    Serial.print(F("SSID: "));
    Serial.println(SENSORSSID.c_str());
    Serial.print(F("AP IP-Adresse: "));
    Serial.println(WiFi.softAPIP());
    Serial.println(F(""));
    
    if (THINGSPEAKAKTIV == 1) {
      SendSensorData();
    }
  } else {
    digitalWrite(LEDPIN ,1);

    Serial.println(F("Starte im Setup-Modus!!!"));
    WiFi.softAP("ESP8266-DHT22-SENSOR-SETUP");
  
    delay(100);
    
    Serial.println(F(""));
    Serial.println(F("AP Modus gestartet"));
    Serial.print(F("SSID: "));
    Serial.println("ESP8266-DHT22-SENSOR-SETUP");
    Serial.print(F("AP IP-Adresse: "));
    Serial.println(WiFi.softAPIP());
  } 

  Serial.println(F(""));
  Serial.println(F("Starte DNS-Server"));
  
  dnsServer.start(DNSPORT, "*", WiFi.softAPIP());

  Serial.println(F("DNS-Server gestartet")); 
  Serial.println(F(""));
  Serial.println(F("Starte HTTP-Server"));

  server.begin();

  Serial.println(F("HTTP-Server gestartet")); 
  Serial.println(F(""));

  Serial.println(F("...ESP8266-DHT22-SENSOR erfolgreich gestartet."));
  Serial.println(F(""));  

  STARTZEITPUNKTMESSUNG=0;
  STARTZEITPUNKTTS=0;
  STARTZEITPUNKTSWUPDATE=0;
  
  THINGSPEAKUPDATEINTERVAL=UPDATEINTERVAL*60000;
}

void loop() {  
  unsigned long ISTZEITPUNKT=millis();
  
  //Wenn Systemspannung zu gering System abschalten
  if (ESP.getVcc() <= SHUTDOWNVCC) {
    Serial.println(F("Systemspannung zu gering, System wird abgeschaltet..."));
    Serial.println(F(""));  

    delay(100);
    
    ESP.deepSleep(0, WAKE_RF_DISABLED);
    delay(100);
  }

  if (FIRSTSTARTFLAG == 111) {
    if ((unsigned long)(ISTZEITPUNKT-STARTZEITPUNKTSWUPDATE) >= (unsigned long)(SWUPDATEINTERVAL*60000)) {
      CheckForUpdate();
      STARTZEITPUNKTSWUPDATE=ISTZEITPUNKT;
    }
    
    //Ist es an der Zeit zu messen?
    if ((unsigned long)(ISTZEITPUNKT-STARTZEITPUNKTMESSUNG) >= 2000) {
      GetSensorData();
      ShowSensorData();
    
      STARTZEITPUNKTMESSUNG=ISTZEITPUNKT;
    } else if (THINGSPEAKAKTIV == 1) {
      //Ist es an der Zeit Daten an Thingspeak zu senden?
      if ((unsigned long)(ISTZEITPUNKT-STARTZEITPUNKTTS) >= THINGSPEAKUPDATEINTERVAL) {
        CheckForUpdate();
        SendSensorData();
        STARTZEITPUNKTTS=ISTZEITPUNKT;
      }
    } 
  }

  dnsServer.processNextRequest();

  WiFiClient client = server.available();

  if (digitalRead(RESETPIN)==0) {
    digitalWrite(LEDPIN, 1);
    
    delay(500);
    
    while (digitalRead(RESETPIN)==0) {
      delay(100);
    }

    digitalWrite(LEDPIN, 0);

    delay(500);
    
    ResetWiFi();
  }

  if(client) {
    while(client.connected() && !client.available()){
      delay(1);
    }

    String RequestString = client.readStringUntil('\r');

    client.flush();
  
    int addr_start = RequestString.indexOf(' ');
    int addr_end = RequestString.indexOf(' ', addr_start + 1);

    if (addr_start == -1 || addr_end == -1) {
      Serial.print(F("Ungueltige Anfrage: "));
      Serial.println(RequestString);
      Serial.println(F(""));
      
      client.stop();
      return;
    } else {
      RequestString = RequestString.substring(addr_start + 1, addr_end);

      Serial.print(F("Gueltige Anfrage: "));
      Serial.println(RequestString);
      Serial.println(F(""));
      
      String HTMLSite;
      String HTMLHeader;
      String ERRORTEXT;
      
      if ( RequestString.startsWith("/favicon.ico") ) 
      {
        HTMLHeader  = "HTTP/1.1 200 OK\r\n";
        HTMLHeader += "Content-Type: image/png\r\n";
        HTMLHeader += "Content-Length: ";
        HTMLHeader += sizeof(favicon);
        HTMLHeader += "\r\n";
        HTMLHeader += "Connection: close\r\n";
        HTMLHeader += "\r\n";
        
        client.print(HTMLHeader);
        delay(10);
        client.write(favicon,sizeof(favicon));
        delay(10);
        
        HTMLHeader="";
      }
      else if ( RequestString.startsWith("/logo.png")) 
      {
        HTMLHeader  = "HTTP/1.1 200 OK\r\n";
        HTMLHeader += "Content-Type: image/png\r\n";
        HTMLHeader += "Content-Length: ";
        HTMLHeader += sizeof(logo);
        HTMLHeader += "\r\n";
        HTMLHeader += "Connection: close\r\n";
        HTMLHeader += "\r\n";
        
        client.print(HTMLHeader);
        delay(10);
        client.write(logo,sizeof(logo));
        delay(10);
        
        HTMLHeader="";
      }

      if (RequestString.startsWith("/seteditconfig")) {

        //1. Wert extrahieren (WLAN CONNECTIONTIMEOUT)
        int StartPosition=RequestString.indexOf('=');
        StartPosition++;
        
        int EndePosition=RequestString.indexOf("&");

        int NeuesCONNECTIONTIMEOUT; 
        NeuesCONNECTIONTIMEOUT = RequestString.substring(StartPosition,EndePosition).toInt();

        if(NeuesCONNECTIONTIMEOUT != 10 && NeuesCONNECTIONTIMEOUT != 30 && NeuesCONNECTIONTIMEOUT != 60) {
          ERRORTEXT="Falsches Connetion-Timeout!";
        }
        
        //2. Wert extrahieren (THINGSPEAKAKTIV Flag)
        StartPosition=RequestString.indexOf("=",EndePosition);
        StartPosition++;
        
        EndePosition=RequestString.indexOf("&",EndePosition+2);
        
        int NeuTHINGSPEAKAKTIV;
        NeuTHINGSPEAKAKTIV = RequestString.substring(StartPosition,EndePosition).toInt();

        if(NeuTHINGSPEAKAKTIV !=0 && NeuTHINGSPEAKAKTIV != 1) {
          ERRORTEXT="Falscher ThingSpeak &Uuml;bertragungsstatus!";
        }
        
        //3. Wert extrahieren (THINGSPEAK UPDATEINTERVAL)
        StartPosition=RequestString.indexOf("=",EndePosition);
        StartPosition++;
        
        EndePosition=RequestString.indexOf("&",EndePosition+2);
        
        int NeuesTHINGSPEAKINTERVAL;
        NeuesTHINGSPEAKINTERVAL = RequestString.substring(StartPosition,EndePosition).toInt();

        if(NeuesTHINGSPEAKINTERVAL != 15 && NeuesTHINGSPEAKINTERVAL !=30 && NeuesTHINGSPEAKINTERVAL != 60) {
          ERRORTEXT="Falsches ThingSpeak &Uuml;bertragungs Interval!";
        }
        
        //4. Wert extrahieren (THINGSPEAK API KEY)
        StartPosition=RequestString.indexOf("=",EndePosition);
        StartPosition++;
        
        EndePosition=RequestString.indexOf("&",EndePosition+2);

        String NeuerTHINGSPEAKAPIKEY; 
        NeuerTHINGSPEAKAPIKEY = RequestString.substring(StartPosition,EndePosition);

        if(NeuerTHINGSPEAKAPIKEY.length() > 16) {
          ERRORTEXT="Falscher ThingSpeak API Key!";
        }
        
        if(NeuerTHINGSPEAKAPIKEY == "" && NeuTHINGSPEAKAKTIV == 1) {
          ERRORTEXT="ThingSpeak API Key fehlt!";
        }
        
        //5. Wert extrahieren (Sensor STANDORT)
        StartPosition=RequestString.indexOf("=",EndePosition);
        StartPosition++;
        
        EndePosition=RequestString.indexOf("&",EndePosition+2);

        String NeuerSENSORSTANDORT; 
        NeuerSENSORSTANDORT = RequestString.substring(StartPosition,EndePosition);

        if(NeuerSENSORSTANDORT.length() > 25) {
          ERRORTEXT="Sensorstandort zu lang!";
        }
        
        //6. Wert extrahieren (SENSOR WLANSSID)
        StartPosition=RequestString.indexOf("=",EndePosition);
        StartPosition++;
        
        EndePosition=RequestString.indexOf("&",EndePosition+2);

        String NeueSENSORSSID; 
        NeueSENSORSSID = RequestString.substring(StartPosition,EndePosition);

        if(NeueSENSORSSID.length() > 32) {
          ERRORTEXT="Sensor WLAN SSID zu lang!";
        }

        //7. Wert extrahieren (SENSOR WLANPWD)
        StartPosition=RequestString.indexOf("=",EndePosition);
        StartPosition++;
        
        EndePosition=RequestString.indexOf("&",EndePosition+2);

        String NeuesSENSORPWD; 
        NeuesSENSORPWD = RequestString.substring(StartPosition,EndePosition);

        if(NeuesSENSORPWD.length() > 64) {
          ERRORTEXT="Sensor WLAN Passwort zu lang!";
        }

        //7. Wert extrahieren (Neues KONFIGPWD)
        StartPosition=RequestString.indexOf("=",EndePosition);
        StartPosition++;
        
        EndePosition=RequestString.indexOf("&",EndePosition+2);

        String NeuesKONFIGPWD; 
        NeuesKONFIGPWD = RequestString.substring(StartPosition,EndePosition);

        if (NeuesKONFIGPWD == "") {
          NeuesKONFIGPWD=KONFIGPWD.c_str();
        } 
        
        if(NeuesKONFIGPWD.length() > 10) {
          ERRORTEXT="Neues Konfigurationspasswort zu lang (max. 10 Zeichen)!";
        }
        
        //9. Wert extrahieren (AKTIVESKONFIGPASSWORT)
        String angegebenesKONFIGPASSWORT;
        angegebenesKONFIGPASSWORT=RequestString.substring(RequestString.lastIndexOf("=")+1);

        if (angegebenesKONFIGPASSWORT != KONFIGPWD.c_str()) {
          ERRORTEXT="Falsches Konfigurations-Passwort";
          RequestString="/editconfig.htm";
        } else if (angegebenesKONFIGPASSWORT == "") {
          ERRORTEXT="Kein Konfigurations-Passwort angegeben";
          RequestString="/editconfig.htm";
        } else if(ERRORTEXT == "" ) {
          EEPROM.begin(512);
  
          delay(10);
  
          EEPROM.write(1, 0);
          EEPROM.write(2, 0);
          
          //Lösche alte Konfiguration
          for (int i=117; i<266; i++) {
            EEPROM.write(i ,0);
          }
  
          EEPROM.commit();
          
          Serial.println(F(""));
          Serial.println(F("Schreibe neues CONNECTIONTIMEOUT ins EEPROM:"));
    
          EEPROM.write(2, NeuesCONNECTIONTIMEOUT);
            
          Serial.print(F("schreibe: "));
          Serial.println(NeuesCONNECTIONTIMEOUT); 

          Serial.println(F(""));
          Serial.println(F("Schreibe neues THINGSPEAKAKTIV ins EEPROM:"));
  
          EEPROM.write(238, NeuTHINGSPEAKAKTIV);
            
          Serial.print(F("schreibe: "));
          Serial.println(NeuTHINGSPEAKAKTIV); 
  
          Serial.println(F(""));
          Serial.println(F("Schreibe neues THINGSPEAKINTERVAL ins EEPROM:"));
  
          EEPROM.write(1, NeuesTHINGSPEAKINTERVAL);
            
          Serial.print(F("schreibe: "));
          Serial.println(NeuesTHINGSPEAKINTERVAL); 

          Serial.println(F(""));
          Serial.println(F("Schreibe neuen THINGSPEAKAPIKEY ins EEPROM:"));
    
          for (int i = 0; i < NeuerTHINGSPEAKAPIKEY.length(); ++i){
            EEPROM.write(239+i, NeuerTHINGSPEAKAPIKEY[i]);
            
            Serial.print(F("schreibe: "));
            Serial.println(NeuerTHINGSPEAKAPIKEY[i]); 
          }    

          Serial.println(F(""));
          Serial.println(F("Schreibe neuen SENSORSTANDORT ins EEPROM:"));
    
          for (int i = 0; i < NeuerSENSORSTANDORT.length(); ++i){
            EEPROM.write(213+i, NeuerSENSORSTANDORT[i]);
            
            Serial.print(F("schreibe: "));
            Serial.println(NeuerSENSORSTANDORT[i]); 
          }    

          Serial.println(F(""));
          Serial.println(F("Schreibe neue SENSORSSID ins EEPROM:"));
    
          for (int i = 0; i < NeueSENSORSSID.length(); ++i){
            EEPROM.write(117+i, NeueSENSORSSID[i]);
            
            Serial.print(F("schreibe: "));
            Serial.println(NeueSENSORSSID[i]); 
          }    
  
          Serial.println(F(""));
          Serial.println(F("Schreibe neues SENSORPWD ins EEPROM:"));
    
          for (int i = 0; i < NeuesSENSORPWD.length(); ++i){
            EEPROM.write(149+i, NeuesSENSORPWD[i]);
            
            Serial.print(F("schreibe: "));
            Serial.println(NeuesSENSORPWD[i]); 
          }    
  
          Serial.println(F(""));
          Serial.println(F("Schreibe neues KONFIGPWD ins EEPROM:"));
    
          for (int i = 0; i < NeuesKONFIGPWD.length(); ++i){
            EEPROM.write(256+i, NeuesKONFIGPWD[i]);
            
            Serial.print(F("schreibe: "));
            Serial.println(NeuesKONFIGPWD[i]); 
          }    

          EEPROM.commit();
          EEPROM.end();
                 
          ReadEEPROMConfig();

          STARTZEITPUNKTMESSUNG=0;
          STARTZEITPUNKTTS=0;
  
          THINGSPEAKUPDATEINTERVAL=UPDATEINTERVAL*60000;

          RequestString="/index.htm";
        } else {
          RequestString="/editconfig.htm";
        }
      }
      
      if (RequestString.startsWith("/setwlanconfig?")) {
        step=2;
        
        //1. Wert extrahieren (WLAN SSID)
        int StartPosition=RequestString.indexOf('=');
        StartPosition++;
        
        int EndePosition=RequestString.indexOf("&");

        String NeueWLANSSID; 
        NeueWLANSSID = RequestString.substring(StartPosition,EndePosition);

        //2. Wert extrahieren (Netzwerk Passwort)
        StartPosition=RequestString.indexOf("=",EndePosition);
        StartPosition++;
        
        EndePosition=RequestString.indexOf("&",EndePosition+2);
        
        String NeuesWLANPWD;
        NeuesWLANPWD = RequestString.substring(StartPosition,EndePosition);

        //3. Wert extrahieren (CONNECTIONTIMEOUT)
        int NeuesCONNECTIONTIMEOUT=0;
        NeuesCONNECTIONTIMEOUT=RequestString.substring(RequestString.lastIndexOf("=")+1).toInt();

        if(ERRORTEXT == "") {
          EEPROM.begin(512);
  
          delay(10);
  
          //Lösche alte Konfiguration
          for (int i=21; i<117; i++) {
            EEPROM.write(i ,0);
          }
  
          Serial.println(F(""));
          Serial.println(F("Schreibe neue WLANSSID ins EEPROM:"));
    
          for (int i = 0; i < NeueWLANSSID.length(); ++i){
            EEPROM.write(21+i, NeueWLANSSID[i]);
            
            Serial.print(F("schreibe: "));
            Serial.println(NeueWLANSSID[i]); 
          }    
  
          Serial.println(F(""));
          Serial.println(F("Schreibe neues WLANPWD ins EEPROM:"));
  
          for (int i = 0; i < NeuesWLANPWD.length(); ++i){
            EEPROM.write(53+i, NeuesWLANPWD[i]);
            
            Serial.print(F("schreibe: "));
            Serial.println(NeuesWLANPWD[i]); 
          }    
  
          Serial.println(F(""));
          Serial.print(F("Schreibe neues CONNECTIONTIMEOUT ins EEPROM: "));
  
          Serial.print(F("schreibe: "));
          Serial.println(NeuesCONNECTIONTIMEOUT);
          
          EEPROM.write(2, NeuesCONNECTIONTIMEOUT);
  
          EEPROM.commit();
          EEPROM.end();
        } else {
          step=1;
        }
      }
      
      if (RequestString.startsWith("/setipconfig?")) {
        step=3;

        //1. Wert extrahieren (IP Typ)
        int StartPosition=RequestString.indexOf('=');
        StartPosition++;
        
        int EndePosition=RequestString.indexOf("&");

        int NeuerIPTYP; 
        NeuerIPTYP = RequestString.substring(StartPosition,EndePosition).toInt();

        if(NeuerIPTYP != 0 && NeuerIPTYP != 1) {
          ERRORTEXT="Falsche IP-Adressart (DHCP oder statisch)!";
        }
        
        //2. Wert extrahieren (IP-Adresse Teil 1)
        StartPosition=RequestString.indexOf("=",EndePosition);
        StartPosition++;
        
        EndePosition=RequestString.indexOf("&",EndePosition+2);
        
        int NeueIP1;
        NeueIP1 = RequestString.substring(StartPosition,EndePosition).toInt();

        if(NeuerIPTYP == 1) {
          if(NeueIP1 <1 || NeueIP1 >255) {
            ERRORTEXT="IP-Adresse Teil 1 ist falsch!";
          }
          
        } else if (NeueIP1 < 0 || NeueIP1 > 255) {
          ERRORTEXT="IP-Adresse Teil 1 ist falsch!";
        }
        
        //3. Wert extrahieren (IP-Adresse Teil 2)
        StartPosition=RequestString.indexOf("=",EndePosition);
        StartPosition++;
        
        EndePosition=RequestString.indexOf("&",EndePosition+2);

        int NeueIP2;
        NeueIP2 = RequestString.substring(StartPosition,EndePosition).toInt();

        if(NeueIP2 < 0 || NeueIP2 > 255) {
          ERRORTEXT="IP-Adresse Teil 2 ist falsch!";
        }
        
        //4. Wert extrahieren (IP-Adresse Teil 3)
        StartPosition=RequestString.indexOf("=",EndePosition);
        StartPosition++;
        
        EndePosition=RequestString.indexOf("&",EndePosition+2);
        
        int NeueIP3;
        NeueIP3 = RequestString.substring(StartPosition,EndePosition).toInt();

        if(NeueIP3 < 0 || NeueIP3 > 255) {
          ERRORTEXT="IP-Adresse Teil 3 ist falsch!";
        }
        
       //5. Wert extrahieren (IP-Adresse Teil 4)
        StartPosition=RequestString.indexOf("=",EndePosition);
        StartPosition++;
        
        EndePosition=RequestString.indexOf("&",EndePosition+2);

        int NeueIP4;
        NeueIP4 = RequestString.substring(StartPosition,EndePosition).toInt();

        if(NeueIP4 < 0 || NeueIP4 > 255) {
          ERRORTEXT="IP-Adresse Teil 4 ist falsch!";
        }
        
        //6. Wert extrahieren (Gateway IP-Adresse Teil 1)
        StartPosition=RequestString.indexOf("=",EndePosition);
        StartPosition++;
        
        EndePosition=RequestString.indexOf("&",EndePosition+2);

        int NeueGWIP1;
        NeueGWIP1 = RequestString.substring(StartPosition,EndePosition).toInt();

        if(NeuerIPTYP == 1) {
          if(NeueGWIP1 <1 || NeueGWIP1 >255) {
            ERRORTEXT="Gateway IP-Adresse Teil 1 ist falsch!";
          }
          
        } else if(NeueGWIP1 < 0 || NeueGWIP1 > 255) {
          ERRORTEXT="Gateway IP-Adresse Teil 1 ist falsch!";
        }
        
        //7. Wert extrahieren (Gateway IP-Adresse Teil 2)
        StartPosition=RequestString.indexOf("=",EndePosition);
        StartPosition++;
        
        EndePosition=RequestString.indexOf("&",EndePosition+2);

        int NeueGWIP2;
        NeueGWIP2 = RequestString.substring(StartPosition,EndePosition).toInt();

        if(NeueGWIP2 < 0 || NeueGWIP2 > 255) {
          ERRORTEXT="Gateway IP-Adresse Teil 2 ist falsch!";
        }

        //8. Wert extrahieren (Gateway IP-Adresse Teil 3)
        StartPosition=RequestString.indexOf("=",EndePosition);
        StartPosition++;
        
        EndePosition=RequestString.indexOf("&",EndePosition+2);

        int NeueGWIP3;
        NeueGWIP3 = RequestString.substring(StartPosition,EndePosition).toInt();

        if(NeueGWIP3 < 0 || NeueGWIP3 > 255) {
          ERRORTEXT="Gateway IP-Adresse Teil 3 ist falsch!";
        }

        //9. Wert extrahieren (Gateway IP-Adresse Teil 4)
        StartPosition=RequestString.indexOf("=",EndePosition);
        StartPosition++;
        
        EndePosition=RequestString.indexOf("&",EndePosition+2);

        int NeueGWIP4;
        NeueGWIP4 = RequestString.substring(StartPosition,EndePosition).toInt();

        if(NeueGWIP4 < 0 || NeueGWIP4 > 255) {
          ERRORTEXT="Gateway IP-Adresse Teil 4 ist falsch!";
        }

        //10. Wert extrahieren (Subnet Mask Teil 1)
        StartPosition=RequestString.indexOf("=",EndePosition);
        StartPosition++;
        
        EndePosition=RequestString.indexOf("&",EndePosition+2);

        int NeueMASK1;
        NeueMASK1 = RequestString.substring(StartPosition,EndePosition).toInt();

        if(NeuerIPTYP == 1) {
          if(NeueMASK1 != 255) {
            ERRORTEXT="Subnet Mask Teil 1 ist falsch (255)!";
          }
        } else if(NeueMASK1 < 0 || NeueMASK1 != 255) {
          NeueMASK1=0;
        }

        //11. Wert extrahieren (Subnet Mask Teil 2)
        StartPosition=RequestString.indexOf("=",EndePosition);
        StartPosition++;
        
        EndePosition=RequestString.indexOf("&",EndePosition+2);

        int NeueMASK2;
        NeueMASK2 = RequestString.substring(StartPosition,EndePosition).toInt();

        if(NeuerIPTYP == 1) {
          if(NeueMASK2 !=0 && NeueMASK2 != 255) {
            ERRORTEXT="Subnet Mask Teil 2 ist falsch (0 oder 255)!";
          }
          
        } else if(NeueMASK2 < 0 || NeueMASK2 != 255) {
          NeueMASK2=0;
        }

        //12. Wert extrahieren (Subnet Mask Teil 3)
        StartPosition=RequestString.indexOf("=",EndePosition);
        StartPosition++;
        
        EndePosition=RequestString.indexOf("&",EndePosition+2);

        int NeueMASK3;
        NeueMASK3 = RequestString.substring(StartPosition,EndePosition).toInt();

        if(NeuerIPTYP == 1) {
          if(NeueMASK3 !=0 && NeueMASK3 != 255) {
            ERRORTEXT="Subnet Mask Teil 3 ist falsch (0 oder 255)!";
          }
          
        } else if(NeueMASK3 < 0 || NeueMASK3 != 255) {
          NeueMASK3=0;
        }

        //13. Wert extrahieren (Subnet Mask Teil 4)
        StartPosition=RequestString.indexOf("=",EndePosition);
        StartPosition++;
        
        EndePosition=RequestString.indexOf("&",EndePosition+2);

        int NeueMASK4;
        NeueMASK4 = RequestString.substring(StartPosition,EndePosition).toInt();

        if(NeuerIPTYP == 1) {
          if(NeueMASK4 !=0 && NeueMASK4 != 255) {
            ERRORTEXT="Subnet Mask Teil 4 ist falsch (0 oder 255)!";
          }
          
        } else if(NeueMASK4 < 0 || NeueMASK4 != 255) {
          NeueMASK4=0;
        }

        //14. Wert extrahieren (DNS Server IP-Adresse Teil 1)
        StartPosition=RequestString.indexOf("=",EndePosition);
        StartPosition++;
        
        EndePosition=RequestString.indexOf("&",EndePosition+2);

        int NeueDNSIP1;
        NeueDNSIP1 = RequestString.substring(StartPosition,EndePosition).toInt();

        if(NeueDNSIP1 < 0 || NeueDNSIP1 > 255) {
          ERRORTEXT="DNS-Server IP-Adresse Teil 1 ist falsch!";
        }

        //15. Wert extrahieren (DNS Server IP-Adresse Teil 2)
        StartPosition=RequestString.indexOf("=",EndePosition);
        StartPosition++;
        
        EndePosition=RequestString.indexOf("&",EndePosition+2);
        
        int NeueDNSIP2;
        NeueDNSIP2 = RequestString.substring(StartPosition,EndePosition).toInt();

        if(NeueDNSIP2 < 0 || NeueDNSIP2 > 255) {
          ERRORTEXT="DNS-Server IP-Adresse Teil 2 ist falsch!";
        }

        //16. Wert extrahieren (DNS Server IP-Adresse Teil 3)
        StartPosition=RequestString.indexOf("=",EndePosition);
        StartPosition++;
        
        EndePosition=RequestString.indexOf("&",EndePosition+2);
        
        int NeueDNSIP3;
        NeueDNSIP3 = RequestString.substring(StartPosition,EndePosition).toInt();

        if(NeueDNSIP3 < 0 || NeueDNSIP3 > 255) {
          ERRORTEXT="DNS-Server IP-Adresse Teil 3 ist falsch!";
        }

        //17. Wert extrahieren (DNS Server IP-Adresse Teil 4)
        int NeueDNSIP4;
        NeueDNSIP4 = RequestString.substring(RequestString.lastIndexOf("=")+1).toInt();

        if(NeueDNSIP4 < 0 || NeueDNSIP4 > 255) {
          ERRORTEXT="DNS-Server IP-Adresse Teil 4 ist falsch!";
        }
        
        if(ERRORTEXT == "") {
          EEPROM.begin(512);
  
          delay(10);
  
          //Alte Konfigurationsdaten löschen
          for (int i=4; i<21; i++) {
            EEPROM.write(i, 0);
          }
  
          Serial.println(F(""));
          Serial.println(F("Schreibe neuen IPTYP ins EEPROM:"));
    
          EEPROM.write(4, NeuerIPTYP);
  
          Serial.print(F("schreibe: "));
          Serial.println(NeuerIPTYP); 
  
          Serial.println(F(""));
          Serial.println(F("Schreibe neue IP-Adresse Teil 1 ins EEPROM:"));
  
          EEPROM.write(5, NeueIP1);
          
          Serial.print(F("schreibe: "));
          Serial.println(NeueIP1); 
  
          Serial.println(F(""));
          Serial.println(F("Schreibe neue IP-Adresse Teil 2 ins EEPROM:"));
  
          EEPROM.write(6, NeueIP2);
          
          Serial.print(F("schreibe: "));
          Serial.println(NeueIP2); 
  
          Serial.println(F(""));
          Serial.println(F("Schreibe neue IP-Adresse Teil 3 ins EEPROM:"));
  
          EEPROM.write(7, NeueIP3);
          
          Serial.print(F("schreibe: "));
          Serial.println(NeueIP3); 
  
          Serial.println(F(""));
          Serial.println(F("Schreibe neue IP-Adresse Teil 4 ins EEPROM:"));
  
          EEPROM.write(8, NeueIP4);
          
          Serial.print(F("schreibe: "));
          Serial.println(NeueIP4); 
  
          Serial.println(F(""));
          Serial.println(F("Schreibe neue Gateway IP-Adresse Teil 1 ins EEPROM:"));
  
          EEPROM.write(9, NeueGWIP1);
          
          Serial.print(F("schreibe: "));
          Serial.println(NeueGWIP1); 
  
          Serial.println(F(""));
          Serial.println(F("Schreibe neue Gateway IP-Adresse Teil 2 ins EEPROM:"));
  
          EEPROM.write(10, NeueGWIP2);
          
          Serial.print(F("schreibe: "));
          Serial.println(NeueGWIP2); 
  
          Serial.println(F(""));
          Serial.println(F("Schreibe neue Gateway IP-Adresse Teil 3 ins EEPROM:"));
  
          EEPROM.write(11, NeueGWIP3);
          
          Serial.print(F("schreibe: "));
          Serial.println(NeueGWIP3); 
  
          Serial.println(F(""));
          Serial.println(F("Schreibe neue Gateway IP-Adresse Teil 4 ins EEPROM:"));
  
          EEPROM.write(12, NeueGWIP4);
          
          Serial.print(F("schreibe: "));
          Serial.println(NeueGWIP4); 
  
          Serial.println(F(""));
          Serial.println(F("Schreibe neue Subnet Mask Teil 1 ins EEPROM:"));
  
          EEPROM.write(13, NeueMASK1);
          
          Serial.print(F("schreibe: "));
          Serial.println(NeueMASK1); 
  
          Serial.println(F(""));
          Serial.println(F("Schreibe neue Subnet Mask Teil 2 ins EEPROM:"));
  
          EEPROM.write(14, NeueMASK2);
          
          Serial.print(F("schreibe: "));
          Serial.println(NeueMASK2); 
  
          Serial.println(F(""));
          Serial.println(F("Schreibe neue Subnet Mask Teil 3 ins EEPROM:"));
  
          EEPROM.write(15, NeueMASK3);
          
          Serial.print(F("schreibe: "));
          Serial.println(NeueMASK3); 
  
          Serial.println(F(""));
          Serial.println(F("Schreibe neue Subnet Mask Teil 4 ins EEPROM:"));
  
          EEPROM.write(16, NeueMASK4);
          
          Serial.print(F("schreibe: "));
          Serial.println(NeueMASK4); 
  
          Serial.println(F(""));
          Serial.println(F("Schreibe neue DNS Server IP-Adresse Teil 1 ins EEPROM:"));
  
          EEPROM.write(17, NeueDNSIP1);
          
          Serial.print(F("schreibe: "));
          Serial.println(NeueDNSIP1); 
  
          Serial.println(F(""));
          Serial.println(F("Schreibe neue DNS Server IP-Adresse Teil 2 ins EEPROM:"));
  
          EEPROM.write(18, NeueDNSIP2);
          
          Serial.print(F("schreibe: "));
          Serial.println(NeueDNSIP2); 
  
          Serial.println(F(""));
          Serial.println(F("Schreibe neue DNS Server IP-Adresse Teil 3 ins EEPROM:"));
  
          EEPROM.write(19, NeueDNSIP3);
          
          Serial.print(F("schreibe: "));
          Serial.println(NeueDNSIP3); 
  
          Serial.println(F(""));
          Serial.println(F("Schreibe neue DNS Server IP-Adresse Teil 4 ins EEPROM:"));
  
          EEPROM.write(20, NeueDNSIP4);
          
          Serial.print(F("schreibe: "));
          Serial.println(NeueDNSIP4); 

          EEPROM.commit();
          EEPROM.end();
        } else {
          step=2;
        }
      }

      if (RequestString.startsWith("/settsconfig?")) {
        step=4;

        //1. Wert extrahieren (THINGSPEAKATIV)
        int StartPosition=RequestString.indexOf('=');
        StartPosition++;
        
        int EndePosition=RequestString.indexOf("&");

        int NeuTHINGSPEAKAKTIV; 
        NeuTHINGSPEAKAKTIV = RequestString.substring(StartPosition,EndePosition).toInt();

        if(NeuTHINGSPEAKAKTIV != 0 && NeuTHINGSPEAKAKTIV !=1) {
          ERRORTEXT="Falscher Thingspeak-&Uuml;bertragungsstatus!";
        }
        
        //2. Wert extrahieren (UPDATEINTERVAL)
        StartPosition=RequestString.indexOf('=', EndePosition);
        StartPosition++;
        
        EndePosition=RequestString.indexOf("&", EndePosition + 2);

        int NeuesUPDATEINTERVAL = 0;
        NeuesUPDATEINTERVAL = RequestString.substring(StartPosition,EndePosition).toInt();

        if(NeuesUPDATEINTERVAL != 15 && NeuesUPDATEINTERVAL != 30 && NeuesUPDATEINTERVAL != 60) {
          ERRORTEXT="Falscher Update Interval!";
        }
        
        //3. Wert extrahieren (THINGSPEAKAPIKEY)
        String NeuerTHINGSPEAKAPIKEY; 
        NeuerTHINGSPEAKAPIKEY = RequestString.substring(RequestString.lastIndexOf("=")+1);

        if(NeuerTHINGSPEAKAPIKEY.length() > 16) {
          ERRORTEXT="Falscher ThingSpeak API Key!";
        }

        if(NeuerTHINGSPEAKAPIKEY == "" && NeuTHINGSPEAKAKTIV == 1) {
          ERRORTEXT="ThingSpeak API Key fehlt!";
        }
        
        if(ERRORTEXT == "") {
          EEPROM.begin(512);
  
          delay(10);
          
          //Alte Konfigurationsdaten löschen
          for (int i=238; i<256; i++) {
            EEPROM.write(i, 0);
          }
  
          Serial.println(F(""));
          Serial.println(F("Schreibe neuen THINGSPEAKATIV Status ins EEPROM:"));
    
          EEPROM.write(238, NeuTHINGSPEAKAKTIV);
          
          Serial.print(F("schreibe: "));
          Serial.println(NeuTHINGSPEAKAKTIV); 
  
          Serial.println(F(""));
          Serial.println(F("Schreibe neues UPDATEINTERVAL ins EEPROM:"));
  
          EEPROM.write(1, NeuesUPDATEINTERVAL);
          
          Serial.print(F("schreibe: "));
          Serial.println(NeuesUPDATEINTERVAL); 
  
          Serial.println(F(""));
          Serial.println(F("Schreibe neuen THINGSPEAKAPIKEY ins EEPROM:"));
  
          for (int i = 0; i < NeuerTHINGSPEAKAPIKEY.length(); ++i){
            EEPROM.write(239+i, NeuerTHINGSPEAKAPIKEY[i]);
            
            Serial.print(F("schreibe: "));
            Serial.println(NeuerTHINGSPEAKAPIKEY[i]); 
          }    
  
          EEPROM.commit();
          EEPROM.end();
        } else {
          step=4;
        }
      }

      if (RequestString.startsWith("/setsensorconfig?")) {
        step=5;

        //1. Wert extrahieren (STANDORT)
        int StartPosition=RequestString.indexOf('=');
        StartPosition++;
        
        int EndePosition=RequestString.indexOf("&");

        String NeuerSTANDORT; 
        NeuerSTANDORT = RequestString.substring(StartPosition,EndePosition);

        //2. Wert extrahieren (SENSORSSID)
        StartPosition=RequestString.indexOf("=",EndePosition);
        StartPosition++;
        
        EndePosition=RequestString.indexOf("&",EndePosition+2);

        String NeueSENSORSSID = "";
        NeueSENSORSSID = RequestString.substring(StartPosition,EndePosition);

        //3. Wert extrahieren (SENSORPWD)
        StartPosition=RequestString.indexOf("=",EndePosition);
        StartPosition++;
        
        EndePosition=RequestString.indexOf("&",EndePosition+2);

        String NeuesSENSORPWD = "";
        NeuesSENSORPWD = RequestString.substring(StartPosition,EndePosition);
        
        //4. Wert extrahieren (KONFIGPWD)
        String NeuesKONFIGPWD = "";
        NeuesKONFIGPWD = RequestString.substring(RequestString.lastIndexOf("=")+1);

        if(NeuesKONFIGPWD == "") {
          ERRORTEXT="Bitte Konfigurationspasswort angeben";
        } else if(NeuesKONFIGPWD.length() > 10) {
          ERRORTEXT="Konfigurationspasswort zu lang (max. 10 Zeichen)!";
        }
        
        if(ERRORTEXT == "") {
          EEPROM.begin(512);
  
          delay(10);
          
          //Alte Konfigurationsdaten löschen
          for (int i=117; i<238; i++) {
            EEPROM.write(i, 0);
          }
  
          for (int i=256; i<266; i++) {
            EEPROM.write(i, 0);
          }
  
          Serial.println(F(""));
          Serial.println(F("Schreibe neuen STANDORT ins EEPROM:"));
    
          for (int i = 0; i < NeuerSTANDORT.length(); ++i){
            EEPROM.write(213+i, NeuerSTANDORT[i]);
            
            Serial.print(F("schreibe: "));
            Serial.println(NeuerSTANDORT[i]); 
          }    
  
          Serial.println(F(""));
          Serial.println(F("Schreibe neue SENSORSSID ins EEPROM:"));
  
          for (int i = 0; i < NeueSENSORSSID.length(); ++i){
            EEPROM.write(117+i, NeueSENSORSSID[i]);
            
            Serial.print(F("schreibe: "));
            Serial.println(NeueSENSORSSID[i]); 
          }    
  
          Serial.println(F(""));
          Serial.println(F("Schreibe neues SENSORPWD ins EEPROM:"));
  
          for (int i = 0; i < NeuesSENSORPWD.length(); ++i){
            EEPROM.write(149+i, NeuesSENSORPWD[i]);
            
            Serial.print(F("schreibe: "));
            Serial.println(NeuesSENSORPWD[i]); 
          }    
  
          Serial.println(F(""));
          Serial.println(F("Schreibe neues KONFIGPWD ins EEPROM:"));
  
          for (int i = 0; i < NeuesKONFIGPWD.length(); ++i){
            EEPROM.write(256+i, NeuesKONFIGPWD[i]);
            
            Serial.print(F("schreibe: "));
            Serial.println(NeuesKONFIGPWD[i]); 
          }
                  
          Serial.println(F("Schreibe neues FIRSTSTARTFLAG ins EEPROM:"));
          FIRSTSTARTFLAG=111;
          
          EEPROM.write(0, FIRSTSTARTFLAG);
  
          Serial.print(F("schreibe: "));
          Serial.println(FIRSTSTARTFLAG); 
  
          EEPROM.commit();
          EEPROM.end();
        } else {
          step=4;
        }
      }

      if (step==5) {
        Serial.println(F("Abschlussseite des Setup wird ausgegeben"));
        Serial.println(F(""));
        
        HTMLSite = "<!DOCTYPE html><html><head>";
        HTMLSite += "<title>";
        HTMLSite += SENSORSSID.c_str();
        HTMLSite += "</title>";
        HTMLSite += "</head><body style='font-family:Verdana, Arial, Sans-Serif'><center>";
        HTMLSite += SENSORSSID.c_str();
        HTMLSite += "<br /><br /><fieldset style='width:450px'><br />";
        HTMLSite += "<b>Das Setup des Sensors<br />";
        HTMLSite += "ist abgeschlossen.<br /><br />";
        HTMLSite += "Der Sensor startet jetzt neu!<br />";
        HTMLSite += "<br /></fieldset></center></body></html>\r\n\r\n";

        HTMLHeader  = "HTTP/1.1 200 OK\r\n";
        HTMLHeader += "Content-Length: ";
        HTMLHeader += HTMLSite.length();
        HTMLHeader += "\r\n";
        HTMLHeader += "Content-Type: text/html\r\n";
        HTMLHeader += "Connection: close\r\n";
        HTMLHeader += "\r\n";
        
        client.print(HTMLHeader);
        client.print(HTMLSite);

        delay(10);
        
        client.stop();

        WiFi.disconnect();

        ESP.deepSleep(1000,WAKE_RF_DEFAULT); //System neu starten über Deep-Sleep Timer
        delay(100);
      }
      
      IPAddress AKTSOFTAPIP = WiFi.softAPIP();
      
      String HTMLAKTSOFTAPIP = String(AKTSOFTAPIP[0]) + '.' + String(AKTSOFTAPIP[1]) + '.' + String(AKTSOFTAPIP[2]) + '.' + String(AKTSOFTAPIP[3]);

      if (step==1) {
        Serial.println(F("WLAN Konfigurationsseite wird ausgegeben"));
        Serial.println(F(""));

        HTMLSite = "<!DOCTYPE html><html><head><title>";
        HTMLSite += SENSORSSID.c_str();
        HTMLSite += "</title>";
        HTMLSite += "</head><body style='font-family:Verdana, Arial, Sans-Serif'><center>";
        HTMLSite += "<img src='logo.png' border='0' /><br /><br />";
        HTMLSite += SENSORSSID.c_str();
        
        if(ERRORTEXT != "") {
          HTMLSite += "<br /><br /><fieldset style='width:450px'><legend>Es ist ein Fehler aufgetreten!</legend>";
          HTMLSite += "<font color='red'>";
          HTMLSite += ERRORTEXT;
          HTMLSite += "</font><br /></fieldset>";
        }

        HTMLSite += "<br /><br /><fieldset style='width:450px'><legend>Sensor Setup Schritt 1</legend>";
        HTMLSite += "<form method='GET' action='http://";
        HTMLSite += HTMLAKTSOFTAPIP;
        HTMLSite += "/setwlanconfig'>";
        HTMLSite += "<br /><b>WLAN Einstellungen</b><br /><hr /><br />";
        HTMLSite += HTMLFORMULARWLAN;
        HTMLSite += "<br />WLAN-Passwort: <input name='WLANPWD' type='text' size='30' maxlength='64' value='";
        HTMLSite += WLANPWD.c_str();
        HTMLSite += "'></input><br />";
        HTMLSite += "<br />Verbindungs-Timeout: ";
        HTMLSite += "<select name='CONNECTIONTIMEOUT' size='1'>";

        if (CONNECTIONTIMEOUT==10) {
          HTMLSite += "<option value='10' selected>10</option><option value='30'>30</option><option value='60'>60</option>";
        } else if (CONNECTIONTIMEOUT==30) {
          HTMLSite += "<option value='10'>10</option><option value='30' selected>30</option><option value='60'>60</option>";
        } else {
          HTMLSite += "<option value='10'>10</option><option value='30'>30</option><option value='60' selected>60</option>";
        }
 
        HTMLSite += "</select> Sekunden<br />";
        HTMLSite += "<br /></fieldset>";
        HTMLSite += "<br /><input type='submit' value='Einstellungen speichern und weiter zu Schritt 2...'></form>";
        HTMLSite += "</center></body></html>\r\n\r\n";
      }
      
      if (step==2) {
        Serial.println(F("IP Konfigurationsseite wird ausgegeben"));
        Serial.println(F(""));

        HTMLSite = "<!DOCTYPE html><html><head><title>";
        HTMLSite += SENSORSSID.c_str();
        HTMLSite += "</title>";
        HTMLSite += "</head><body style='font-family:Verdana, Arial, Sans-Serif'><center>";
        HTMLSite += "<img src='logo.png' border='0' /><br /><br />";
        HTMLSite += SENSORSSID.c_str();

        if(ERRORTEXT != "") {
          HTMLSite += "<br /><br /><fieldset style='width:450px'><legend>Es ist ein Fehler aufgetreten!</legend>";
          HTMLSite += "<font color='red'>";
          HTMLSite += ERRORTEXT;
          HTMLSite += "</font><br /></fieldset>";
        }

        HTMLSite += "<br /><br /><fieldset style='width:450px'><legend>Sensor Setup Schritt 2</legend>";
        HTMLSite += "<form method='GET' action='http://";
        HTMLSite += HTMLAKTSOFTAPIP;
        HTMLSite += "/setipconfig'>";
        HTMLSite += "<br /><b>IP Einstellungen</b><br /><hr />";
        HTMLSite += "<br />IP-Adresstyp: ";
        HTMLSite += "<select name='STATICIP' size='1'>";
        
        if (STATICIP==0) {
          HTMLSite += "<option value='0' selected>DHCP</option><option value='1'>Statisch</option></select>";
        } else {
          HTMLSite += "<option value='0'>DHCP</option><option value='1' selected>Statisch</option></select>";
        }
        HTMLSite += "<br /><br />IP-Adresse: <input name='IP1' type='text' size='3' maxlength='3' value='";
        HTMLSite += String(ip[0]);
        HTMLSite += "'></input>.";
        HTMLSite += "<input name='IP2' type='text' size='3' maxlength='3' value='";
        HTMLSite += String(ip[1]);
        HTMLSite += "'></input>.";
        HTMLSite += "<input name='IP3' type='text' size='3' maxlength='3' value='";
        HTMLSite += String(ip[2]);
        HTMLSite += "'></input>.";
        HTMLSite += "<input name='IP4' type='text' size='3' maxlength='3' value='";
        HTMLSite += String(ip[3]);
        HTMLSite += "'></input>";
        HTMLSite += "<br /><br />Gateway IP-Adresse: <input name='GWIP1' type='text' size='3' maxlength='3' value='";
        HTMLSite += String(gw[0]);
        HTMLSite += "'></input>.";
        HTMLSite += "<input name='GWIP2' type='text' size='3' maxlength='3' value='";
        HTMLSite += String(gw[1]);
        HTMLSite += "'></input>.";
        HTMLSite += "<input name='GWIP3' type='text' size='3' maxlength='3' value='";
        HTMLSite += String(gw[2]);
        HTMLSite += "'></input>.";
        HTMLSite += "<input name='GWIP4' type='text' size='3' maxlength='3' value='";
        HTMLSite += String(gw[3]);
        HTMLSite += "'></input>";
        HTMLSite += "<br /><br />Subnet Mask: <input name='MASK1' type='text' size='3' maxlength='3' value='";
        HTMLSite += String(sub[0]);
        HTMLSite += "'></input>.";
        HTMLSite += "<input name='MASK2' type='text' size='3' maxlength='3' value='";
        HTMLSite += String(sub[1]);
        HTMLSite += "'></input>.";
        HTMLSite += "<input name='MASK3' type='text' size='3' maxlength='3' value='";
        HTMLSite += String(sub[2]);
        HTMLSite += "'></input>.";
        HTMLSite += "<input name='MASK4' type='text' size='3' maxlength='3' value='";
        HTMLSite += String(sub[3]);
        HTMLSite += "'></input>";
        HTMLSite += "<br /><br />DNS-Server IP-Adresse: <input name='DNSIP1' type='text' size='3' maxlength='3' value='";
        HTMLSite += String(dns[0]);
        HTMLSite += "'></input>.";
        HTMLSite += "<input name='DNSIP2' type='text' size='3' maxlength='3' value='";
        HTMLSite += String(dns[1]);
        HTMLSite += "'></input>.";
        HTMLSite += "<input name='DNSIP3' type='text' size='3' maxlength='3' value='";
        HTMLSite += String(dns[2]);
        HTMLSite += "'></input>.";
        HTMLSite += "<input name='DNSIP4' type='text' size='3' maxlength='3' value='";
        HTMLSite += String(dns[3]);
        HTMLSite += "'></input><br />";
        HTMLSite += "<br /></fieldset>";
        HTMLSite += "<br /><input type='submit' value='Einstellungen speichern und weiter zu Schritt 3...'></form>";
        HTMLSite += "</center></body></html>\r\n\r\n";
      } 
      
      if (step==3) {
        Serial.println(F("Thingspeak Konfigurationsseite wird ausgegeben"));
        Serial.println(F(""));

        HTMLSite = "<!DOCTYPE html><html><head><title>";
        HTMLSite += SENSORSSID.c_str();
        HTMLSite += "</title>";
        HTMLSite += "</head><body style='font-family:Verdana, Arial, Sans-Serif'><center>";
        HTMLSite += "<img src='logo.png' border='0' /><br /><br />";
        HTMLSite += SENSORSSID.c_str();

        if(ERRORTEXT != "") {
          HTMLSite += "<br /><br /><fieldset style='width:450px'><legend>Es ist ein Fehler aufgetreten!</legend>";
          HTMLSite += "<font color='red'>";
          HTMLSite += ERRORTEXT;
          HTMLSite += "</font><br /></fieldset>";
        }
        
        HTMLSite += "<br /><br /><fieldset style='width:450px'><legend>Sensor Setup Schritt 3</legend>";
        HTMLSite += "<form method='GET' action='http://";
        HTMLSite += HTMLAKTSOFTAPIP;
        HTMLSite += "/settsconfig'>";
        HTMLSite += "<br /><b>Thingspeak Einstellungen</b><br /><hr />";
        HTMLSite += "<br />&Uuml;bertragung aktiv: ";
        HTMLSite += "<select name='THINGSPEAKAKTIV' size='1'>";

        if (THINGSPEAKAKTIV==0) {
          HTMLSite += "<option value='0' selected>NEIN</option><option value='1'>JA</option></select>";
        } else {
          HTMLSite += "<option value='0'>NEIN</option><option value='1' selected>JA</option></select>";
        }
        HTMLSite += "<br /><br />&Uuml;bertrag alle ";
        HTMLSite += "<select name='UPDATEINTERVAL' size='1'>";

        if (UPDATEINTERVAL==15) {
          HTMLSite += "<option value='15' selected>15</option><option value='30'>30</option><option value='45'>45</option><option value='60'>60</option>";
        } else if (UPDATEINTERVAL==30) {  
          HTMLSite += "<option value='15'>15</option><option value='30' selected>30</option><option value='45'>45</option><option value='60'>60</option>";
        } else if (UPDATEINTERVAL==30) {  
          HTMLSite += "<option value='15'>15</option><option value='30'>30</option><option value='45' selected>45</option><option value='60'>60</option>";
        } else {  
          HTMLSite += "<option value='15'>15</option><option value='30'>30</option><option value='45'>45</option><option value='60' selected>60</option>";
        }

        HTMLSite += "</select> Minuten";
        HTMLSite += "<br /><br />API Write-Key: <input name='THINGSPEAKAPIKEY' type='text' size='20' maxlength='16' value='";
        HTMLSite += THINGSPEAKAPIKEY.c_str();
        HTMLSite += "'></input><br />";
        HTMLSite += "<br /></fieldset>";
        HTMLSite += "<br /><input type='submit' value='Einstellungen speichern und weiter zu Schritt 4...'></form>";
        HTMLSite += "</center></body></html>\r\n\r\n";
      } 
      
      if (step==4) {
        Serial.println(F("Sensor Konfigurationsseite wird ausgegeben"));
        Serial.println(F(""));

        HTMLSite = "<!DOCTYPE html><html><head><title>";
        HTMLSite += SENSORSSID.c_str();
        HTMLSite += "</title>";
        HTMLSite += "</head><body style='font-family:Verdana, Arial, Sans-Serif'><center>";
        HTMLSite += "<img src='logo.png' border='0' /><br /><br />";
        HTMLSite += SENSORSSID.c_str();

        if(ERRORTEXT != "") {
          HTMLSite += "<br /><br /><fieldset style='width:450px'><legend>Es ist ein Fehler aufgetreten!</legend>";
          HTMLSite += "<font color='red'>";
          HTMLSite += ERRORTEXT;
          HTMLSite += "</font><br /></fieldset>";
        }
        
        HTMLSite += "<br /><br /><fieldset style='width:450px'><legend>Sensor Setup Schritt 4</legend>";
        HTMLSite += "<form method='GET' action='http://";
        HTMLSite += HTMLAKTSOFTAPIP;
        HTMLSite += "/setsensorconfig'>";
        HTMLSite += "<br /><b>Sensor Einstellungen</b><br /><hr />";
        HTMLSite += "<br />Standort: <input name='SENSORSTANDORT' type='text' size='25' maxlength='25' value='";
        HTMLSite += SENSORSTANDORT.c_str();
        HTMLSite += "'></input><br />";
        HTMLSite += "<br />Sensor WLAN SSID: <input name='SENSORSSID' type='text' size='32' maxlength='32' value='";
        HTMLSite += SENSORSSID.c_str();
        HTMLSite += "'></input><br />";
        HTMLSite += "<br />Sensor WLAN Passwort: <input name='SENSORPWD' type='text' size='30' maxlength='64' value='";
        HTMLSite += SENSORPWD.c_str();
        HTMLSite += "'></input><br />";
        HTMLSite += "<br />Konfigurations-Passwort: <input name='KONFIGPWD' type='password' size='15' maxlength='10' value='";
        HTMLSite += KONFIGPWD.c_str();
        HTMLSite += "'></input><br />";
        HTMLSite += "<br /></fieldset>";
        HTMLSite += "<br /><input type='submit' value='Einstellungen speichern und Setup beenden...'></form>";
        HTMLSite += "</center></body></html>\r\n\r\n";
      } 

      if (RequestString.startsWith("/editconfig.htm")) {
        Serial.println(F("Sensor Konfigurationsaenderungsseite wird ausgegeben"));
        Serial.println(F(""));

        HTMLSite = "<!DOCTYPE html><html><head><title>";
        HTMLSite += SENSORSSID.c_str();
        HTMLSite += "</title>";
        HTMLSite += "</head><body style='font-family:Verdana, Arial, Sans-Serif'><center>";
        HTMLSite += "<img src='logo.png' border='0' /><br /><br />";
        HTMLSite += SENSORSSID.c_str();

        if(ERRORTEXT != "") {
          HTMLSite += "<br /><br /><fieldset style='width:450px'><legend>Es ist ein Fehler aufgetreten!</legend>";
          HTMLSite += "<font color='red'><b>";
          HTMLSite += ERRORTEXT;
          HTMLSite += "</b></font><br /></fieldset>";
        }
        
        HTMLSite += "<br /><br /><fieldset style='width:450px'><legend>Sensor Konfiguration &auml;ndern</legend>";
        HTMLSite += "<form method='GET' action='seteditconfig.htm'>";
        HTMLSite += "<br /><b><u>WLAN Einstellungen</u></b><br />";
        HTMLSite += "<br />Verbindungs-Timeout: ";
        HTMLSite += "<select name='CONNECTIONTIMEOUT' size='1'>";

        if (CONNECTIONTIMEOUT==10) {
          HTMLSite += "<option value='10' selected>10</option><option value='30'>30</option><option value='60'>60</option>";
        } else if (CONNECTIONTIMEOUT==30) {
          HTMLSite += "<option value='10'>10</option><option value='30' selected>30</option><option value='60'>60</option>";
        } else {
          HTMLSite += "<option value='10'>10</option><option value='30'>30</option><option value='60' selected>60</option>";
        }
 
        HTMLSite += "</select> Sekunden<br />";
        HTMLSite += "<br /><hr /><br /><b><u>ThingSpeak Einstellungen</u></b><br />";
        HTMLSite += "<br />&Uuml;bertragung aktiv: ";
        HTMLSite += "<select name='THINGSPEAKAKTIV' size='1'>";

        if (THINGSPEAKAKTIV==0) {
          HTMLSite += "<option value='0' selected>NEIN</option><option value='1'>JA</option></select>";
        } else {
          HTMLSite += "<option value='0'>NEIN</option><option value='1' selected>JA</option></select>";
        }
        HTMLSite += "<br /><br />&Uuml;bertragung alle ";
        HTMLSite += "<select name='UPDATEINTERVAL' size='1'>";

        if (UPDATEINTERVAL==15) {
          HTMLSite += "<option value='15' selected>15</option><option value='30'>30</option><option value='45'>45</option><option value='60'>60</option>";
        } else if (UPDATEINTERVAL==30) {  
          HTMLSite += "<option value='15'>15</option><option value='30' selected>30</option><option value='45'>45</option><option value='60'>60</option>";
        } else if (UPDATEINTERVAL==30) {  
          HTMLSite += "<option value='15'>15</option><option value='30'>30</option><option value='45' selected>45</option><option value='60'>60</option>";
        } else {  
          HTMLSite += "<option value='15'>15</option><option value='30'>30</option><option value='45'>45</option><option value='60' selected>60</option>";
        }

        HTMLSite += "</select> Minuten";
        HTMLSite += "<br /><br />API Write-Key: <input name='THINGSPEAKAPIKEY' type='text' size='20' maxlength='16' value='";
        HTMLSite += THINGSPEAKAPIKEY.c_str();
        HTMLSite += "'></input><br />";
        HTMLSite += "<br /><hr /><br /><b><u>Sensor Einstellungen</u></b><br />";
        HTMLSite += "<br />Standort: <input name='SENSORSTANDORT' type='text' size='25' maxlength='25' value='";
        HTMLSite += SENSORSTANDORT.c_str();
        HTMLSite += "'></input><br />";
        HTMLSite += "<br />Sensor WLAN SSID: <input name='SENSORSSID' type='text' size='32' maxlength='32' value='";
        HTMLSite += SENSORSSID.c_str();
        HTMLSite += "'></input><br />";
        HTMLSite += "<br />Sensor WLAN Passwort: <input name='SENSORPWD' type='password' size='30' maxlength='64' value='";
        HTMLSite += SENSORPWD.c_str();
        HTMLSite += "'></input><br /><br /><hr />";
        HTMLSite += "<br />Neues Konfigurations-Passwort: <input name='NEUES KONFIGPWD' type='password' size='15' maxlength='10'></input><br />";
        HTMLSite += "<br />Aktives Konfigurations-Passwort: <input name='KONFIGPWD' type='password' size='15' maxlength='10'></input><br />";
        HTMLSite += "<br /></fieldset>";
        HTMLSite += "<br /><fieldset style='width:450px'><br /><input type='submit' value='Einstellungen speichern'></form>";
        HTMLSite += "<br /><br /><form metdod='get' action='/index.htm'><input type='submit' value='Abbrechen und zur&uuml;ck zu den Sensorwerten'></form>";
        HTMLSite += "<br /></fieldset></center></body></html>\r\n\r\n";
      } 

      uint8_t mac[6];
      WiFi.macAddress(mac);
      IPAddress LOCALIPIST = WiFi.localIP();
      IPAddress GATEWAYIST = WiFi.gatewayIP();
      IPAddress SUBMASKIST = WiFi.subnetMask();
      IPAddress DNSIPIST = WiFi.dnsIP();
      
      String HTMLipStr = String(LOCALIPIST[0]) + '.' + String(LOCALIPIST[1]) + '.' + String(LOCALIPIST[2]) + '.' + String(LOCALIPIST[3]);
      String HTMLgwStr = String(GATEWAYIST[0]) + '.' + String(GATEWAYIST[1]) + '.' + String(GATEWAYIST[2]) + '.' + String(GATEWAYIST[3]);
      String HTMLsmStr = String(SUBMASKIST[0]) + '.' + String(SUBMASKIST[1]) + '.' + String(SUBMASKIST[2]) + '.' + String(SUBMASKIST[3]);
      String HTMLdnsStr = String(DNSIPIST[0]) + '.' + String(DNSIPIST[1]) + '.' + String(DNSIPIST[2]) + '.' + String(DNSIPIST[3]);

      if (RequestString.startsWith("/sensorinfo.htm")) {  
        HTMLSite = "<!DOCTYPE html><html><head><meta http-equiv='refresh' content='5'><title>";
        HTMLSite += SENSORSSID.c_str();
        HTMLSite += "</title>";
        HTMLSite += "</head><body style='font-family:Verdana, Arial, Sans-Serif'><center>";
        HTMLSite += "<img src='logo.png' border='0' /><br /><br />";
        HTMLSite += SENSORSSID.c_str();
        HTMLSite += "<br /><br /><fieldset style='width:450px'><legend>Sensor Informationen</legend>";
        HTMLSite += "<br />ESP8266 Chip-ID: ";
        HTMLSite += ESP.getChipId();
        HTMLSite += "<br /><br />ESP8266 Speed: ";
        HTMLSite += ESP.getCpuFreqMHz();
        HTMLSite += " MHz<br /><br />Flash Chip-ID: ";
        HTMLSite += ESP.getFlashChipId();
        HTMLSite += "<br /><br />Flash Speed: ";
        HTMLSite += ESP.getFlashChipSpeed()/1000000;
        HTMLSite += " MHz<br /><br />Flash Size: ";
        HTMLSite += ESP.getFlashChipSize();
        HTMLSite += " Bytes<br /><br /><hr /><br />SDK-Version: ";
        HTMLSite += ESP.getSdkVersion();
        HTMLSite += "<br /><br />Boot Mode: ";
        HTMLSite += ESP.getBootMode();
        HTMLSite += "<br /><br />Free Heap Size: ";
        HTMLSite += ESP.getFreeHeap();
        HTMLSite += " Bytes<br /><br /><hr /><br />";
        HTMLSite += "Systemspannung: ";
        HTMLSite += String(ESP.getVcc()).substring(0,1);
        HTMLSite += ",";
        HTMLSite += String(ESP.getVcc()).substring(1);
        HTMLSite += " Volt<br /><br /></fieldset><br /><fieldset style='width:450px'><br /><form action='index.htm'><input type='submit' value='Zur&uuml;ck zu den Sensorwerten'></form>";
        HTMLSite += "<br /></fieldset></center></body></html>\r\n\r\n";
      } 
      
      if (RequestString.startsWith("/netinfo.htm")) {  
        HTMLSite = "<!DOCTYPE html><html><head><title>";
        HTMLSite += SENSORSSID.c_str();
        HTMLSite += "</title>";
        HTMLSite += "</head><body style='font-family:Verdana, Arial, Sans-Serif'><center>";
        HTMLSite += "<img src='logo.png' border='0' /><br /><br />";
        HTMLSite += SENSORSSID.c_str();
        HTMLSite += "<br /><br /><fieldset style='width:450px'><legend>WLAN Netzwerk Informationen</legend>";
        HTMLSite += "<br />WLAN SSID: ";
        HTMLSite += WiFi.SSID();
        HTMLSite += "<br /><br />WLAN Kanal: ";
        HTMLSite += WiFi.channel();
        HTMLSite += "<br /><br />WLAN Signalkst&auml;rke: ";
        HTMLSite += WiFi.RSSI();
        HTMLSite += " dBm<br /><br />Router MAC Adresse: ";
        HTMLSite += WiFi.BSSIDstr();
        HTMLSite += "<br /><br />Eigene IP-Adresse: ";
        HTMLSite += HTMLipStr;
        HTMLSite += "<br /><br />Eigene MAC Adresse: ";
        HTMLSite += macToStr(mac);
        HTMLSite += "<br /><br />Gateway IP-Adresse: ";
        HTMLSite += HTMLgwStr;
        HTMLSite += "<br /><br />Subnet Mask: ";
        HTMLSite += HTMLsmStr;
        HTMLSite += "<br /><br />DNS Server IP-Adresse: ";
        HTMLSite += HTMLdnsStr;
        HTMLSite += "<br /><br /></fieldset><br /><fieldset style='width:450px'><br /><form action='index.htm'><input type='submit' value='Zur&uuml;ck zu den Sensorwerten'></form>";
        HTMLSite += "<br /></fieldset></center></body></html>\r\n\r\n";
      }
      
      if (RequestString.startsWith("/prginfo.htm")) {  
        HTMLSite = "<!DOCTYPE html><html><head><title>";
        HTMLSite += SENSORSSID.c_str();
        HTMLSite += "</title>";
        HTMLSite += "</head><body style='font-family:Verdana, Arial, Sans-Serif'><center>";
        HTMLSite += "<img src='logo.png' border='0' /><br /><br />";
        HTMLSite += SENSORSSID.c_str();
        HTMLSite += "<br /><br /><fieldset style='width:450px'><legend>Programm Informationen</legend>";
        HTMLSite += "<br />Version<br/><br />";
        HTMLSite += SOFTWAREVERSION;
        HTMLSite += "<br /><br /><hr /><br />Author<br/><br /><a href='http://blog.thomasheldt.de' target=_blank'>Thomas Heldt</a> (Karlsbad, Germany)";
        HTMLSite += "<br /><br /><hr /><br />Arduino ESP8266 Addon<br /><br /><a href='https://github.com/esp8266/Arduino' target='_blank'>ESP8266 Arduino Core auf Github</a>";
        HTMLSite += "<br /><br /><hr /><br />DHT22 Library<br /><br /><a href='https://github.com/adafruit/DHT-sensor-library' target='_blank'>Adafruit DHT Library</a>";
        HTMLSite += "<br /><br /><hr /><br />DNSServer Library<br /><br /><a href='https://github.com/esp8266/Arduino/tree/master/libraries/DNSServer' target='_blank'>By Kristian Novoseli&cacute;</a>";
        HTMLSite += "<br /><br /></fieldset><br /><fieldset style='width:450px'><br /><form action='index.htm'><input type='submit' value='Zur&uuml;ck zu den Sensorwerten'></form>";
        HTMLSite += "<br /></fieldset></center></body></html>\r\n\r\n";
      }
      
      if (FIRSTSTARTFLAG==111 && HTMLSite == "") {  
        String TEMPAKTUELLETEMPERATUR=String(AKTUELLETEMPERATUR, 1);
        TEMPAKTUELLETEMPERATUR.replace(".",",");
        
        String TEMPAKTUELLELUFTFEUCHTE=String(AKTUELLELUFTFEUCHTE, 1);
        TEMPAKTUELLELUFTFEUCHTE.replace(".",",");

        HTMLSite = "<!DOCTYPE html><html><head><meta http-equiv='refresh' content='5; URL=\index.htm'><title>";
        HTMLSite += SENSORSSID.c_str();
        HTMLSite += "</title>";
        HTMLSite += "</head><body style='font-family:Verdana, Arial, Sans-Serif'><center>";
        HTMLSite += "<img src='logo.png' border='0' /><br /><br />";
        HTMLSite += SENSORSSID.c_str();
        HTMLSite += "<br /><br /><fieldset style='width:450px'><legend>";
        HTMLSite += SENSORSTANDORT.c_str();
        HTMLSite += "</legend><br />";
        HTMLSite += "<u>Aktuelle Sensorwerte</u><br />";
        HTMLSite += "<br />Temperatur: ";
        HTMLSite += TEMPAKTUELLETEMPERATUR;
        HTMLSite += " &deg;C<br /><br />Luftfeuchte: ";
        HTMLSite += TEMPAKTUELLELUFTFEUCHTE;
        HTMLSite += " %<br /><br /><hr /><br />";
        HTMLSite += "Systemspannung: ";
        HTMLSite += String(ESP.getVcc()).substring(0,1);
        HTMLSite += ",";
        HTMLSite += String(ESP.getVcc()).substring(1);
        HTMLSite += " Volt<br /><br />";
        HTMLSite += "</fieldset><br /><fieldset style='width:450px'><br /><form action='sensorinfo.htm'><input type='submit' value='Sensor Informationen'></form>";
        HTMLSite += "<br /><form action='netinfo.htm'><input type='submit' value='WLAN Netzwerk Informationen'></form>";
        HTMLSite += "<br /><form action='prginfo.htm'><input type='submit' value='Programm Informationen'></form>";
        HTMLSite += "<br /><form action='editconfig.htm'><input type='submit' value='Einstellungen &auml;ndern'></form>";
        HTMLSite += "<br /></fieldset></center></body></html>\r\n\r\n";
      } 

      if(RequestString.startsWith("/ncsi.txt") == 0) {
        if((step == 0 || HTMLSite == "") && FIRSTSTARTFLAG != 111) {
          step=1;
         
          Serial.println(F("Setup Startseite wird ausgegeben"));
          Serial.println(F(""));
  
          HTMLSite = "<!DOCTYPE html><html><head><title>";
          HTMLSite += SENSORSSID.c_str();
          HTMLSite += "</title>";
          HTMLSite += "</head><body style='font-family:Verdana, Arial, Sans-Serif'><center>";
          HTMLSite += "<img src='logo.png' border='0' /><br /><br />";
          HTMLSite += SENSORSSID.c_str();
          HTMLSite += "<br /><br /><fieldset style='width:450px'><br />";
          HTMLSite += "<b>Herzlich Willkommen zum Setup<br />";
          HTMLSite += "des ESP8266 DHT-22 Akku Sensors.<br /><br />";
          HTMLSite += "Sie werden jetzt Schritt f&uuml;r Schritt<br />";
          HTMLSite += "durch das Setup gef&uuml;hrt.<br /><br /></fieldset><br />";
          HTMLSite += "<form method='GET' action='http://";
          HTMLSite += HTMLAKTSOFTAPIP;
          HTMLSite += "/wlanconfig.htm'>";
          HTMLSite += "<input type='submit' value='Weiter zu Schritt 1...'></form>";
          HTMLSite += "</center></body></html>\r\n\r\n";
        }
      }
                
      if (HTMLSite.length() > 0) {
        HTMLHeader  = "HTTP/1.1 200 OK\r\n";
        HTMLHeader += "Content-Length: ";
        HTMLHeader += HTMLSite.length();
        HTMLHeader += "\r\n";
        HTMLHeader += "Content-Type: text/html\r\n";
        HTMLHeader += "Connection: close\r\n";
        HTMLHeader += "\r\n";
        
        client.print(HTMLHeader);
        delay(10);
        client.print(HTMLSite);
        delay(10);
      }
    }
  }

  delay(100);
}

Hier geht es weiter mit der Software die den DEEP-Sleep Timer nutzt…


Hier findet ihr Links zu den eingesetzen Libraries.

Adafuit DHT Library – Download unter https://github.com/adafruit/DHT-sensor-library

DNSServer Library by Kristian Novoselić – Bestandteil der ESP8266 Erweiterung der Arduino IDE Link


Über den nachfolgenden Link kann man sich die bisher veröffentlichte Software downloaden.

Produktivsoftware Download

Verlinke diesen Beitrag:

<a href="http://blog.thomasheldt.de/esp8266-am2302-dht22-sensor-fuer-akkubetrieb-ein-projekt-zum-mitmachen-3/">ESP8266 AM2302 (DHT22) Sensor für Akkubetrieb, ein Projekt zum Mitmachen! (3-1)</a>

The following two tabs change content below.
c7282393508c6050f22643a7feb8fec6?s=80&r=g ESP8266 AM2302 (DHT22) Sensor für Akkubetrieb, ein Projekt zum Mitmachen! (3-1)

Thomas H.

Als Betreiber dieses Blog versuche ich hier interessante Projekte und Tipps rund um die Elektronik zu bieten.
Aktualisiert am: 7. Februar 2016

Die finale Version der ersten Software wurde heute veröffentlicht, im Blog und im Download-Archiv

Aktualisiert am: 23. Februar 2016

Auf Wunsch einiger Mitmacher habe ich noch ein Favicon und ein kleines Logo als Bild integriert in die letzte Software Version. Aktuell arbeite ich noch an einer Sensor Konfigseite um Korrekturwerte zu speichern damit man ggf. vorhandene lineare Abweichungen des Sensors korrigieren kann.

27 Gedanken zu „ESP8266 AM2302 (DHT22) Sensor für Akkubetrieb, ein Projekt zum Mitmachen! (3-1)

  1. Georg

    Hallo Thomas,
    schöne Sache hier!
    Du verwendest ja hier ein ESP-12(E/F) Module, richtig. Warum ist
    denn da der Reset-Pin auf Pin 2? Wo steht denn das?
    Danke im Voraus.

    Antworten
    1. Thomas H. Beitragsautor

      Hallo Georg,

      da bringst du was durcheinander 😉

      Der GPIO2 ist in der Software zum resetten der Konfiguration da, der Reset des ESP-12 Moduls ist ja mit GPIO16 verbunden um den Deep-Sleep nutzen zu können. In einer späteren Version der Platine werde ich aber einen anderen GPIO für diesen Konfigurations-Reset in der Software nehmen.

      Gruß
      Thomas

      Antworten
  2. georg

    Hi Thomas,
    ah ja! Klar, Schaltplan lesen hilft.
    Das mit dem GPIO16 habe ich aber noch nicht ganz…
    GPIO16 ist mit Reset verbunden. Wie hängt das nun mit
    dem Deep-Sleep zusammen.
    Danke im Voraus.

    Antworten
    1. Thomas H. Beitragsautor

      Hallo georg,

      der Deep-Sleep beim ESP8266 ist so gelöst das nach Ablauf des Timers einfach der GPIO16 kurz auf Low geht und darüber den Reset Pin „aktiviert“.

      Es wird also quasi einfach ein Hardware-Reset durchgeführt.

      Aus diesem Grunde funktioniert der Deep-Sleep nur wenn GPIO16 fest mir Reset verbunden ist.

      Gruß
      Thomas

      Antworten
    1. Thomas H. Beitragsautor

      Hallo georg,

      der GPIO16 wird vom ESP8266 selber nach Ablauf der Zeit auf Low gepulst die man beim Aufruf des Deep-Sleep Modus vorgibt.

      Man muss das nicht selber machen, würde ja auch nicht gehen da der ESP8266 ja „schläft“.

      Die Programmzeilen die den Deep-Sleep aktivieren beginnen alle mit ESP.deepSleep.

      Schau mal ins Archiv da findest du Software die den Deep-Sleep aktiv nutzt, oder auch bei der Testsoftware zu diesem Projekt.

      Gruß
      Thomas

      Antworten
    1. Thomas H. Beitragsautor

      Hallo Alex,

      da ich selber mit MQTT nichts mache gehe ich aktuell nicht davon aus.

      Aber wäre sicher etwas für die „Mitmacher“ 😉

      Gruß
      thomas

      Antworten
      1. Alex

        Hi Thomas,

        Ja wäre vielleicht für alle die interessant, die Fhem nutzen, oder schlägst du was anderes vor?

        Grüsse

        Alex

        Antworten
        1. Thomas H. Beitragsautor

          Hallo Alex,

          sorry Fhem nutze ich auch nicht, aber wenn ich mal wieder Zeit habe schaue ich mir das mal an 😉

          Solange kann vielleicht ein „Mitbastler“ was dazu programmieren.

          Gruß
          Thomas

          Antworten
  3. Denis

    Die DHT-Sensoren haben ja eine breite Streuung. Vielleicht wäre ja eine Art Kalibrierung interessant, bei der man während des Setups den Offset der Temperatur und der Feuchtigkeit angeben kann (die dann bei den Messwerten drauf addiert oder abgezogen werden).
    Zum anderen: Ich hatte auf einigen Seiten gelesen, dass der Temperatursensor sich etwas seltsam verhalten soll, wenn er zu nah am ESP8266 ist. Hast du das bei dem Design berücksichtigt?

    Antworten
    1. Thomas H. Beitragsautor

      Hallo Denis,

      ich habe eine Kalibrierung in der Software über eine Mittelwertbildung integriert.

      Auch habe ich bis jetzt keine Abweichungen bzgl. der Nähe zum ESP8266 Modul bemerkt,
      der Sensor liegt ja ein Stück neben dem Modul und nicht direkt dahinter oder darüber.

      Allerdings muss ich anmerken das ich auch nur mehrere DHT22 hier habe die ich miteinander
      vergleiche, ein Referenzthermometer ist nicht vorhanden.

      Aber die Möglichkeit einen Offset zu integrieren finde ich nicht schlecht und werde sie
      mir mal durch den Kopf gehen lassen 😉

      Bis ich aber soweit bin kann jeder gerne auf der Basis der vorhandenen Software selber so eine
      „Kalibrierung“ integrieren.

      Gruß
      Thomas

      Antworten
      1. Denis

        Hi,
        habe mir mal den Spaß gemacht und 4 verschiedene DHT22-Sensoren unterschiedlichen Alters getestet und teilweise Abweichungen um 1-2 Grad gehabt. Bei der Feuchtigkeit waren es 10-20%. Die Serienstreuung ist bei so billigen Teilen nicht ungewöhnlich. Referenzthermometer ist immer so eine Sache. Aber zumindestens wäre es vermutlich nett, wenn man mehrere Sensoren auf eine gemeinsame Referenz „kalibriert“.

        Antworten
        1. Thomas H. Beitragsautor

          Hallo Denis,

          es sollte einfach sein verschiedene Sensoren einmal auszumessen und in der Software dann eine Variable für die Temperaturkorrektur
          und eine für die Luftfeuchtekorrektur zu hinterlegen.

          Bei allen Messungen der Abweichung war diese sogar relativ linear so das komplizierte Berechnungen zur Korrektur eigentlich nicht notwendig sein sollten.

          Aber man sollte sich auch klar machen wie hoch die Genuigkeit wirklich benötigt wird, also mir ist es bei der Messung z.B. in den Innenräumen eigentlich egal
          ob da ein Grad mehr oder weniger angezeigt wird 😉

          Gruß
          Thomas

          Antworten
  4. Michael

    Super Blog! Und ein super aufwendiger Beitrag zum EPS8266 mit Akkutechnik.

    Kann man die Platine/Bausatz wieder erwerben?
    Gibt’s eine Empfehlung oder Vorschläge für ein passendes Gehäuse (in Verbindung mit der genannten Akkuhalterung)?
    Gibt es eine Empfehlung zu einem passenden Solarmodul?

    Antworten
    1. Thomas H. Beitragsautor

      Hallo Michael,

      leider gibt es aktuell keine Platinen (und daher auch keine Bausätze). In ca. 4-5- Wochen habe ich wieder mehr Luft und werde dieses Projekt weiter dokumentieren und meine Erfahrun und den Betrieb mit einer 10W 12V Solarzelle veröffentlichen.

      Danach wird es eine neue Platine und auch wieder Bausätze geben.

      Gruß
      Thomas

      Antworten
  5. Thomas R.

    Hallo Thomas,

    zuerst mal Danke für Dein Projekt und die gute Dokumentation.

    Ich habe Deine Schaltung in vereinfachter Form nachgebaut und betreibe die mit 2 AA Batterien. Bei 15 minütiger Aktualisierung läuft die Schltung jetzt schon 4 Tage. Die Batterispannung wird aktuell mit 2,73V ausgegeben. Interessant, da ja gem. Datenblatt der ESP8266/12 nur bis 3V arbeiten soll. Ich bin auf der Suche nach einer Batterielösung und werde mit weiteren Batterietypen experimentieren. Hat ein anderer Nutzer Erfahrungen mit einer Stromversorgung über Batterien?

    Gruß Thomas R.

    Antworten
  6. Foppel

    Hallo Thomas,
    zwei AA Batterien sind etwas wenig für den DHT22. Ich habe das so gelöst und 3 AA Akkus genommen. Davon geht dann eine Leitung direkt an den DHT22 und die andere über eine Diode zum ESP8266. Bis 2,2V am ESP bekomme ich noch vernünftige Messwerte raus 🙂
    Danke auch an den Blog Ersteller Thomas. Sind wirklich gute Ideen von Dir. Ich mache zwar alles mit der Wifi Manager Library aber das braucht auch mehr Speicher. Schade das man über die Over The Air Update Funktion so wenig findet.
    Viele Grüße – Foppel

    Antworten
  7. Horst

    Hallo Thomas,

    Habe dein Projekt um ein paar sensoren erweitert jedoch von anfang an das problem das der Reset Schalter für das Wifi als auch der Wifi Jumpen keine Funktion haben. Gibt es Tipps?
    Beim betätigen leuchtet die blue led des esp07 bis mal los lässt. Der gpio für den reset ist als Pull up definiert.

    Grüße
    Horst

    Antworten
  8. Schlier

    Fehler im EEProm

    Hallo Thomas,

    ich hatte Dir eine Email geschrieben.
    Bei mir kommt es zum Zerschießen des Erproms, und danach geht kein Wifi mehr.

    Antworten

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.