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

Vom Aufbau der Platine bis hin zur fertigen Test-Software wird in diesem 2. Teil des Projektes alles Schritt für Schritt gezeigt, und erklärt.

Im 3. Teil wird es dann um die endgültige „Produktivsoftware“ gehen.

VORBEREITUNG-300x169 ESP8266 AM2302 (DHT22) Sensor für Akkubetrieb, ein Projekt zum Mitmachen! (2)

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

Download der Arduino-IDE Testsoftware als ZIP-Archiv

Quellen der benutzen Libraries

Tag 1 – Die Bestückung der Platine und deren Test
Tag 2 – Die erste Testsoftware inkl. Erklärung
Tag 3 – Weitere Testsoftware und Datenübertragung an Thingspeak
Tag 4 – Erklärung der Testsoftware und Integration eines Webservers


TAG 1 – Die Bestückung der Platine und deren Test

Wichtig, bitte legt euch alle Bauteile und Werkzeuge griffbereit hin. Wir fangen mit der Bestückung des Teils der Platine an auf der sich die USB-Buchse, die Ladeschaltung und der Spannungsregler befinden.

Zuerst bestücken wir den MAX1811, bitte auf die richtige Einbaulage achten, der MAX1811 hat an PIN 1 einen kleinen Punkt.

MAX1811-300x203 ESP8266 AM2302 (DHT22) Sensor für Akkubetrieb, ein Projekt zum Mitmachen! (2)
Nun folgen alle Bauteile rund um die Ladeschaltung, die Platine sieht danach so aus…

Ladeschaltung-300x212 ESP8266 AM2302 (DHT22) Sensor für Akkubetrieb, ein Projekt zum Mitmachen! (2)
Bitte jetzt unbedingt alle Lötstellen kontrollieren, es darf kein Kurzschluss am MAX1811 vorhanden sein! Wenn alles OK ist machen wir mit dem Spannungsregler und den restlichen Bauteilen weiter.

Bei den meisten Bauteilen wie Widerständen, Stiftleisten, dem Taster und den keram. Kondensatoren braucht man nicht auf die Einbaulage achten, wichtig ist es nur bei den Tantal-Elkos und den LEDs sowie dem MAX1811.

Hier ein Bild in dem ich den + Anschluss der Elkos markiert habe…

Elko-Polung-300x235 ESP8266 AM2302 (DHT22) Sensor für Akkubetrieb, ein Projekt zum Mitmachen! (2)
Die Polung der LED ist zur Sicherheit auf dem folgenden Bild noch einmal gezeigt…

LED-Polung-300x212 ESP8266 AM2302 (DHT22) Sensor für Akkubetrieb, ein Projekt zum Mitmachen! (2)

ACHTUNG !!!

Die Buchse für den Akku hat zu lange Anschlussbeine, man muss die Anschlüsse soweit kürzen das sie nicht auf der anderen Seite der Platine heraus kommen!

Auf der anderen Seite liegt nachher das ESP8266 Modul bündig auf der Platine auf.

Akkubuchse-300x229 ESP8266 AM2302 (DHT22) Sensor für Akkubetrieb, ein Projekt zum Mitmachen! (2)
Hat man auf der Unterseite alles bestückt sieht die Platine jetzt so aus…

BOTTOM-300x204 ESP8266 AM2302 (DHT22) Sensor für Akkubetrieb, ein Projekt zum Mitmachen! (2)

Noch ein TIP, die Buchse sollte man mit etwas Kleber fixieren. Auf dem Bild ist es gut zu sehen…

Buchse-geklebt-300x169 ESP8266 AM2302 (DHT22) Sensor für Akkubetrieb, ein Projekt zum Mitmachen! (2)
Nun kommt der erste Test. Wir benötigen dazu ein Multimeter in der Einstellung zur Messung von Gleichspannung bis 20V. Wir verbinden dazu jetzt die Platine mit einem passenden Kabel mit einem USB Steckernetzteil. Es darf jetzt nichts heiss werden oder qualmen 😉

Ladeschaltung-kontrollmessung-300x169 ESP8266 AM2302 (DHT22) Sensor für Akkubetrieb, ein Projekt zum Mitmachen! (2)

Wir messen an den beiden AKKU-Pads und sollten dort eine Spannung von ca. 4,17-4,19 V anliegen haben. Etwas mehr oder weniger ist jetzt nicht so schlimm, es sollten aber nicht mehr als 4,2 V sein.

Ladeschaltung-Kontrollspannung-300x169 ESP8266 AM2302 (DHT22) Sensor für Akkubetrieb, ein Projekt zum Mitmachen! (2)
Ist dieser Test erfolgreich verlaufen so messen wir die Spannung nach dem Spannungsregler, diese sollte ca. 3,3V betragen. Wir messen dazu zwischen dem AKKU-Masse-Pad und dem Pluspol des 330µF Tantal Kondensators…

Spannungsregler-Kontrollmessung-228x300 ESP8266 AM2302 (DHT22) Sensor für Akkubetrieb, ein Projekt zum Mitmachen! (2)Spannungsregler-Ausgangsspannung-300x169 ESP8266 AM2302 (DHT22) Sensor für Akkubetrieb, ein Projekt zum Mitmachen! (2)
Ist auch diese Messung positiv verlaufen bestücken wir die andere Seite der Platine, bitte bei den LEDs auf die korrekte Polung achten!

Wenn alles fertig gelötet ist sollte die Platine jetzt so aussehen…

Fertige-Platine-300x212 ESP8266 AM2302 (DHT22) Sensor für Akkubetrieb, ein Projekt zum Mitmachen! (2)

Glückwunsch der schwerste Teil ist geschafft, jetzt kann auch der Akku angeschlossen werden, ich empfehle aber diesen zur Programmierung noch weg zu lassen.

Fertig sieht es bei mir jetzt so aus…

Testplatine-mit-Akku-256x300 ESP8266 AM2302 (DHT22) Sensor für Akkubetrieb, ein Projekt zum Mitmachen! (2)


TAG 2 – Die erste Testsoftware inkl. Erklärung

Wer die Arduino IDE noch nicht installiert hat sollte sich diese jetzt auf dem PC installieren, man findet sie über folgenden Link: https://www.arduino.cc/en/Main/Software .

Weitere Informationen zu dieser Erweiterung findet man direkt auf Github über den folgenden Link
https://github.com/esp8266/Arduino.

Hat man sich die IDE installiert und gestartet muss man noch die Erweiterung für den ESP8266 integrieren, dies geschieht wie folgt…

  1. Man öffnet den Menüpunkt Voreinstellungen im Menü Datei
  2. In das Feld „Zusätzliche Boardverwalter-URLs“ trägt man http://arduino.esp8266.com/stable/package_esp8266com_index.json ein und klickt auf OK.
  3. Im Menü Werkzeuge klickt man auf Board:….. und wählt dort den Boardverwalter aus.
  4. Ganz unten findet man einen Eintrag der esp8266 by ESP8266 Community heißt, diesen klickt man an und wählt dann installieren. Dies dauert jetzt eine Zeit, bitte habt etwas Geduld.
  5. Ist die Erweiterung installiert so startet am besten die IDE einmal neu, dies hat bei mir einige Probleme mit der Boardverwaltung vermieden.
  6. Nach erfolgtem Neustart der IDE wählt man im Menü Werkzeuge unter Boards nun das „Generic ESP8266 Module“ aus, wir nutzen ESP12-F (oder E) . Bei Flash Size wählen wir „4M (3M SPIFFS)“ aus und setzen den Port auf den Port, den unser USB-Seriell Wandler als virtuellen Com-Port bereit stellt.
  7. Um den Upload neuer Software zu beschleunigen kann man unter Upload-Speed bei vielen USB-Seriell Wandlern die Einstellung 921600 wählen.

So jetzt kann das erste Testprogramm erstellt werden, dieses kleine Programm liest den
AM2302 (DHT22) Sensor aus und sendet die Daten mit 115200 Baud an den PC.

Folgenden Code muss man eingeben:

#include <DHT.h>

#define DHTPIN 4             
#define DHTTYPE DHT22        

