Bodenfeuchtigkeit messen mit dem ESP32 + Home Assistant Integration

Wenn du Schwierigkeiten hast, deine Pflanzen am Leben zu erhalten, oder ein begeisterter Statistikfan bist, der es liebt, Bodenfeuchtigkeit über Wochen und Monate zu verfolgen und zu analysieren, dann ist dieser Beitrag genau das Richtige für dich. Ich habe ein ausgefeiltes Skript entwickelt, das herkömmliche, analoge Bodenfeuchtigkeitssensoren automatisch kalibriert, deren Werte in Prozent ausgibt und die Daten mittels MQTT auch an Home Assistant usw. überträgt.

Was Du benötigst:

Hardware: * Achtung Amazon Affiliate
Einen Mikrocontroller wie ESP32 oder Arduino. Da der Code keine speziellen Bibliotheken verwendet und abgesehen von der Stromversorgung des Sensors lediglich einen Pin benötigt, ist er auf den meisten Geräten einsetzbar. Falls du jedoch eine batteriebetriebene, langfristige Überwachung deiner Pflanzen anstrebst, empfehle ich den FireBeetle 2 ESP32-E. Mit diesem Modell habe ich beeindruckende Batterielaufzeiten von mehreren Monaten erreicht. Außerdem benötigest du einen Bodenfeuchtigkeitssensor (soil moisture sensor).
Software:
Arduino IDE
Homeassistant + MQTT Broker

* Achtung Amazon Affiliate

Die Verkabelung

Verbinde das Pluskabel (+) mit einem 3V- oder 5V-Pin. Wenn du, wie ich, einen ESP32 verwendest, ist der GPIO35 eine gute Wahl. Bei einem ESP32 im D1-Format oder einem anderen Mikrocontroller wie Arduino, solltest du in den Spezifikationen deines Geräts nach einem geeigneten analogen Pin suchen, denn dieser ist notwendig, um die Daten des Sensors zu empfangen. Stelle sicher, dass du den entsprechenden GPIO-Pin auch im Code anpasst.

Inbetriebnahme

Im oberen Teil des Codes ist es notwendig, die WLAN- und MQTT-Konfigurationen festzulegen. Falls du noch keinen MQTT-Benutzer in Homeassistant hast, erstelle einfach einen neuen Admin-Benutzer in Homeassistant und trage dessen Daten in den Code ein. Beachte, dass die Berechtigungen der Homeassistant-Benutzer auch für MQTT relevant sind.

Energieeffizienz ist entscheidend

Berücksichtige, dass WLAN, Bluetooth und Sensorabfragen viel Energie verbrauchen. Diese Faktoren sind ausschlaggebend, um die Akkulaufzeit deines Geräts deutlich zu verlängern. Im Code kannst du die Variable „sleepTimeSeconds“ anpassen, um zu steuern, wie häufig die Feuchtigkeitsdaten an Homeassistant übermittelt werden. Zu Beginn, besonders während des Debuggings, kannst du niedrigere Werte wählen. Sobald alles reibungslos funktioniert, empfehle ich, die Abfragefrequenz auf einmal pro Stunde oder sogar seltener zu reduzieren. Mit dieser Einstellung kannst du bei einem 3000mAh-Akku eine Laufzeit von etwa sechs Monaten erreichen.

Automatische Kalibrierung

