BitBastelei #190 – ESP8266 & AMS2302 WLAN-Temperatur- und Feuchtesensor

BitBastelei #190 - ESP8266 & AMS2302 WLAN-Temperatur- und Feuchtesensor

(113 MB) 00:31:40

2016-03-27 10:00 🛈

Vor etwa einem Jahr hatte ich als Beispiel schon mal einen DHT22/AMS2302 Temperatur- und Feuchtesensor mit dem ESP8266 verbunden. Seinerzeit recht ineffizient mit fertiger Firmware. Da ich für einen Serverraum kurzfristig ein Monitoring brauche legen wir das Ganze nochmal neu auf – diesmal mit eigener Firmware, welche die Daten direkt an Volkszähler oder einen anderen Dienst sendet und zwischen den Messungen stromsparend in den Schlafmodus geht. Leider ist bei dem hier verwendeten ESP-01 eine Hardwaremodifikation nötig um Deep-Sleep zu ermöglichen.

Zeitmarken

  • 00:00 Aufbauplanung
  • 04:54 Deep-Sleep-Modifikation
  • 06:22 Software
  • 19:01 Flashen & ESP01-Stromverbrauch
  • 23:53 Vom Breadboard zum Streifenraster / 3.3-Regler
  • 29:15 Fazit

Links zum Thema

Deep-Sleep-Modifikation an ESP-01

Um die Deep-Sleep-Funktion an einem ESP-01-Modul nutzen zu können muss GPIO16 mit RESET verbunden werden.

Bild: https://www.adlerweb.info/blog/wp-content/uploads/2016/03/esp01-deepsleep-300×171.png

Beschaltung

  • >=1µF Elko und 100nF Kerko zwischen USB-VCC und GND
  • 5V via 3.3V-Spannungsregler (z.B. AMS1117-3.3) an DHT und ESP
  • >=1µF Elko und 100nF Kerko zwischen 3.3V-VCC und GND
  • GND an DHT und ESP
  • 10k? Pullup an ESP-Pins GPIO0, GPIO, RESET und CH_PD
  • 100nF Kondensator zwischen CH_PD und GND
  • 100nF Kondensator an Stromversorgung des DHT22

Bild: https://www.adlerweb.info/blog/wp-content/uploads/2016/03/espdht-1-300×169.png

Code

https://gist.githubusercontent.com/adlerweb/405f2aa5dc1084e697c7/

#include <Arduino.h>

// wenn aktiv: Meldungen per Serial
#define SERIAL

// wenn auskommentiert: delay()
// wenn aktiv: deep sleep nutzen (Hardwaremodifikation notwendig)
#define DEEP

//sekunden zwischen Aufwachvorgängen
#define WAIT 120

const String host = "192.168.123.123";
const unsigned int port = 80;

const String url_start = "/vz/htdocs/middleware.php/data/";
const String url_stop = ".json?operation=add&value=";

const String uuid_temp = "**UUIDTEMPERATUR**";
const String uuid_humid = "**UUIDFEUCHTE**";

byte maxwait = 120; //Wifi must connect in < x seconds

#define DHTPIN            2         // Pin which is connected to the DHT sensor.
#define DHTTYPE           DHT22     // DHT 22 (AM2302)







#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>

#include <ESP8266HTTPClient.h>

#include <Adafruit_Sensor.h>
#include <DHT.h>
#include <DHT_U.h>

ESP8266WiFiMulti WiFiMulti;

DHT_Unified dht(DHTPIN, DHTTYPE);

void setup() {
  #ifdef SERIAL
    Serial.begin(115200);
    Serial.println("BOOT");

    Serial.print("Wifi...");
  #endif

  WiFiMulti.addAP("freifunk-myk.de");

  #ifdef SERIAL
    Serial.println("OK");
    Serial.print("DHT...");
  #endif

  dht.begin();

  #ifdef SERIAL
    Serial.print("OK");
  #endif

  sensor_t sensor;
  #ifdef SERIAL
    dht.temperature().getSensor(&sensor);
    Serial.println("------------------------------------");
    Serial.println("Temperature");
    Serial.print  ("Sensor:       "); Serial.println(sensor.name);
    Serial.print  ("Driver Ver:   "); Serial.println(sensor.version);
    Serial.print  ("Unique ID:    "); Serial.println(sensor.sensor_id);
    Serial.print  ("Max Value:    "); Serial.print(sensor.max_value); Serial.println(" °C");
    Serial.print  ("Min Value:    "); Serial.print(sensor.min_value); Serial.println(" °C");
    Serial.print  ("Resolution:   "); Serial.print(sensor.resolution); Serial.println(" °C");
  #endif
  dht.humidity().getSensor(&sensor);
  #ifdef SERIAL
    Serial.println("------------------------------------");
    Serial.println("Humidity");
    Serial.print  ("Sensor:       "); Serial.println(sensor.name);
    Serial.print  ("Driver Ver:   "); Serial.println(sensor.version);
    Serial.print  ("Unique ID:    "); Serial.println(sensor.sensor_id);
    Serial.print  ("Max Value:    "); Serial.print(sensor.max_value); Serial.println("%");
    Serial.print  ("Min Value:    "); Serial.print(sensor.min_value); Serial.println("%");
    Serial.print  ("Resolution:   "); Serial.print(sensor.resolution); Serial.println("%");
    Serial.println("------------------------------------");
  #endif
}