DHT dht(DHTPIN, DHTTYPE);

void setup() {
  pinMode(5,OUTPUT);
  pinMode(14,OUTPUT);

  Serial.begin(115200);

  Serial.println("");  
  Serial.println("ESP8266-DHT22-AKKU-SENSOR DHT22 Test...");
 
  digitalWrite(14,1);
  digitalWrite(5,1);

  delay(1000);
  
  dht.begin();
}

void loop() {
  float hum = dht.readHumidity();
  float temp = dht.readTemperature();
  
  if (isnan(hum) || isnan(temp)) {
    Serial.println("Sensorfehler!");
  } else {
    Serial.print("Luftfeuchte: ");
    Serial.println(humist);
    Serial.print("Temperatur: ");
    Serial.println(tempist);
  }  
  
  delay(2000);
}

Der USB-Seriell Wandler muss auf den Betrieb mit 3,3 V eingestellt sein, dies ist wichtig da der ESP8266 auf den I/Os nur 3,3 V verträgt!

USB-Seriell-Wandler-300x171 ESP8266 AM2302 (DHT22) Sensor für Akkubetrieb, ein Projekt zum Mitmachen! (2)
Jetzt müssen folgende Verbindungen zwischen dem USB-Seriell Wandler und der Platine hergestellt werden, bitte die Platine dazu von der Stromversorgung trennen…

Platine RXD an Wandler TXD
Platine TXD an Wandler RXD
Platine GND and Wandler GND

Programmierung-300x169 ESP8266 AM2302 (DHT22) Sensor für Akkubetrieb, ein Projekt zum Mitmachen! (2)

Zu guter letzt setzt man noch einen Jumper auf die PRG Stiftleiste, ich habe einen roten Jumper genommen damit man es besser sehen kann 😉

Jetzt steckt man das USB-Kabel wieder in das Steckernetzteil, die blaue LED des ESP8266 Moduls sollte ganz kurz aufleuchten.

In der Arduino IDE klickt man nun auf das Symbol mit dem kleinen Pfeil…

Programm-hochladen ESP8266 AM2302 (DHT22) Sensor für Akkubetrieb, ein Projekt zum Mitmachen! (2)

Wenn man sein Projekt noch nicht gespeichert hat kommt jetzt eine Abfrage nach dem Namen und dem Speicherort, bitte einfach DHT22_Test eingeben und OK klicken.

Jetzt erscheint unten in der IDE die Meldung das komipiliert wird…

Komilieren-300x87 ESP8266 AM2302 (DHT22) Sensor für Akkubetrieb, ein Projekt zum Mitmachen! (2)Dann sollte die blaue LED des ESP8266 Moduls schnell blinken und folgende Meldung erscheint nach einigen Sekunden…

Upload-fertig-300x31 ESP8266 AM2302 (DHT22) Sensor für Akkubetrieb, ein Projekt zum Mitmachen! (2)Nun in der IDE unter Werkzeuge den Menüpunkt Serieller Monitor anklicken, nach und nach sollten jetzt die Meldungen des Sensors angezeigt werden…

Serieller-Monitor-DHT-Test-300x143 ESP8266 AM2302 (DHT22) Sensor für Akkubetrieb, ein Projekt zum Mitmachen! (2)Herzlichen Glückwunsch! Der Sensor funktioniert, nun kommen wir zur Erkärung der Software…

In der Zeile #include <DHT.h> binden wir eine fertige Library für den Sensor ein, diese ist getestet und funktioniert gut.

Jetzt legen wir fest an welchen GPIO des ESP8266 was dran hängt, #define DHTPIN 4 bedeutet das der Datenausgang des Sensors mit GPIO 4 verbunden ist. Das #definde DHTTYPE DHT22 informiert die benutzte Library darüber welchen Sensortypen wir nutzen, in unserem Fall den AM2302=DHT22.

Nun übergeben wir diese Vorgaben an die Library indem wir DHT dht(DHTPIN, DHTTYPE); ausführen. Als nächstes kommt der erste Programmabschnitt, dieser wird nur beim Start ausgeführt und trägt deshalb die Bezeichnung setup.

Zuerst setzen wir unsere GPIOs in den benötigten Zustand, also ob Eingang oder Ausgang.

pinMode(5, OUTPUT); setzt GPIO 5 auf Ausgang, hier hängt unsere grüne LED dran.

pinMode(14, OUTPUT); setzt GPIO 14 des ESP8266 auch auf Ausgang, dieser GPIO schaltet unseren Sensor an bzw. ab indem er ihn mit Spannung versorgt oder eben nicht.

Mit Serial.begin(115200); wird die serielle Schnittstelle des ESP8266 konfiguriert, wir wollen uns ja Daten über diese Schnittstelle an den PC senden lassen.

Die nächsten beiden Zeilen senden jetzt einfach eine Leerzeile und einen Begrüßungstext an den PC. Danach setzen wir unsere GPIOs das erste mal ein.

digitalWrite(14,1); setzt nun GPIO 14 auf High, also ca. 3,3 V. Jetzt wird der Sensor mit Spannung versorgt und wir können Messungen durchführen.

Über digitalWrite(5,1); aktivieren wir die grüne LED um auch optisch eine Startmeldung zu erhalten.

Jetzt kommt das „böse“ delay(1000); was aber an dieser Stelle, und auch später bei der ESP8266 Programmierung, nicht nur sinnvoll sondern auch benötigt wird, dazu später mehr. In anderen Mikrocontroller Programmen würde man Verzögerungen lieber über nicht blockierende Timer-Funktionen lösen.

Wir müssen an dieser Stelle eine kleine Verzögerung einbauen damit der Sensor, er wurde gerade gestartet (mit Spannung versorgt), stabil anläuft.

dht.begin(DHT); schliesslich startet die Kommunikation mit dem Sensor.

Nun folgt der nächste Programmabschnitt namens loop, dieser wird in einer Endlosschleife immer wieder durchlaufen, daher auch der Name 🙂

In den Zeilen

float hum = dht.readHumidity();
float temp = dht.readTemperature();

definieren wir zwei Variablen und weisen diesen gleichzeitig das Ergebnis zweier Funktionen aus der Sensor Library zu, einmal die aktuelle Luftfeuchte (hum) und die aktuelle Temperatur (temp).

Da wir mit Nachkommastellen arbeiten nutzen wir den Typ float !

Die Library Funktionen sind so aufgebaut das sie uns nur bei erfolgreichem Auslesen des Sensors Werte zurück geben, daher testen wir in der folgenden Zeile

 if (isnan(hum) || isnan(temp))

ob eine, oder beide, Variablen Werte enthalten und geben dann eine Meldung über die serielle Schnittstelle an den PC weiter.

Zum Schluss folgt noch einmal eine Pause von 2 Sekunden da der Sensor nur alle 2 Sekunden ausgelesen werden kann um gültige Daten zu liefern.

delay(2000);

So unser erstes kleines Testprogramm ist fertig 😉

Um nun auch den Deep Sleep Modus zu testen, und auch gleich ein paar Informationen mehr zum Modul anzuzeigen habe ich folgendes Testprogramm geschrieben.

Der einzige Unterschied zum obigen Programm ist der das die 2 Sekunden Verzögerung zwischen den Messungen jetzt dadurch erreicht werden, indem das Modul in den Tiefschlaf versetzt wird.

Zusätzlich habe ich alles in den setup Bereich verschoben da das Modul nach erfolgter Messung, und folgendem Tiefschlaf, ja immer wieder neu gestartet wird.

Viel Spaß beim testen 🙂

#include <DHT.h>

#define DHTPIN 4             
#define DHTTYPE DHT22        

DHT dht(DHTPIN, DHTTYPE);