Die meisten Bodenfeuchtigkeitssensoren erfordern eine Kalibrierung, bei der du normalerweise die spezifischen Werte für jeden Sensor manuell ermitteln und im Skript eintragen musst. Dies kann mühsam sein, insbesondere wenn mehrere Sensoren in Betrieb genommen werden sollen, da die Werte je nach Kabellänge, gewähltem Pin und Lötstelle variieren können. Ich habe zur Vereinfachung des Prozesses eine automatische Kalibrierung implementiert. Nachdem der ESP32 mit dem Sensor programmiert wurde, hast du 20 Sekunden Zeit, um die Minimal- und Maximalwerte zu kalibrieren. Das funktioniert am besten, indem der Sensor während des Programmierens durch die Arduino IDE absolut trocken bleibt. Sobald der Programmierungsvorgang abgeschlossen ist warte 2-3 Sekunden und tauche den Sensor binnen 20 Sekunden in Wasser. Auf diese Weise lernt der ESP32 die minimalen und maximalen Werte und zeigt die Feuchtigkeitswerte fortan in Prozent an. Die Kalibrierung bleibt dauerhaft gespeichert, selbst nach einem Stromverlust des ESP32. Sollten 20 Sekunden für die Kalibrierung nicht ausreichen, kannst du die Variable „calibrationPeriod“ im Code anpassen und den Wert erhöhen. Beobachte auch die Konsolenausgabe, denn der ESP32 sollte dir die ermittelten Werte anzeigen.

Rekalibrierung
Nach der erstmaligen Kalibrierung werden die Daten permanent im nichtflüchtigen Speicher (NVS) des ESP32 gesichert. Solltest du eine erneute Kalibrierung des ESP32 wünschen, kannst du das nachstehende Skript verwenden. Dieses Skript bereinigt den nichtflüchtigen Speicher des ESP32 vollständig. Nachdem der Speicher gelöscht wurde, kannst du den ursprünglichen Code des Pflanzensensors wieder aufspielen und den Kalibrierungsprozess von Neuem beginnen.

#include <Arduino.h>
#include <Preferences.h>

Preferences preferences;

void setup() {
  Serial.begin(115200);
  
  // Initialisierung des Preferences-Speichers
  preferences.begin("moisture", false);

  // Überprüfen, ob die Kalibrierungsdaten bereits gelöscht wurden
  bool isCleared = preferences.getBool("isCleared", false);

  if (!isCleared) {
    // Löschen des Speicherbereichs, wenn er noch nicht gelöscht wurde
    Serial.println("Lösche Kalibrierungsdaten...");
    preferences.clear();

    // Setzen der Flagge, dass die Daten gelöscht wurden
    preferences.putBool("isCleared", true);

    // Bestätigung der Löschung
    Serial.println("Kalibrierungsdaten wurden zurückgesetzt.");
  } else {
    Serial.println("Kalibrierungsdaten wurden bereits gelöscht.");
  }

  // Schließen der Preferences
  preferences.end();

  // Warten, um die Ausgabe im seriellen Monitor zu sehen
  delay(2000);

  // Neustart oder weiteren Code ausführen
  Serial.println("System wird neu gestartet.");
  ESP.restart();
}

void loop() {
  // Der Loop-Block bleibt leer, da alle Aktionen im Setup-Block durchgeführt werden.
}

Der Code für die Bodenfeuchtigkeitsüberwachung

#include <Arduino.h>
#include <WiFi.h>
#include <PubSubClient.h>
#include <Preferences.h>

const int moistureSensorPin = 35;  // Pin-Nummer des Feuchtigkeitssensors

Preferences preferences;  // Präferenzenspeicher für Kalibrierungswerte
int airValue;             // Kalibrierungswert für trockene Umgebung
int waterValue;           // Kalibrierungswert für nasse Umgebung
unsigned long startTime;  // Startzeit für die Kalibrierungsphase
const unsigned long calibrationPeriod = 20000;  // Kalibrierungszeit in Millisekunden (20 Sekunden)
const unsigned long sleepTimeSeconds = 20;  // Schlafzeit des Sensors in Sekunden (hier auf 20 Sekunden gesetzt)

// WLAN-Informationen (ersetzen Sie die Werte durch generische oder entfernen Sie sie)
const char* ssid = "[SSID]";            // WLAN-SSID
const char* password = "[PASSWORT]";    // WLAN-Passwort
const char* mqttServer = "[MQTT_SERVER_IP]";  // MQTT-Server-Adresse
const char* mqttUser = "[MQTT_BENUTZERNAME]"; // MQTT-Benutzername
const char* mqttPassword = "[MQTT_PASSWORT]"; // MQTT-Passwort
const char* mqttTopic = "pflanzen/pflanze01";  // MQTT-Topic für die Übertragung der Sensorwerte