bool waitWifi() {
  while((WiFiMulti.run() != WL_CONNECTED) && maxwait > 0) {
      #ifdef SERIAL
        Serial.println("Wait Wifi");
      #endif
      delay(1000);
      maxwait--;
  }

  if(WiFiMulti.run() == WL_CONNECTED) return true;
  return false;
}

void sendHttpData(String url) {
    HTTPClient http;

    if(waitWifi()) {

      #ifdef SERIAL
        Serial.print("GET: "); Serial.println(url);
      #endif
      http.begin(host, port, url); //HTTP
      int httpCode = http.GET();
      #ifdef SERIAL
      if(httpCode) {
          if(httpCode == 200) {
              String payload = http.getString();
              Serial.println(payload);
          }else{
            Serial.print("HTTP "); Serial.println(httpCode);
          }
      } else {
          Serial.print("[HTTP] GET... failed, no connection or no HTTP server\n");
      }
      #endif
    }else{
      #ifdef SERIAL
        Serial.print("No WiFi available\n");
      #endif
    }
}

void loop() {

  String url_temp = "";

  #ifndef SERIAL
    digitalWrite(1, HIGH); //LED off
  #endif

  delay(2000); //If we've just started the power might be somewhat distorted - lets wait a bit to get things setteled...

  sensors_event_t event;
  
  dht.temperature().getEvent(&event);
  if (isnan(event.temperature)) {
    #ifdef SERIAL
      Serial.println("Error reading temperature!");
    #endif
  } else{
    #ifdef SERIAL
      Serial.print("Temperature: ");
      Serial.print(event.temperature);
      Serial.println(" °C");
    #endif
    url_temp = url_start;
    url_temp += uuid_temp;
    url_temp += url_stop;
    url_temp += event.temperature;

    sendHttpData(url_temp);
  }

  dht.humidity().getEvent(&event);
  if (isnan(event.relative_humidity)) {
    #ifdef SERIAL
      Serial.println("Error reading humidity!");
    #endif
  }
  else {
    #ifdef SERIAL
      Serial.print("Humidity: ");
      Serial.print(event.relative_humidity);
      Serial.println("%");
    #endif
    url_temp = url_start;
    url_temp += uuid_humid;
    url_temp += url_stop;
    url_temp += event.relative_humidity;

    sendHttpData(url_temp);
  }
  #ifdef SERIAL
    Serial.println("SLEEP");
    Serial.flush();
  #endif

  #ifdef DEEP
    ESP.deepSleep(1000000 * WAIT);
  #else
    //@todo disconnect WiFi to save power?
    delay(1000 * WAIT);
  #endif
}

Edits

  • Pinout: GPIO0 und GPIO2 waren vertauscht, danke an Felix für den Hinweis