void setup() {
  pinMode(5,OUTPUT);
  pinMode(14,OUTPUT);

  digitalWrite(14,1);
  digitalWrite(5,1);
  
  Serial.begin(115200);

  Serial.println(F(""));  
  Serial.println(F(""));  
  Serial.println(F("ESP8266-DHT22-AKKU-SENSOR Test mit Deep-Sleep..."));
  Serial.println(F(""));
  Serial.print(F("SDK-Version: "));
  Serial.println(ESP.getSdkVersion());
  Serial.print(F("ESP8266 Chip-ID: "));
  Serial.println(ESP.getChipId());
  Serial.print(F("ESP8266 Speed in MHz: "));  
  Serial.println(ESP.getCpuFreqMHz());
  Serial.print(F("Free Heap Size in Bytes: "));
  Serial.println(ESP.getFreeHeap());
  Serial.println(F(""));
 
  delay(1000);
  
  dht.begin();

  float hum = dht.readHumidity();
  float temp = dht.readTemperature();

  if (isnan(hum) || isnan(temp)) {
    Serial.println(F("Sensorfehler!"));
  } else {
    Serial.print(F("Luftfeuchte: "));
    Serial.print(hum);
    Serial.println(F(" %"));
    Serial.print(F("Temperatur: "));
    Serial.print(temp);
    Serial.println(F(" *C"));
  }  
  
  ESP.deepSleep(2000000, WAKE_RF_DISABLED);
  delay(100);
}

void loop() {
}


TAG 3 – Weitere Testsoftware und Datenübertragung an Thingspeak

Heute werden wir den ESP8266 mit unserem WLAN verbinden und die Daten des Sensors an Thingspeak senden.

Dazu ist ein kostenloser Account bei Thingspeak.com erforderlich den man sich einfach wie folgt anlegt.

Ruft die Thingspeak Seite über https://thingspeak.com/ auf und klickt oben rechts auf Sign Up.

Thingspeak-Startseite-300x142 ESP8266 AM2302 (DHT22) Sensor für Akkubetrieb, ein Projekt zum Mitmachen! (2)
Füllt das Formular aus und klickt auf Create Account. Achtet bitte darauf die korrekte Zeitzone auszuwählen!

Thingspeak-Account-anlegen-300x198 ESP8266 AM2302 (DHT22) Sensor für Akkubetrieb, ein Projekt zum Mitmachen! (2)
Auf der nun folgenden Seite klickt einfach auf New Channel.

Thingspeak-New-Channel-300x122 ESP8266 AM2302 (DHT22) Sensor für Akkubetrieb, ein Projekt zum Mitmachen! (2)
Füllt die benötigten Felder des Formulars, wie im Bild zu sehen, aus und klickt danach auf Save Channel unten auf der Seite.

Thingspeak-Channel-Daten-300x219 ESP8266 AM2302 (DHT22) Sensor für Akkubetrieb, ein Projekt zum Mitmachen! (2)Thingspeak-Channel-speichern-300x118 ESP8266 AM2302 (DHT22) Sensor für Akkubetrieb, ein Projekt zum Mitmachen! (2)
Jetzt sollte folgende Seite erscheinen, es ist jetzt ein Channel vorhanden an den wir Daten zur Visualisierung senden können.

Wir haben 2 Werte vorgegeben die wir angezeigt haben möchten, Temperatur und Luftfeuchte.

Um die Ansicht etwas zu komprimieren kann man die untere Box mit der Maus an der Titelleiste anklicken, festhalten und nach rechts verschieben. Direkt neben die erste Box. Es sieht dann so aus…

Thingspeak-Account-mit-Channel-300x228 ESP8266 AM2302 (DHT22) Sensor für Akkubetrieb, ein Projekt zum Mitmachen! (2)
Klickt jetzt bitte im mittleren Menü der Seite auf API Keys, um Daten an Thingspeak zu senden benötigen wir einen s.g. Write API Key um uns zu legitimieren.

Thingspeak-Write-API-Key-300x174 ESP8266 AM2302 (DHT22) Sensor für Akkubetrieb, ein Projekt zum Mitmachen! (2)
Schreibt euch den Key am besten auf, wir benötigen ihn nachher in der nächsten Testsoftware.

Gebt diesen Key auch niemals weiter, jeder der diesen Key hat kann Daten an euren Channel senden und das wäre ja nicht im Sinne des Erfinders 😉

Jetzt machen wir weiter mit der nächsten Testsoftware, unser heutiges Ziel ist es das sich der ESP8266 mit unserem heimischen WLAN verbindet, den Sensor ausliest und die Daten an den soeben erstellten Thingspeak Channel sendet.

Folgendes Programm muss in der IDE eingegeben werden…

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

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

#define UPDATEINTERVAL 15 //Wir aktualisieren den Thingspeak Channel alle 15 Minuten (Mindestabstand=15 Minuten)
#define CONNECTIONTIMEOUT 60 //Verbindungstimeout für die Verbindung mit unserem WLAN (Sekunden)

const char* THINGSPEAKAPIKEY = "********"; //Der Write Key des Thingspeak Channels kommt hier rein
const char* THINGSPEAKHOST = "api.thingspeak.com";

const char* WLANSSID = "********"; //Die SSID eures WLAN kommt hier rein
const char* WLANPWD = "********";  //Das WLAN Passwort eures WLAN kommt hier rein, bei einem offenen WLAN einfach leer lassen

DHT dht(DHTPIN, DHTTYPE);

void setup() {
  pinMode(LEDPIN, OUTPUT);
  pinMode(DHTPOWERPIN, OUTPUT);

  digitalWrite(DHTPOWERPIN, 1);
  digitalWrite(LEDPIN, 1);

  Serial.begin(115200);

  Serial.println(F(""));  
  Serial.println(F(""));  
  Serial.println(F("ESP8266-DHT22-AKKU-SENSOR Thingspeak Test mit Deep-Sleep..."));
  Serial.println(F(""));
  Serial.print(F("SDK-Version: "));
  Serial.println(ESP.getSdkVersion());
  Serial.print(F("ESP8266 Chip-ID: "));
  Serial.println(ESP.getChipId());
  Serial.print(F("ESP8266 Speed in MHz: "));  
  Serial.println(ESP.getCpuFreqMHz());
  Serial.print(F("Free Heap Size in Bytes: "));
  Serial.println(ESP.getFreeHeap());
  Serial.println(F(""));
 
  delay(1000);
  
  dht.begin();

  float hum = dht.readHumidity();
  float temp = dht.readTemperature();

  digitalWrite(DHTPOWERPIN, 0);

  if (isnan(hum) || isnan(temp)) {
    Serial.println(F("Sensorfehler!"));
    ESP.deepSleep(1000000,WAKE_RF_DEFAULT);
    delay(100);
  } else {
    Serial.print(F("Luftfeuchte: "));
    Serial.print(hum);
    Serial.println(F(" %"));
    Serial.print(F("Temperatur: "));
    Serial.print(temp);
    Serial.println(F(" *C"));
    Serial.println(F(""));
    
    Serial.print(F("Verbinde mit "));
    Serial.println(WLANSSID);
  
    WiFi.begin(WLANSSID, WLANPWD);

    int timeout=0;
    
    while (WiFi.status() != WL_CONNECTED) {
      delay(1000);
      Serial.print(F("."));
      timeout+=1;

      if (timeout>=CONNECTIONTIMEOUT) {
        Serial.println(F(""));
        Serial.println(F("Timeout!"));  
        
        ESP.deepSleep(1000000,WAKE_RF_DEFAULT);
        delay(100);
      }
    }

    Serial.println(F(""));
    Serial.println(F("Verbindung hergestellt"));  
    Serial.print(F("IP Addresse: "));
    Serial.println(WiFi.localIP());
  
    Serial.print(F("Verbinde mit "));
    Serial.println(THINGSPEAKHOST);
  
    WiFiClient client;

    if (!client.connect(THINGSPEAKHOST, 80)) {
      Serial.println(F(""));
      Serial.println(F("Verbindung fehlgeschlagen!"));

      ESP.deepSleep(1000000,WAKE_RF_DEFAULT);
      delay(100);
    } else {
      Serial.println(F("Verbindung erfolgreich hergestellt"));
      Serial.println(F("Sende Daten an Thingspeak Channel..."));
  
      String POSTString ="api_key=";
      POSTString += THINGSPEAKAPIKEY;
      POSTString += "&field1=";
      POSTString += temp;
      POSTString += "&field2=";
      POSTString += hum;
  
      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);
      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);
      client.stop();
      
      Serial.println(F("Verbindung zum Server beendet"));
      Serial.println(F("Daten an Thingspeak Channel gesendet"));

      WiFi.disconnect();
    
      Serial.println(F("Verbindung mit WLAN beendet"));
      Serial.println(F("Ich lege mich schlafen..."));

      ESP.deepSleep(60000000*UPDATEINTERVAL,WAKE_RF_DEFAULT);
      delay(100);
    }  
  }
}