WiFiClient espClient;
PubSubClient client(espClient);

void setup() {
  Serial.begin(115200);  // Starten der seriellen Kommunikation
  preferences.begin("moisture", false);  // Öffnen des Präferenzenspeichers für den Feuchtigkeitssensor

  // Laden der gespeicherten Kalibrierungswerte
  airValue = preferences.getInt("airValue", 4095);
  waterValue = preferences.getInt("waterValue", 0);
  bool isCalibrated = preferences.getBool("isCalibrated", false);

  // Start der Kalibrierung, falls noch nicht kalibriert
  if (!isCalibrated) {
    Serial.println("Kalibrierung beginnt - Bitte den Sensor in unterschiedliche Feuchtigkeitszustände bringen.");
    startTime = millis();
  } else {
    Serial.println("Kalibrierung übersprungen.");
  }

  setup_wifi();  // Einrichten der WiFi-Verbindung
  client.setServer(mqttServer, 1883);  // Konfiguration des MQTT-Clients
}

void loop() {
  bool isCalibrated = preferences.getBool("isCalibrated", false);

  // Verbindung zum MQTT-Server wiederherstellen, falls notwendig
  if (!client.connected()) {
    reconnect();
  }
  client.loop();

  // Durchführung der Sensor-Kalibrierung
  if (!isCalibrated && millis() - startTime < calibrationPeriod) {
    int sensorValue = analogRead(moistureSensorPin);  // Lesen des Sensorwerts
    waterValue = max(waterValue, sensorValue);        // Aktualisieren des Wasserwerts
    airValue = min(airValue, sensorValue);            // Aktualisieren des Luftwerts
    Serial.println("Kalibrierung: Luftwert = " + String(airValue) + ", Wasserwert = " + String(waterValue));
  } else if (millis() - startTime >= calibrationPeriod && !isCalibrated) {
    // Speichern der Kalibrierungswerte
    preferences.putInt("airValue", airValue);
    preferences.putInt("waterValue", waterValue);
    preferences.putBool("isCalibrated", true);
  }

  // Messung und Übermittlung der Bodenfeuchtigkeit, falls kalibriert
  if (isCalibrated) {
    int sensorValue = analogRead(moistureSensorPin);
    int moisturePercent = waterValue == airValue ? 0 : map(sensorValue, airValue, waterValue, 100, 0);
    moisturePercent = constrain(moisturePercent, 0, 100);  // Sicherstellen, dass der Wert zwischen 0 und 100 liegt
    Serial.println("Bodenfeuchtigkeit: " + String(moisturePercent) + "%");

    char msg[50];
    sprintf(msg, "%d", moisturePercent);  // Formatieren der Nachricht
    client.publish(mqttTopic, msg);       // Senden der Bodenfeuchtigkeit an den MQTT-Server

    client.loop();
    delay(10);  // Kurze Verzögerung, um sicherzustellen, dass die Nachricht gesendet wurde

    // Einstellen des Schlafmodus für Energieeinsparung
    esp_sleep_enable_timer_wakeup(sleepTimeSeconds * 1000000);
    esp_deep_sleep_start();
  }
}

void setup_wifi() {
  delay(10);
  Serial.println("Verbinde zu WiFi...");
  WiFi.begin(ssid, password);  // Verbindung zum WLAN
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("WiFi verbunden.");
}

void reconnect() {
  // Wiederverbindung zum MQTT-Server versuchen
  while (!client.connected()) {
    Serial.print("Versuche, eine MQTT-Verbindung herzustellen...");
    if (client.connect("ArduinoClient", mqttUser, mqttPassword)) {
      Serial.println("verbunden");
    } else {
      Serial.print("fehlgeschlagen, rc=");
      Serial.print(client.state());
      Serial.println(" Versuche es in 5 Sekunden erneut");
      delay(5000);
    }
  }
}