28 Gedanken zu „BitBastelei #190 – ESP8266 & AMS2302 WLAN-Temperatur- und Feuchtesensor“

  1. Hi. Danke für das gute Video. Ich habe ein AI-Thinker DevBoard mit einem EPS8266-12E. Diesen möchte ich so ähnlich nutzen wie Du. Aber ich würde gerne die Daten per MQTT verschicken für Openhab u.s.w. Vielleicht wäre das ja auch noch ein Video wert.

  2. Vielen Dank für das interessante Projekt! Ich hab mir das für Domoticz nachgebaut und die Bibliothek WifiManager gefunden. Damit versucht der ESP zuerst, sich mit dem letzten WLAN zu verbinden. Schlägt das fehl, macht er einen eigenen AP auf. Verbindet man sich mit dem, bekommt man ein Webformular angezeigt, in das man die Daten für den zu verwendeten AP eintragen kann. Ist vor allem für wechselnde Einsatzorte interessant.

    https://github.com/tzapu/WiFiManager

  3. Erstmal: tolle Bastelidee!

    Hab es mir für ein kleines Wetterstationsprojekt nachgebaut. Bin dabei aber leider auf ein Problem gestossen, welches ich nicht lösen konnte – evtl. hast du ja noch eine Idee:
    Nachdem ich die Änderungen am ESP-01 für den deep Sleep gemacht habe und dann deinen Code mit Sleep laufen lasse bekomme ich 1x die Werte aber nach dem Sleep/Reset bekomme ich über die Konsole nur noch „Error reading temperature!“…
    Wenn ich den Sleep auskommentiere läuft es ohne Probleme. Hab es versuchsweise auch mal mit einem nicht modifizierten ESP-01 gemacht und dort kam er nicht mehr aus dem deep Sleep zurück. Also denke ich, dass der Umbau schon passt…

    Da ich für mein Projekt gerne auch Akku/Batterie betriebene Sensoren haben wollte wäre der Deep Sleep für mich ideal.

    1. Hallo,

      so direkt sagt mir der Fehler nichts. Was helfen könnte:

      • Größeres Delay zwischen Start/Aufwachen des Controllers und erstem auslesen des Sensors
      • Prüfen ob am Temperatursensor ein Entstörkondensator (ca. 100nF) vorhanden ist und ggf. dort noch einen hin löten

      EDIT: Der Kondensator am Temperatursensor hat geholfen

  4. Hallo,

    ich habe nur eine Frage, da ich ein Problem mit Farben habe, könntest du noch in der „Stückliste“ aufnehmen, welche Widerstände du verwendet hast?

    1. Hallo,
      die sind schon bei Bestückung angegeben: Alle 10k?. Da nur Pullup aber auch nicht so kritisch, sollte alles zwischen >1k? und <100k? funktionieren.

      Btw: Du solltest dir evtl überlegen den E-Mail-Provider zu wechseln – dein jetziger blockiert statt ausschließlich SPAM auch komplette Konkurrenzanbieter – egal ob „gute“ oder „böse“. Konnte entsprechend die Antwort nicht zusätzlich per Mail senden.

  5. Oh, stimmt! Jetzt sehe ich das auch!
    Habe ich wohl überlesen weil mir „Ohm“ gefehlt hat.

    Gut zu wissen mit der Email werde mich darum kümmern!

  6. Hi,

    Great video Thanks! Got it all working now.
    Have a question on the current measuring part with the ossiloscope.

    How do you measure the current? A resitor in series and doing a differential measurement or perhaps a current measuring probe?
    And how to setup the scope so that it shows mAmps like in the video.

    Took a look at the current probe solution but it points outs that a current probe is much more expensive than the SDS 1102CNL scope itself. Not a real option for me.

    Btw Reading German is not an issue. Writing on the other hand…..:-)

    1. Hi,
      sorry for the late reply – somewhat missed the notification.
      I use a 1? Resistor on the negative rail. The oscilloscope is connected to both sides where ground is common between both devices. This allows it to directly measure current without differential Signals – so I can still use the second channel for other mesurements.
      Display can be changed between volt and amp on the third page of the channel setup. Whith 1? and 1x probe the values should be correct.
      Keep in mind 1? is rather large and will not work on circuits sensitive to input voltage quality – at 1A we’re loosing 1V which is too much for most ICs. It is possible to use a smaller resistor, but afair the scope cannot scale the view below 1? and the resolution may suffer.

  7. Tach Kommando zurück

    Hat mir keine ruhe gelassen das Problem mit der Arduino IDE .
    Habe alle Bibliotheken die Fehler hatten neu von Hand installiert.
    Alles super jetzt läuft es und das einbinden des ESP war nurnoch eine kleinichkeit.
    Volkszähler wird jetzt schön mit Messwerten gefüttert.
    Danke für alles und lösch den anderen Eintrag am besten .
    Habe mich oft verschrieben sorry dafür.

  8. Hallo, vielen Dank für das Video und den Code. Mit den nötigen Anpassungen lief es auf anhieb!
    Ich würde mir nun noch wünschen, dass Du ein ähnliches Beispiel mit dem ESP8266 und dem DS18B20 mit VZ erstellen könntest. Im Web werde ich da nicht wirklich fündig. Mir fehlt momentan das Know How, dies selbst zu erarbeiten.

    Über eine Antwort würde ich mich sehr freuen!

    Vielen Dank.

  9. Respekt!! Sehr Gutes Video, Danke dafür.

    Probiere mich gerade ohne erfolg darin, dein Projekt mit einem analogen Bodenfeuchtesensor nachzubauen und in Volkszähler einzubinden.

    Also falls du ein Video machen möchtest 😉

  10. Das Komplette Projekt wollte ich so aufbauen:
    iobroker zur hausautomatisierung und Darstellung (funktioniert schon)

    und einen esp8266 mit bodenfeuchtesensor und batterie pro pflanze zur feuchtigkeitsüberwachung der erde.

    Und das ganze im Volkszähler loggen und in iobroker einbinden der dann die aktuelle bodenfeuchte anzeigt und gegebenenfalls einen Alarm anzeigt wen gegossen werden mus.

  11. Okay, Problem gefunden. Aber leider:

    GET: /vz/htdocs/middleware.php/data/enfernteUUID.json?operation=add&value=54.20
    HTTP 404

    Und im Volkszähler landen auch keine Daten.

    Ich bin ratlos

  12. Hallo,

    404 heißt, dass der Pfad nicht gefunden wurde. Sicher, dass der so stimmt? Im Browser sollte bei middleware.php eine Nachricht mit „Missing or invalid PATH_INFO“ auftauchen.

  13. ein freundliches hallo,
    ich habe das jetzt versucht nachzubauen, aaaaber ich bekomme beim sketch hochladen immer diese meldung, womit ich nichts anfangen kann.
    vielleicht hast du ja einen tip. ich habe verschiedene esp01 versucht, kompilieren geht – hochladen nicht. comport ist ok. ich benutze einen usb-adapter speziell für diese esp01 weil ich keinen blassen habe wie sonst. hier mal die meldung von ard… :

    Arduino: 1.8.5 (Windows 10), Board: „Generic ESP8266 Module, 80 MHz, ck, 26 MHz, 40MHz, QIO, 512K (no SPIFFS), 2, v2 Lower Memory, Disabled, None, Only Sketch, 115200“

    Archiving built core (caching) in: C:\Users\RSOLDIE\AppData\Local\Temp\arduino_cache_216878\core\core_esp8266_esp8266_generic_CpuFrequency_80,ResetMethod_ck,CrystalFreq_26,FlashFreq_40,FlashMode_qio,FlashSize_512K0,led_2,LwIPVariant_v2mss536,Debug_Disabled,DebugLevel_None____,FlashErase_none,UploadSpeed_115200_ecbc24c8479f7fa6a9ef227553a8a3a7.a
    Der Sketch verwendet 272236 Bytes (54%) des Programmspeicherplatzes. Das Maximum sind 499696 Bytes.
    Globale Variablen verwenden 34164 Bytes (41%) des dynamischen Speichers, 47756 Bytes für lokale Variablen verbleiben. Das Maximum sind 81920 Bytes.
    C:\Users\RSOLDIE\AppData\Local\Arduino15\packages\esp8266\tools\esptool\0.4.13/esptool.exe -vv -cd ck -cb 115200 -cp COM4 -ca 0x00000 -cf C:\Users\RSOLDIE\AppData\Local\Temp\arduino_build_389724/esp8266tempLF.ino.bin
    esptool v0.4.13 – (c) 2014 Ch. Klippel
    setting board to ck
    setting baudrate from 115200 to 115200
    setting port from COM1 to COM4
    setting address from 0x00000000 to 0x00000000
    espcomm_upload_file
    espcomm_upload_mem
    setting serial port timeouts to 1000 ms
    opening bootloader
    resetting board
    trying to connect
    flush start
    setting serial port timeouts to 1 ms
    setting serial port timeouts to 1000 ms
    Beim Hochladen des Sketches ist ein Fehler aufgetreten
    flush complete
    espcomm_send_command: sending command header
    espcomm_send_command: sending command payload
    espcomm_send_command: receiving 2013 bytes of data
    read 0, requested 1
    error: failed reading byte
    warning: espcomm_send_command: can’t receive slip payload data
    trying to connect
    flush start
    setting serial port timeouts to 1 ms
    setting serial port timeouts to 1000 ms
    flush complete
    espcomm_send_command: sending command header
    espcomm_send_command: sending command payload
    espcomm_send_command: receiving 2013 bytes of data
    read 0, requested 1
    error: failed reading byte
    warning: espcomm_send_command: can’t receive slip payload data
    trying to connect
    flush start
    setting serial port timeouts to 1 ms
    setting serial port timeouts to 1000 ms
    flush complete
    espcomm_send_command: sending command header
    espcomm_send_command: sending command payload
    espcomm_send_command: receiving 2013 bytes of data
    read 0, requested 1
    error: failed reading byte
    warning: espcomm_send_command: can’t receive slip payload data
    resetting board
    trying to connect
    flush start
    setting serial port timeouts to 1 ms
    setting serial port timeouts to 1000 ms
    flush complete
    espcomm_send_command: sending command header
    espcomm_send_command: sending command payload
    espcomm_send_command: receiving 2013 bytes of data
    read 0, requested 1
    error: failed reading byte
    warning: espcomm_send_command: can’t receive slip payload data
    trying to connect
    flush start
    setting serial port timeouts to 1 ms
    setting serial port timeouts to 1000 ms
    flush complete
    espcomm_send_command: sending command header
    espcomm_send_command: sending command payload
    espcomm_send_command: receiving 2013 bytes of data
    read 0, requested 1
    error: failed reading byte
    warning: espcomm_send_command: can’t receive slip payload data
    trying to connect
    flush start
    setting serial port timeouts to 1 ms
    setting serial port timeouts to 1000 ms
    flush complete
    espcomm_send_command: sending command header
    espcomm_send_command: sending command payload
    espcomm_send_command: receiving 2013 bytes of data
    read 0, requested 1
    error: failed reading byte
    warning: espcomm_send_command: can’t receive slip payload data
    resetting board
    trying to connect
    flush start
    setting serial port timeouts to 1 ms
    setting serial port timeouts to 1000 ms
    flush complete
    espcomm_send_command: sending command header
    espcomm_send_command: sending command payload
    espcomm_send_command: receiving 2013 bytes of data
    read 0, requested 1
    error: failed reading byte
    warning: espcomm_send_command: can’t receive slip payload data
    trying to connect
    flush start
    setting serial port timeouts to 1 ms
    setting serial port timeouts to 1000 ms
    flush complete
    espcomm_send_command: sending command header
    espcomm_send_command: sending command payload
    espcomm_send_command: receiving 2013 bytes of data
    read 0, requested 1
    error: failed reading byte
    warning: espcomm_send_command: can’t receive slip payload data
    trying to connect
    flush start
    setting serial port timeouts to 1 ms
    setting serial port timeouts to 1000 ms
    flush complete
    espcomm_send_command: sending command header
    espcomm_send_command: sending command payload
    espcomm_send_command: receiving 2013 bytes of data
    read 0, requested 1
    error: failed reading byte
    warning: espcomm_send_command: can’t receive slip payload data
    warning: espcomm_sync failed
    error: espcomm_open failed
    error: espcomm_upload_mem failed

    vielen dank im voraus
    mfg ralf

    1. Der Fehler heißt, dass der PC nicht mit dem ESP01 kommunizieren kann. Ist der richtige Port ausgewählt? Am ESP01 die GPIOs im Programmiermodus (0=LOW, 2=HIGH) und neu gestatet?

  14. Hallo, moin moin und guten abend!
    Ersteinmal dicker Daumen-hoch für die gute Beschreibung!

    Ich bin relativ neu im Thema der Arduino-Programmierung und scheitere gerade an einem Fehler!

    Ich habe das Projekt quasi nachgebaut. Ich nutze einen ESP8266 um Temperaturwerte mit einem BME680 über i²C aufzunehmen. Der ESP8266 soll die Werte dann an einen vzlogger auf einem raspberrypi senden. Und genau da hakt es!
    Mittlerweile habe ich den Sketch soweit, dass mir das http.get eine -1 zurückgibt.
    Gebe ich den Link, den das Sketch zusammensetzt, direkt im Browserfenster ein, so wird der Wert an die middleware gegeben und auch angezeigt. Leider nicht über den ESP8266.

    Wo mag das Problem liegen?
    Besten Dank für die Hilfe!

    1. Hmmm… Schuss ins Blaue: Brauch der Server vielleicht HTTPS? Mit dem Code kann der ESP nur unverschlüsselt per HTTP senden.

  15. hi,
    super, habe es gleich nach gebaut.
    mir ist aufgefallen das meine Werte nicht ganz übereinstimmen mit zwei anderen Thermometern. Die Temperatur ist 1°C zu hoch und die Feuchtigkeit ist 10% zu hoch. kann man das in der Software irgendwie anpassen. Ich nutze den DHT11 habe es im Sketch geändert. Weiß aber nicht genau wie ich die Werte anpassen kann.

Schreibe einen Kommentar zu adlerweb Antworten abbrechen

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