void loop() {
}

So sollte die Ausgabe im seriellen Monitor aussehen wenn alles korrekt läuft.

Serielle-Ausgabe-Thingspeak-Testprogramm-291x300 ESP8266 AM2302 (DHT22) Sensor für Akkubetrieb, ein Projekt zum Mitmachen! (2)

Und hier die beiden Charts meines Channels, ich habe ihn Public gemacht, mit meinen aktuellen Daten. Der Abstand der Messungen muss hier nicht unbedingt passen da ich das Modul beim testen öfters neu starte.



Sollte es zu Verbindungs Timeouts kommen überprüft bitte ob eure WLAN-SSID und ggf. das WLAN Passwort korrekt angegeben sind.

Bevor es am Samstag weiter geht mit der Erklärung des letzten Test-Programmes habe ich hier noch eine etwas erweiterte Version die jetzt auch die vorhandenen WLANs anzeigt.

Diese Funktion brauchen wir später noch und ich finde es schön wenn man nach und nach alle Bausteine zusammenbaut.

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

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

#define UPDATEINTERVAL 15 //Wir aktualisieren den Thingspeak Channel alle 15 Minuten (Mindestabstand=15 Minuten)
#define CONNECTIONTIMEOUT 60 //Verbindungstimeout für die Verbindung mit unserem WLAN (Sekunden)

const char* THINGSPEAKAPIKEY = "********"; //Der Write Key des Thingspeak Channels kommt hier rein
const char* THINGSPEAKHOST = "api.thingspeak.com";

const char* WLANSSID = "********"; //Die SSID eures WLAN kommt hier rein
const char* WLANPWD = "********"; //Das WLAN Passwort eures WLAN kommt hier rein

DHT dht(DHTPIN, DHTTYPE);

void setup() {
  pinMode(LEDPIN, OUTPUT);
  pinMode(DHTPOWERPIN, OUTPUT);

  digitalWrite(DHTPOWERPIN, 1);
  digitalWrite(LEDPIN, 1);

  Serial.begin(115200);

  Serial.println(F(""));  
  Serial.println(F(""));  
  Serial.println(F("ESP8266-DHT22-AKKU-SENSOR Thingspeak Test mit Deep-Sleep und Anzeige vorhandener WLANs..."));
  Serial.println(F(""));
  Serial.print(F("SDK-Version: "));
  Serial.println(ESP.getSdkVersion());
  Serial.print(F("ESP8266 Chip-ID: "));
  Serial.println(ESP.getChipId());
  Serial.print(F("ESP8266 Speed in MHz: "));  
  Serial.println(ESP.getCpuFreqMHz());
  Serial.print(F("Free Heap Size in Bytes: "));
  Serial.println(ESP.getFreeHeap());
  Serial.println(F(""));
  Serial.println(F("WiFi-Netzwerk-Scan gestartet..."));
 
  WiFi.mode(WIFI_STA);
  WiFi.disconnect();

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

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

    if(n<=1) {
     Serial.println(F(" WiFi-Netzwerk gefunden"));
    } else {
      Serial.println(F(" WiFi-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)?" ":"*");
    }
  }

  Serial.println(F("")); 

  delay(1000);
  
  dht.begin();

  float hum = dht.readHumidity();
  float temp = dht.readTemperature();

  digitalWrite(DHTPOWERPIN, 0);

  if (isnan(hum) || isnan(temp)) {
    Serial.println(F("Sensorfehler!"));
    ESP.deepSleep(1000000,WAKE_RF_DEFAULT);
    delay(100);
  } else {
    Serial.print(F("Luftfeuchte: "));
    Serial.print(hum);
    Serial.println(F(" %"));
    Serial.print(F("Temperatur: "));
    Serial.print(temp);
    Serial.println(F(" *C"));
    Serial.println(F(""));
    
    Serial.print(F("Verbinde mit WLAN "));
    Serial.println(WLANSSID);
  
    WiFi.begin(WLANSSID, WLANPWD);

    int timeout=0;
    
    while (WiFi.status() != WL_CONNECTED) {
      delay(1000);
      Serial.print(F("."));
      timeout+=1;

      if (timeout>=CONNECTIONTIMEOUT) {
        Serial.println(F(""));
        Serial.println(F("Timeout!"));  
        
        ESP.deepSleep(1000000,WAKE_RF_DEFAULT);
        delay(100);
      }
    }

    Serial.println(F(""));
    Serial.println(F("Verbindung mit WLAN hergestellt"));  
    Serial.print(F("Zugewiesene IP Addresse: "));
    Serial.println(WiFi.localIP());
  
    Serial.print(F("Verbinde mit "));
    Serial.println(THINGSPEAKHOST);
  
    WiFiClient client;

    if (!client.connect(THINGSPEAKHOST, 80)) {
      Serial.println(F(""));
      Serial.println(F("Verbindung mit Thingspeak-Server fehlgeschlagen!"));

      ESP.deepSleep(1000000,WAKE_RF_DEFAULT);
      delay(100);
    } else {
      Serial.println(F("Verbindung mit Thingspeak-Server erfolgreich hergestellt"));
      Serial.println(F("Sende Daten an Thingspeak Channel..."));
  
      String POSTString ="api_key=";
      POSTString += THINGSPEAKAPIKEY;
      POSTString += "&field1=";
      POSTString += temp;
      POSTString += "&field2=";
      POSTString += hum;
  
      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);
      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);
      client.stop();
      
      Serial.println(F("Verbindung zum Server beendet"));
      Serial.println(F("Daten an Thingspeak Channel gesendet"));

      WiFi.disconnect();
    
      Serial.println(F("Verbindung mit WLAN beendet"));
      Serial.println(F("Ich lege mich schlafen..."));

      ESP.deepSleep(60000000*UPDATEINTERVAL,WAKE_RF_DEFAULT);
      delay(100);
    }  
  }
}

void loop() {
}


Tag 4 – Erklärung der Testsoftware und Integration eines Webservers

Jetzt folgt die Erklärung zu den Erweiterungen an der letzten, obigen, Testsoftware. Es wurden folgende Definitionen und Konstanten neu hinzugefügt:

#define UPDATEINTERVAL 15 //Wir aktualisieren den Thingspeak Channel alle 15 Minuten (Mindestabstand=15 Minuten)
#define CONNECTIONTIMEOUT 60 //Verbindungstimeout für die Verbindung mit unserem WLAN (Sekunden)

const char* THINGSPEAKAPIKEY = "********"; //Der Write Key des Thingspeak Channels kommt hier rein
const char* THINGSPEAKHOST = "api.thingspeak.com";

const char* WLANSSID = "********"; //Die SSID eures WLAN kommt hier rein
const char* WLANPWD = "********"; //Das WLAN Passwort eures WLAN kommt hier rein

Wir benötigen diese um uns mit dem eigenen WLAN zu verbinden und dann Daten an unseren ThingSpeak Channel zu übertragen, natürlich müssen da eure eigenen Daten eingetragen werden daher hier nur die ******** 😉

Um die WLANs in Reichweite zu erkennen muss der ESP8266 zuerst in den Station Modus versetzt werden, dies übernimmt die folgende Zeile.

WiFi.mode(WIFI_STA);

Jetzt trennen wir eine ggf. aufgebaute Verbindung da sonst nicht nach WLANs gesucht werden kann.

WiFi.disconnect();

Die nachfolgend deklarierte Variable n nimmt die Anzahl der gefundenen WLANs auf welche von der Funktion WiFi.scanNetworks() übergeben wurde.

int n = WiFi.scanNetworks();

Jetzt ist der Scan abgeschlossen und wir lassen uns eine Meldung darüber an den PC senden…