Home Assistant Integration

Nachdem du die MQTT-Daten korrekt im Code hinterlegt und eine MQTT Community definiert hast, musst du den Sensor in der Home Assistant Konfigurationsdatei configuration.yaml hinzufügen. Füge den folgenden Code in die Konfigurationsdatei ein, falls du noch keine anderen Sensoren konfiguriert hast. Dabei ist es wichtig, dass du die im Code definierte MQTT Community angibst. Den Namen des Sensors kannst du nach deinen Wünschen wählen.

mqtt:  # MQTT-Schnittstellenkonfiguration
  sensor:  # Definiert einen oder mehrere Sensoren
    - name: "Pflanze 1 Bodenfeuchtigkeit"  # Name des Sensors, der im System angezeigt wird
      state_topic: "pflanzen/pflanze01"  # MQTT-Topic, von dem der Sensor seine Daten bezieht
      unit_of_measurement: '%'  # Einheit der Messung für die Sensorwerte, hier Prozent

Anschließend gehst du am besten in die Entwicklerwerkzeuge, prüfst die Konfiguration und startest Home Assistant neu.
Nach dem Neustart solltest du deinen Pflanzensensor in den Entitäten finden.

Fehlerbehebung

Das Skript ist so konzipiert, dass es in der Konsole laufend Rückmeldungen über seine Aktivitäten gibt. Hier kannst du überprüfen, ob die WLAN-Verbindung erfolgreich aufgebaut wurde und ob MQTT korrekt funktioniert. Während der Kalibrierungsphase werden die Rohdaten des Sensors angezeigt, gefolgt von den berechneten Feuchtigkeitswerten. Diese Informationen sind äußerst hilfreich, um eventuelle Probleme schnell zu identifizieren. Sollte trotz korrekter Konfiguration und erfolgreicher Ausgaben in der Konsole keine Daten in Home Assistant sichtbar sein, empfiehlt es sich, einen Blick in das Log des MQTT-Brokers zu werfen.

3D Druck Gehäuse

Solltest du meine Akkus und den FireBeetle 2 ESP32-E verwenden habe ich dir dafür auch ein Case wo der ESP32 zumindest etwas vor Erde geschützt ist. Schau mal hier vorbei: https://makerworld.com/en/models/159185


🤞 1x pro Monat unsere News, Tipps und Tutorials gebündelt direkt in dein Postfach!

Wir senden keinen Spam! Erfahre mehr in unserer Datenschutzerklärung.


Kommentare

2 Antworten zu „Bodenfeuchtigkeit messen mit dem ESP32 + Home Assistant Integration“

  1. Genau das wollte ich eigentlich selbst machen 😁 habe gerade den Beitrag Arduino Sensordaten via Bluetooth LE übertragen kommentiert und genau diesen Gedanken gehabt wo Sie hier bearbeiten. Nur halt mittels WLAN! Ich finde WLAN hat nur Nachteile für mein Smart Home vor allem wenn ich noch Sensoren usw rein lasse. Am liebsten würde ich das ganze mit Zigbee realisieren da ich aber schon alles für Bluetooth da habe. Muss das jetzt erstmal reichen. Das Skript für die Automatische Kalibrierung finde ich sehr spannend und wird noch getestet.
    Bin schon gespannt ob ich ihr Skript für die ArduinoBLE Bibliothek für mein Vorhaben verwenden kann! Danke für die Arbeit und Inspirationen 😉

  2. Hallo ich hätte da mal eine Frage. Kann ich die Kabel vom Bodenfeuchtigkeitssensor verlängern? Oder gibt es dann Probleme mit der Messgenauigkeit ?

Schreibe einen Kommentar

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

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.