Serial.println(F("WiFi-Netzwerk-Scan abgeschlossen..."));
Serial.println(F(""));

Je nachdem ob, und wieviele Netzwerke gefunden werden folgt nun eine entsprechende Ausgabe.

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

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

  Serial.println(F(""));

Jetzt wollen wir natürlich auch noch wissen welche Netzwerke gefunden wurden, dazu gehen wir die gefundenen Netzwerke, die Anzahl haben wir ja in der Variablen n, durch und zeigen zu jedem Netzwerk einige Werte wie Namen, Signalstärke, und ob es verschlüsselt ist, an.

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)?" ":"*");
}

Das war jetzt schon alles was wir hinzugefügt haben um die Netzwerke welche in Empfangsreichweite liegen zu suchen und uns anzeigen zu lassen.

Die nächste Erweiterung war die Verbindung mit unerem heimischen WLAN, hier nun die Erklärung wie es gemacht wird.

WiFi.begin(WLANSSID, WLANPWD);

Diese Zeile bewirkt das der ESP8266 eine Verbindung mit dem WLAN mit der SSID WLANSSID unter Nutzung des Passwortes WLANPWD versucht herzustellen. Da es passieren kann das eine Verbindung nicht möglich ist müssen wir dafür Sorge tragen das jetzt im folgenden keine Endlosschleife entsteht und den ESP8266 über den integrierten Watchdog in den Reset treibt.

Dies lösen wir indem wir uns eine Variable zum Zählen definieren und diese mit 0 initialisieren.

int timeout=0;

Jetzt kontrollieren wir in einer Schleife ob die Verbindung hergestellt wurde.

while (WiFi.status() != WL_CONNECTED) {
  delay(1000);
  Serial.print(F("."));
  timeout+=1;

  if (timeout>=CONNECTIONTIMEOUT) {
    Serial.println(F(""));
    Serial.println(F("Timeout!"));  
        
    ESP.deepSleep(1000000,WAKE_RF_DEFAULT);
    delay(100);
  }
}

Am Anfang des Programmes haben wir uns eine Kostante für die Zeit definiert, CONNECTIONTIMEOUT, die versucht werden soll eine Verbindung herzustellen. Durch das obige delay(1000) ergibt sich somit eine max. Wartezeit von ca. CONNECTIONTIMEOUT Sekunden.

Wurde die Verbindung erfolgreich hergestellt, informiert uns folgender Code darüber und gibt uns die vom WLAN-Router zugewiesene IP-Adresse aus.

Serial.println(F("Verbindung mit WLAN hergestellt"));  
Serial.print(F("Zugewiesene IP Addresse: "));
Serial.println(WiFi.localIP());

Jetzt noch kurz eine Erläuterung dazu warum Warteschleifen mit delay beim ESP8266 nichts böses sind.

Der ESP8266 arbeitet die WiFi Funktionen im Hintergrund ab, dazu benötigt er Zeit die er bekommt wenn das Programm sich in einer Warteschleife, delay, oder einer kurzen Pause über die spezielle Funktion yield() befindet.

Würden wir in der obigen while Schleife kein delay und auch kein yield einsetzen würde es, wenn keine Verbindung hergstellt werden kann oder die Herstellung zu lange dauert, zwangsläufig zu einem Watchdog Reset kommen. Das muss vermieden werden.

Wir entscheiden im Code oben selber das nach Ablauf des Timeouts, ohne das eine Verbindung hergestellt werden konnte, ein Neustart über den Deep Sleep Timer erfolgt. Diese Lösung halte ich für die sauberste Lösung dieses Problems.

Jetzt aber zur Übertragung der Sensordaten an den Thingspeak Channel.

Gehen wir dazu davon aus, das die Verbindung zum eigenen WLAN erfolgreich hergestellt wurde.

Sollte dies nicht der Fall sein kontrolliert bitte die im Programm angegeben SSID eures WLANs.

Solltet ihr ein offenes WLAN nutzen muss die Variable bei der Definition im Programm leer bleiben.

Also so…

const char* WLANPWD = ""; //Das WLAN Passwort eures WLAN kommt hier rein

Um eine Übertragung zu starten muss unser ESP8266 Modul sich als Client beim Thingspeak Server anmelden, dies erfolgt in den folgenden Zeilen.

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

if (!client.connect(THINGSPEAKHOST, 80)) {

Wir nutzen das Ergebnis des Verbindungsversuches für eine Abfrage mit if ob die Verbindung fehlgeschlagen ist, daher die Abfrage mit !.

Basierend aufg dem Ergebnis dieser Abfrage lassen wir uns bei einem Fehlschalg dieses ausgeben und starten das System ggf. über den Deep Sleep Timer wieder neu.

Serial.println(F(""));
Serial.println(F("Verbindung mit Thingspeak-Server fehlgeschlagen!"));

ESP.deepSleep(1000000,WAKE_RF_DEFAULT);
delay(100);

Wurde die Verbindung erfolgreich hergestellt lassen wir uns auch dazu eine Meldung ausgeben.

} else {
  Serial.println(F("Verbindung mit Thingspeak-Server erfolgreich hergestellt"));
  Serial.println(F("Sende Daten an Thingspeak Channel..."));

Nun müssen wir einen POST Request an den Thingspeak Server senden um unsere Daten zu übertragen, hierzu erzeugen wir einen String den wir dann senden.

String POSTString ="api_key=";
POSTString += THINGSPEAKAPIKEY;
POSTString += "&field1=";
POSTString += temp;
POSTString += "&field2=";
POSTString += hum;

Wir übertragen folgende Werte an Thingspeak:

api_key = Unser Channel Write API Key
field1 = Der Wert für Field1 (In unserem Fall die Temperatur temp)
field2 = Der Wert für field2 (In unserem Fall die Luftfeuchte hum)

Nun müssen wir diesen String noch senden, dazu benötigen wir einen gültigen HTTP Header den wir wie folgt direkt an den Thingspeak Server senden.

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);
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"));

Wer nun genau hinsieht wird erkennen warum wir nicht auch unseren Post Request nicht direkt an den Server senden, im Header muss die Länge des nachfolgenden Requests angegeben werden!

Diese Länge ist aber variabel, je nachdem welche Daten übertragen werden.

Da wir aber den Post Request in einem String vorliegen haben können wir im Header jetzt einfach die Länge dieses Strings nutzen und als Länge des Requests senden.

Dies geschieht in dieser Zeile:

client.print(POSTString.length());

Nun übertragen wir nur noch den Post Request, also unseren String, selber an den Server und die Übertragung ist abgeschlossen.

client.print(POSTString);

Darüber lassen wir uns informieren und beenden die Verbindung zum Thingspeak Server indem wir die Clientverbindung beenden und dann die Verbindung zu unserem WLAN kappen.

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

WiFi.disconnect();
    
Serial.println(F("Verbindung mit WLAN beendet"));
Serial.println(F("Ich lege mich schlafen..."));

Nun legen wir uns, oder besser den ESP8266, einfach wieder schlafen bis zur nächsten Übertragung.

ESP.deepSleep(60000000*UPDATEINTERVAL,WAKE_RF_DEFAULT);
delay(100);

So damit wäre die Erklärung der aktuellen Testsoftware auch erledigt.

Jetzt geht es weiter, wir werden jetzt unseren Sensor so programmieren das er als WLAN-Access-Point arbeitet und uns einen Serverdienst bereit stellt über den wir uns die aktuellen Daten des Sensors in einem Webbrowser anzeigen lassen können.

Wir verzichten jetzt für dieses Beispiel auf den Deep Sleep Modus, wäre ja auch nicht sinnvoll das ein Sensor immer wieder schlafen geht und per Webbrowser nicht erreichbar wäre.

Hier nun das erste Programm zum Access-Point Modus:

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

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

const char* SENSORSSID = "DHT22-SENSOR"; //Die SSID für unser Sensor Access-Point WLAN mit dem wir uns verbinden können
 
float hum;
float temp;

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

void GetSensorData() {
  digitalWrite(DHTPOWERPIN, 1);

  delay(1000);
  
  hum = dht.readHumidity();
  temp = dht.readTemperature();

  digitalWrite(DHTPOWERPIN, 0);
}

void setup() {
  pinMode(LEDPIN, OUTPUT);
  pinMode(DHTPOWERPIN, OUTPUT);

  Serial.begin(115200);

  Serial.println(F(""));  
  Serial.println(F(""));  
  Serial.println(F("ESP8266-DHT22-AKKU-SENSOR Server Test mit Anzeige vorhandener WLANs..."));
  Serial.println(F(""));
  Serial.print(F("SDK-Version: "));
  Serial.println(ESP.getSdkVersion());
  Serial.print(F("ESP8266 Chip-ID: "));
  Serial.println(ESP.getChipId());
  Serial.print(F("ESP8266 Speed in MHz: "));  
  Serial.println(ESP.getCpuFreqMHz());
  Serial.print(F("Free Heap Size in Bytes: "));
  Serial.println(ESP.getFreeHeap());
  Serial.println(F(""));
  Serial.println(F("WiFi-Netzwerk-Scan gestartet..."));
 
  WiFi.mode(WIFI_STA);
  WiFi.disconnect();

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

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

    if(n<=1) {
     Serial.println(F(" WiFi-Netzwerk gefunden"));
    } else {
      Serial.println(F(" WiFi-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)?" ":"*");
    }
  }

  Serial.println(F("")); 
  
  dht.begin();

  WiFi.softAP(SENSORSSID);

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

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

  server.begin();

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

  digitalWrite(LEDPIN, 1);
}

void loop() {
  GetSensorData();
  
  if (isnan(hum) || isnan(temp)) {
    Serial.println(F("Sensorfehler!"));
  } else {
    Serial.print(F("Luftfeuchte: "));
    Serial.print(hum);
    Serial.println(F(" %"));
    Serial.print(F("Temperatur: "));
    Serial.print(temp);
    Serial.println(F(" *C"));
    Serial.println(F(""));
  }

  WiFiClient client = server.available();

  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);
    } else {
      RequestString = RequestString.substring(addr_start + 1, addr_end);

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

      String HTMLSite,HTMLHeader;

      HTMLSite ="<!DOCTYPE html><html><head><title>";
      HTMLSite += SENSORSSID;
      HTMLSite += "</title>";
      HTMLSite += "</head><body style='font-family:Verdana, Arial, Sans-Serif'><br /><center>";
      HTMLSite += SENSORSSID;
      HTMLSite += "<br /><br /><fieldset style='width:350px'><br /><br />";
      HTMLSite += "<u>Aktuelle Sensordaten</u><br />";
      HTMLSite += "<br />Temperatur: ";
      HTMLSite += temp;
      HTMLSite += " &deg;C<br /><br />Luftfeuchte: ";
      HTMLSite += hum;
      HTMLSite += " %<br /><br /></fieldset>";
      HTMLSite += "</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);

      client.stop();
    }
  }

  delay(2000);
}

Und hier folgt jetzt auch gleich die Erklärung…

Zuerst wird auffallen das die eigentliche Messung in eine eigene Routine gewandert ist.

void GetSensorData() {
  digitalWrite(DHTPOWERPIN, 1);

  delay(1000);
  
  hum = dht.readHumidity();
  temp = dht.readTemperature();

  digitalWrite(DHTPOWERPIN, 0);
}

Dies hat den Vorteil das es alles etwas übersichtlicher wird in Zukunf.

Als neue Konstante haben wir jetzt den Namen den das WLAN des Sensor Access-Points bekommen soll.

const char* SENSORSSID = "DHT22-SENSOR"; //Die SSID für unser Sensor Access-Point WLAN mit dem wir uns verbinden können

Neu ist auch die Zeile in der jetzt der Server-Port zugewiesen wird, ich habe jetzt einfach einmal den Port 80 gewählt da jeder Webbrowser standardmäßig darauf zugreift.

WiFiServer server(80);

Um jetzt den Access-Point Modus zu starten dient der folgende Code.

WiFi.softAP(SENSORSSID);

delay(100);

Die kurze Verzögerung mit dem delay(100) habe ich eingebaut damit bei den nachfolgenden Anzeigen der Access-Point Modus auch komplett gestartet ist und uns die korrekte IP-Adresse angezeigt wird. Ich hatte sonst den Fall das 0.0.0.0 angezeigt wurde obwohl die korrekte IP-Adresse gesetzt wurde.

Zu unserer Info werden jetzt ein paar Daten angezeigt, zum einen die SSID des Access-Point Wlans und die, eben erwähnte, IP-Adresse.

Serial.println(F("AP Modus gestartet"));
Serial.print(F("SSID: "));
Serial.println(SENSORSSID);
Serial.print(F("AP IP-Adresse: "));
Serial.println(WiFi.softAPIP());

Nun wird der eigentlkiche Server gestartet und wir bekommen dies über die serielle Verbindung mitgeteilt.

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

server.begin();

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

Zur optischen Erkennung das der Sensoir fertig gestartet ist aktivieren wir nun noch die grüne LED auf dem Modul.

digitalWrite(LEDPIN, 1);

Da wir jetzt einen Programmablauf haben der nicht nach einer Messung, oder Übertragung, beendet wird sondern kontinuierlich auf die Anfrage eines Webbrowsers warten nutzen wir nun den Bereich loop erstmalig.

void loop() {
  GetSensorData();
  
  if (isnan(hum) || isnan(temp)) {
    Serial.println(F("Sensorfehler!"));
  } else {
    Serial.print(F("Luftfeuchte: "));
    Serial.print(hum);
    Serial.println(F(" %"));
    Serial.print(F("Temperatur: "));
    Serial.print(temp);
    Serial.println(F(" *C"));
    Serial.println(F(""));
  }

  WiFiClient client = server.available();

  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);
    } else {
      RequestString = RequestString.substring(addr_start + 1, addr_end);

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

      String HTMLSite,HTMLHeader;

      HTMLSite ="<!DOCTYPE html><html><head><title>";
      HTMLSite += SENSORSSID;
      HTMLSite += "</title>";
      HTMLSite += "</head><body style='font-family:Verdana, Arial, Sans-Serif'><br /><center>";
      HTMLSite += SENSORSSID;
      HTMLSite += "<br /><br /><fieldset style='width:350px'><br /><br />";
      HTMLSite += "<u>Aktuelle Sensordaten</u><br />";
      HTMLSite += "<br />Temperatur: ";
      HTMLSite += temp;
      HTMLSite += " &deg;C<br /><br />Luftfeuchte: ";
      HTMLSite += hum;
      HTMLSite += " %<br /><br /></fieldset>";
      HTMLSite += "</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);

      client.stop();
    }
  }

  delay(2000);
}

Auch hierzu natürlich eine Erklärung was da abläuft.

Bei jedem Durchlauf dieser Endlosschleife wird zuerst einmal eine Messung angestoßen um die aktuellen Daten des Sensors zu bekommen.

GetSensorData();

Danach folgt wieder die, uns schon bekannte, Kontrolle ob gültige Daten vorliegen und ggf. deren Übertragung an den PC.

if (isnan(hum) || isnan(temp)) {
  Serial.println(F("Sensorfehler!"));
} else {
  Serial.print(F("Luftfeuchte: "));
  Serial.print(hum);
  Serial.println(F(" %"));
  Serial.print(F("Temperatur: "));
  Serial.print(temp);
  Serial.println(F(" *C"));
  Serial.println(F(""));
}

Nun schauen wir ob sich ein Webbrowser mit uns verbunden hat und uns eine Anfrage (Request) gesendet hat.

WiFiClient client = server.available();

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

Liegt eine Anfrage vor geht es so weiter…

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);
} else {
  RequestString = RequestString.substring(addr_start + 1, addr_end);

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

Es wird die Anfrage einem String (RequestString) zugeweisen, danach testen wir ob das Format der Anfrage korrekt (diese also auswertbar) ist.

Danach lassen wir uns die Anfrage zur Kontrolle an den PC senden.

Um die Anfrage, wir unterscheiden jetzt nicht gezielt was angefragt wurde, zu beantworten, also eine Webseite an den Webbrowser zu senden, setzen wir uns zwei Strings zusammen. Einen Header und die eigentliche Webseite.

String HTMLSite,HTMLHeader;

HTMLSite ="<!DOCTYPE html><html><head><title>";
HTMLSite += SENSORSSID;
HTMLSite += "</title>";
HTMLSite += "</head><body style='font-family:Verdana, Arial, Sans-Serif'><br /><center>";
HTMLSite += SENSORSSID;
HTMLSite += "<br /><br /><fieldset style='width:350px'><br /><br />";
HTMLSite += "<u>Aktuelle Sensordaten</u><br />";
HTMLSite += "<br />Temperatur: ";
HTMLSite += temp;
HTMLSite += " &deg;C<br /><br />Luftfeuchte: ";
HTMLSite += hum;
HTMLSite += " %<br /><br /></fieldset>";
HTMLSite += "</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";

Wir bauen uns zuerst die Webseite an sich zusammen um nachher im Header deren Länge mit zu übermitteln, kommt das Jemanden bekannt vor?

Nun senden wir die Daten an den Webbrowser und beenden die Verbindung.

client.print(HTMLHeader);
client.print(HTMLSite);

client.stop();

Und das war es auch schon, fast. Am Ende müssen wir ja immer 2 Sekunden warten zwischen zwei Messungen, daher noch schnell eine kleine Pause mit delay(2000);.

Installiert diese Software auf dem Modul und startet es, wenn dann die grüne LED angeht könnt ihr euch mit dem Sensor WLAN verbinden und in der Regel über die Eingabe der IP-Adresse 192.168.4.1 im Webbrowser darauf zugreifen.

Im Download ist auch noch eine Version enthalten die sich gleichzeitig mit unserem heimischen WLAN verbindet, so kann man auch über das häusliche Netzwerk auf den Sensor zugreifen.

Viel Spaß bis hierher mit dem Sensor und der ersten Software.

Ach ja jetzt 🙂

Es wäre toll wenn diejenigen die hier im Hintergrund mitbauen und mitprogrammieren einmal ein kurzes Feedback, als Kommentar oder über das Kontaktformular, zukommen lassen könnten wie sie dieses Projekt und dessen Ablauf bis jetzt so finden.

Über einen Klick HIER kommt man jetzt zum letzten Teil dieses Mitmach Projektes.


Hier findet ihr Links zum Download der eingesetzen Libraries.

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


Hier kann man sich die bisherige Software im einem ZIP-Archiv downloaden: DOWNLOAD

Verlinke diesen Beitrag:

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

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

Thomas H.

Als Betreiber dieses Blog versuche ich hier interessante Projekte und Tipps rund um die Elektronik zu bieten.
c7282393508c6050f22643a7feb8fec6?s=80&r=g ESP8266 AM2302 (DHT22) Sensor für Akkubetrieb, ein Projekt zum Mitmachen! (2)

Neueste Artikel von Thomas H. (alle ansehen)

20 Gedanken zu „ESP8266 AM2302 (DHT22) Sensor für Akkubetrieb, ein Projekt zum Mitmachen! (2)

  1. Lev

    Vielen Dank für dieses geniale Tutorial,
    kannst du aber bitte die genauen Libraries angeben, welche du verwendet hast. Es gibt mittlerweile mehrere DHT und ESP8266 Libs für die IDE. Derzeit bekomme ich IMMER ein Timeout beim DHT. Habe ein ESP-01 im Einsatz und schon verschiedene Dinge geprüft
    – Spannung ist korrekt und stabil 100W Netzteil 5V auf 3,3v mit max 800mah step down
    – beide DHT am Arduino getestet -> keine Probleme
    – mit und ohne 10k Widerstand
    – ESP-03 als Ersatz zeigt ebenfalls keine Werte
    – ESP bereits über LUA, LUA-Builder und Arduino programmiert

    Antworten
      1. Lev

        Hi Danke für die Antwort,
        das habe ich mir schon fast gedacht, mittlerweile konnte ich auch die Probleme mit dem DHT22 lösen. Das System benötigt zwangsläufig einen Stützkondensator größer 22µF. Selbst mit 22 (nichts größeres zur Hand) laufen ca 95% aller Messungen stabil.
        Ich bin auch sehr an deinem Boarddesign interessiert. Hier vllt ein paar Ideen für ein Sensoren-Komplett-BoardV2, ich wäre sehr an deiner Meinung interessiert. Gerne wäre ich bei einem Nachfolger dabei 😀

        – Wie schützt du die Lipo-Zelle vor Tiefentladung, in den Specs des LDO sehe ich keine untere Spannungsbegrenzung zum einstellen?
        – Zusätzlicher SolarPanel-Anschluss und dann über TP4056 (geringe Input-Spannung) statt über den MAX zum Laden
        – Pin 12,13 und ADC nach außen führen für BMP180 und Fotoresistor<– dort gibt es ebenfalls (Adafruits?) Libs
        – GPIO 14 dann eventuell über Mosfets da 3 Sensoren zum Schalten zuviel sind

        Antworten
        1. Thomas H. Beitragsautor

          Hallo Lev,
          ich setze Kondensatoren im Bereich 220µF – 330µF ein damit alles stabil läuft.

          Zu deinen anderen Fragen, schau mal im 3. Teil vorbei und schau dir dort die Software an dann kannst du erkennen das ich den ADC nutze um die Systemspannung zu messen und bei zu geringer Spannungs schalte ich den Sensor einfach komplett ab. Bei meinem Testboard hat sich aber gezeigt das unter 3,26 Volt (kann sicher schwanken) der LDO dicht macht und der Sensor abschaltet.

          Zur Sicherheit rate ich aber so oder so dazu eine Zelle mit integrierter Schutzschaltung zu verwenden.

          Das mit dem TP4056 hatte ich auch schon im Auge, aber ich bin da an etwas anderem dran um die Energie der Solarzelle besser zu nutzen. Mehr dazu aber später im Jahr.

          Bzgl. rausführen des ADC siehe oben wozu ich ihn nutze, zu den andern PINs kann ich nur sagen das sehr wahrscheinlich nach diesem Projekt eines kommen wird wo auch andere Sensoren angeschlossen werden können und wo auch auf SD-Card geloggt wird 😉

          Das mit dem Mosfet wird auch dabei sein dann, schon wegen der Abschaltung der Sensoren und SD-Card um Energie zu sparen, aber jetzt machen wir erst einmal das erste Projekt fertig.

          Gruß
          Thomas

          Antworten
  2. Lev

    Hi,
    ja den ADC-Part habe ich im dritten Teil durchaus gesehen, konnte mir das aber nicht erklären, da du laut Schaltung den ADC nicht verdrahtet hattest.
    Ich nutze derzeit eine 2,5W 6V Solarzelle auf einem Nordbalkon mit einer Polling-time von 1min für den Sensor, das ist definitiv zu wenig für die dunkle Jahreszeit auf einer Nordseite. Mein Chip „ESP-03“ verbraucht im Deep-Sleep satte 330µA. der DHT ist stets ON.
    Daher ist eine Umrüstung vom derzeitigen 2200mah Akku auf diese Zelle bereits geplant. http://www.hobbyking.com/hobbyking/store/uh_viewItem.asp?idProduct=18560
    Ich finde die Zelle optimal für solche Projekte.

    Wo bekommst du eigentlich deine Platinen her? Bei mir hat das alles noch so einen Bauhaus-Charakter 😀

    PS: der DHT22 mochte den heißen Lötkolben nicht, jetzt sind es stets 99% Luftfeuchte. Ich werde wohl in Zukunft auf den DHT21 umsteigen, dieser scheint einen integr. Quarz zu haben und soll lt. Specs eine längere Data-Leitung unterstützen. Also Bestens um die Solarzelle von der Elektronik von dem Temp/Feuch-Sensor zu trennen und optimal zu verteilen.

    Gruß & ich freue mich schon auf das nächste Projekt, weiter so
    Lev

    Antworten
    1. Thomas H. Beitragsautor

      Hallo Lev,

      ich beziehe meine Platinen für Privat und die Projekte im Blog in China über verschiedene Anbieter.

      Zum Thema DHT22, ich werde mit dem SI7021 und dem AM2320 mal experimentieren wenn ich wieder Zeit habe.
      Das mit deinem DHT22 ist komisch, ich habe hier beim löten noch keinen kaputt bekommen, obwohl ich gerade beim rumprobieren oft mal ein- und auslöte.
      Aber zum Glück kosten die nicht die Welt 🙂

      Ach ja, der ADC darf nicht angeschlossen sein wenn man ihn nutzt um die Versorgungsspannung vom ESP-Modul selber zu messen!

      Gruß
      Thomas

      Antworten
      1. Lev

        Ola,
        „Ach ja, der ADC darf nicht angeschlossen sein wenn man ihn nutzt um die Versorgungsspannung vom ESP-Modul selber zu messen!“ –> wieder was gelernt, vielen Dank.
        Den DHT werde ich beim Akku-Umbau mal auseinander nehmen, vllt ist dort doch etwas mehr „defekt“. Vllt hat er ja auch den Heißkleber nicht überlebt, musste ihn ans Board ankleben. xD

        Antworten
    1. Thomas H. Beitragsautor

      Hallo Alex,

      danke ist mir doch glatt durch die Lappen gegangen und lag daran das die ersten ESP-12 damals falsch beschriftet waren auf den Platinen der Module.

      Werde es mal korrigieren.

      Gruß
      Thomas

      Antworten
  3. Michael

    Hallo,

    super Arbeit.

    Kannst du mir noch den Link zur ESP8266WIFI.H Library schicken?

    Finde die nicht und beim Übersetzen, bekomme ich die Medlung das der Befehl WIFI() nicht bekannt ist.

    Antworten
    1. Thomas H. Beitragsautor

      Hallo Michael,

      die ESP8266WIFI.h ist Bestandteil der Erweiterung der Arduino IDE für den ESP8266.

      Wenn Du die Erweiterung über den Boardmanager installierst ist die Bibliothek automatisch vorhanden.

      Gruß
      Thomas

      Antworten
  4. Kai

    Hallo Thomas,

    mit etwas Verzug habe ich mittlerweile auch den Aufbau fertiggestellt und die Spannungen wie oben angegeben kontrolliert.
    Es ist die aktuellste Arduino-Version mit der ESP-Erweiterung sowie die DHT-Library installiert.

    Ich nutze einen FTDI @3V3 und Versorge das ESP-Board mit einem externen USB-Netzteil (am FTDI sind nur GND, TX, RX verbunden).
    Das ESP-Board blinkt beim bestromen kurz blau auf.

    Leider erhalte ich nachdem Kompilieren eine Fehlermeldung:
    warning: espcomm_sync failed
    error: espcomm_open failed
    error: espcomm_upload_mem failed

    Man sieht an der TX-Led am FTDI, dass er mehrfach etwas sendet, aber dann keine Kommunikation zustande kommt.
    Ich habe schon alle Baudraten durchprobiert. Kein Erfolg.

    In Putty habe ich einmal reingeschaut, was das ESP-Modul beim Bootup sendet (laut Google sollte da eine Boardinfo kommen).
    Es wird tatsächlich etwas empfangen, leider jedoch nur kryptische Buchstaben (falsche Baudrate? FTDI-Problem?)

    Mit dem FTDI arbeite ich seit Jahren sehr erfolgreich mit Arduinos… in diesem Umfeld funktioniert er also.

    Danke dir!

    VG
    Kai

    Antworten
    1. Thomas H. Beitragsautor

      Hallo Kai,

      es kann mehrere Gründe haben, zuerst die Baudrate, es gibt/gab Module die sich bei 9600 Baud meldeten und welche bei 57600 Baud. Aber zuerst einmal checke die Lötstellen am Modul, evtl. gibt es da ein Problem.

      Zur Not probiere einmal die Baudrate auf 921600 Baud zu stellen, so flashe ich alle meine Module. Aber es sollte auch mit 115200 Baud gehen, und schnell genug, sein.

      Ich nutze hier aktuell keinen FTDI Adapter sondern nur CP210X.

      Wünsche viel Erfolg.

      Gruß
      Thomas

      Antworten
  5. Kai

    Hallo Thomas,

    Lötstellen waren alle i.O.

    Ich habe es jetzt mit 115200baud hinbekommen, wobei ich dabei auch manchmal mehrere Anläufe brauche…
    Bin mir aber nicht sicher, obs an meinem Programmer oder ggf dem ESP liegt, das sich schwertut in den Programmiermode zu gehen.

    VG
    Kai

    Antworten
    1. Thomas H. Beitragsautor

      Hallo Kai,

      freut mich das es jetzt klappt.
      Manchmal sind auch die Jumper schuld.

      Gruß
      Thomas

      Antworten
  6. Canonica

    Hallo Thomas

    Zuerst einmal herzlichen Danke für deine Anstrengungen und Bemühungen dich mit einem solchen Aufwand aufzuopfern.

    Ich habe betreffend deinen Tutorials eine bzw. mehrere Fragen.
    Zuerst einmal läuft meine von dir nachgebaute Schaltung gut. Jedoch verwende ich ein Adafruit HUZZAH ESP8266 welcher sich recht gut verhält.

    Leider bekomme ich nach dem Upload zur Thingspeak Realisierung eine Fehlermeldung
    `Exception (29):
    epc1=0x4000e1b2 epc2=0x00000000 epc3=0x00000000 excvaddr=0x00000100 depc=0x00000000
    ets Jun 1 2016,rst cause:4, boot mode:(3,6)
    wdt reset
    ets Jun 1 2016,rst cause:4, boot mode:(3,6)
    wdt reset`

    load 0x4010f000, len 1264, room 16
    tail 0
    chksum 0x0f
    csum 0x0f
    ~ld

    ESP8266-DHT22-AKKU-SENSOR Thingspeak Test mit Deep-Sleep…

    SDK-Version: 1.5.2(7eee54f4)
    ESP8266 Chip-ID: 1038064
    ESP8266 Speed in MHz: 80
    Free Heap Size in Bytes: 48216

    Luftfeuchte: 48.60 %
    Temperatur: 23.70 *C

    Verbinde mit Chilla
    …………………………………….
    und der ganze kram beginnt von vorne.
    Hättest du eine Ahnung an was das liegen könnte? Herzlichen Dank für deine rasche antwort.

    Fabio

    Antworten
  7. Konrad

    Super Projekt möchte gerne mitmachen, wann gibt es den aktuellen Bausatz?

    Hallo zusammen,

    habe ein ähnliches Problem wie Canonica beim hochladen des Testprogramm Code für Sensor DHT22. Nutze eine ESP 01 als Versuchsaufbau (erweiterter ESP mit herausgeführten GPIO´s 04,05,14 u.15 . GPIO16 auf RST gezogen für Deep Sleep.
    Folgender Fehlercode wird am seriellen Monitor ausgegeben:

    ets Jan 8 2013,rst cause:4, boot mode:(3,1)

    wdt reset
    load 0x4010f000, len 1384, room 16
    tail 8
    chksum 0x2d
    csum 0x2d
    v09f0c112
    ~ld
    þ
    ESP8266-DHT22-AKKU-SENSOR DHT22 Test…

    versuche schon seit mehreren Tagen das Problem zu lösen, leider ohne Erfolg.
    Hat jemand von euch einen Tipp. Wäre dankbar für jeden noch so kleinen Hinweis. Die angegebenen links von Canonica helfen mir leider nicht weiter meine Englischkenntnisse reicht nicht für die Lösung des Problems

    Antworten
  8. Helmut Richter

    Hallo Thomas,

    ein kurze Frage zur Stückliste. Kannst Du eine Typangabe zur Minibuchse für den Akku machen, ich suche nun schon geraume Zeit ohne auch nur etwas ähnliches zu finden. Wahrscheinlich verwende ich die falschen Suchbegriffe.

    Vielen Dank im Voraus
    Helmut

    Antworten

Schreibe einen Kommentar

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