IoT-Automatisierung

Bodenfeuchtesensor mit MQTT: ESP32-Aufbau mit Kalibrierung und Gießalarmen

Schließen Sie eine kapazitive Bodenfeuchtesonde an einen ESP32 an, kalibrieren Sie Trocken- und Nasspunkt, veröffentlichen Sie die Feuchte in Prozent über MQTT mit Deep Sleep und lösen Sie entprellte Gießalarme aus.

Bodenfeuchtesensor-MQTT-Knoten mit ESP32 und kapazitiver Sonde in einem Pflanzbeet, der Messwerte an einen Cloud-Broker sendet
Probieren Sie es auf Ihrem eigenen MQTT-Broker ausHolen Sie sich im Free-Tarif einen privaten, verwalteten MQTT-Broker und starten Sie mit fertigen Codebeispielen.
Kostenlos testen Codebeispiele Keine Kreditkarte erforderlich

Ein Bodenfeuchtesensor mit MQTT zeigt Ihnen, wann ein Beet, ein Topf oder eine Feldzone wirklich Wasser braucht, statt nach einem festen Zeitplan zu gießen. In diesem Tutorial schließen Sie eine kapazitive Sonde an einen ESP32 an, kalibrieren sie gegen trockenen und gesättigten Boden, veröffentlichen die Feuchte in Prozent in einem Deep-Sleep-Zyklus an einen MQTT-Broker und lösen einen entprellten Gießalarm aus, auf den Dashboards und Automatisierungen reagieren können.

Warum eine kapazitive Sonde

Die billigen resistiven Sonden mit zwei Zinken aus Starterkits leiten Strom durch den Boden. Innerhalb weniger Wochen korrodieren die freiliegenden Elektroden, die Messwerte driften, und das Metall gelangt in den Boden. Kapazitive Sonden messen die Dielektrizitätskonstante des Bodens über eine beschichtete Leiterplatte, sodass nichts Leitfähiges den Boden berührt. Sie sind das sinnvolle Minimum für alles, was eine Saison überstehen soll.

Sondentyp Lebensdauer im Boden Genauigkeit Hinweise
Resistive Gabel Wochen Schlecht, driftet Nur für eine eintägige Demo geeignet
Kapazitiv (Boards v1.2 / v2.0) Saisons, wenn die Kante versiegelt ist Relativ, Kalibrierung nötig Bestes Preis-Leistungs-Verhältnis für Hobby und kleine Betriebe
Professionelle FDR/TDR-Sonden Jahre Gut, oft volumetrisch SDI-12- oder RS485-Ausgang, höhere Kosten

Kapazitive Boards liefern einen relativen Messwert, keinen volumetrischen Wassergehalt. Für die Entscheidung, wann gegossen wird, reicht das völlig, sofern Sie jede Sonde in dem Boden kalibrieren, in dem sie später steckt.

Bauteile und Verdrahtung

Bauteil Zweck
ESP32-Entwicklungsboard (oder ein Board mit geringem Ruhestrom für Batteriebetrieb) Liest die Sonde, verbindet sich mit WLAN und MQTT
Kapazitive Bodenfeuchtesonde Misst die Feuchte
3 Jumperkabel Versorgung, Masse, Signal
Optional: 18650-Zelle, Halter und kleines Solarmodul Netzunabhängige Versorgung

Verdrahtung:

Sonden-Pin ESP32-Pin
VCC GPIO 25 (geschaltete Versorgung)
GND GND
AOUT GPIO 34 (ADC1)

Zwei Details sind wichtig. Erstens: Verwenden Sie einen ADC1-Pin (GPIO 32 bis 39). ADC2-Pins lassen sich nicht auslesen, solange WLAN aktiv ist. Zweitens: Versorgen Sie die Sonde über einen GPIO statt über die 3,3-V-Schiene, damit sie nichts verbraucht, während der ESP32 schläft. Kapazitive Sonden ziehen nur wenige Milliampere, weit innerhalb dessen, was ein GPIO liefern kann. Manche billigen Boards haben einen Spannungsregler, der bei 3,3 V nicht sauber arbeitet; bei sprunghaften Messwerten prüfen Sie die Board-Revision.

Versiegeln Sie die Oberkante der Sonde und die freiliegenden Bauteile mit Nagellack, Schutzlack oder Schrumpfschlauch. Wasser, das in die Schnittkante der Leiterplatte kriecht, ist die häufigste Ausfallursache.

Die Sonde kalibrieren

Der ESP32 liefert einen Rohwert von 0 bis 4095. Kapazitive Sonden messen hoch bei Trockenheit und niedrig bei Nässe. Flashen Sie den Sketch unten mit CALIBRATION_MODE auf true, öffnen Sie den seriellen Monitor mit 115200 Baud und notieren Sie zwei Werte:

  1. Trocken: die Sonde in völlig trockener Erde aus demselben Beet (oder als grobe Notlösung an der Luft).
  2. Nass: die Sonde in derselben, mit Wasser gesättigten Erde, nach einigen Minuten Wartezeit.

Stecken Sie die Sonde jedes Mal gleich tief ein, bis zur auf dem Board markierten Linie und nie tiefer. Typische Werte liegen bei etwa 2.600 bis 3.000 trocken und 1.000 bis 1.400 nass, aber jede Sonde ist anders; deshalb messen Sie, statt Werte zu übernehmen.

Der ESP32-Sketch für den Bodenfeuchtesensor mit MQTT

Der Sketch wacht auf, versorgt die Sonde, bildet den Median mehrerer Messungen, rechnet ihn in Prozent um, verbindet sich mit WLAN und Broker, veröffentlicht eine retained Telemetrienachricht und einen Alarmzustand und geht wieder in den Deep Sleep. Er nutzt die Bibliothek PubSubClient. Ersetzen Sie s5d1v8 durch Ihre eigene Zufallszeichenfolge, denn der öffentliche MQTT-Broker ist für jeden lesbar.

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

#define CALIBRATION_MODE false

const char* WIFI_SSID = "YOUR_WIFI";
const char* WIFI_PASS = "YOUR_WIFI_PASSWORD";

const char* MQTT_HOST = "broker.connectmq.com";
const uint16_t MQTT_PORT = 1883;
const char* CLIENT_ID = "soil-bed1-s5d1v8";
const char* TOPIC_TELE   = "connectmq/demo/s5d1v8/garden/bed1/telemetry";
const char* TOPIC_ALERT  = "connectmq/demo/s5d1v8/garden/bed1/alert";
const char* TOPIC_STATUS = "connectmq/demo/s5d1v8/garden/bed1/status";

const int PIN_PROBE_PWR = 25;
const int PIN_PROBE_ADC = 34;

const int RAW_DRY = 2850;   // aus der Kalibrierung
const int RAW_WET = 1180;   // aus der Kalibrierung

const float ALERT_ON_PCT  = 25.0;  // Alarm unterhalb dieses Werts auslösen
const float ALERT_OFF_PCT = 35.0;  // Alarm oberhalb dieses Werts aufheben
const uint64_t SLEEP_MIN = 15;

RTC_DATA_ATTR bool alertActive = false;
RTC_DATA_ATTR uint32_t bootCount = 0;

WiFiClient net;
PubSubClient mqtt(net);

int readRawMedian() {
  digitalWrite(PIN_PROBE_PWR, HIGH);
  delay(300);  // Sondenausgang einschwingen lassen
  int v[9];
  for (int i = 0; i < 9; i++) {
    v[i] = analogRead(PIN_PROBE_ADC);
    delay(20);
  }
  digitalWrite(PIN_PROBE_PWR, LOW);
  for (int i = 1; i < 9; i++) {           // Insertion Sort
    int k = v[i], j = i - 1;
    while (j >= 0 && v[j] > k) { v[j + 1] = v[j]; j--; }
    v[j + 1] = k;
  }
  return v[4];
}

float rawToPercent(int raw) {
  float pct = 100.0f * (RAW_DRY - raw) / (float)(RAW_DRY - RAW_WET);
  if (pct < 0) pct = 0;
  if (pct > 100) pct = 100;
  return pct;
}

bool connectWifi() {
  WiFi.mode(WIFI_STA);
  WiFi.begin(WIFI_SSID, WIFI_PASS);
  for (int i = 0; i < 40 && WiFi.status() != WL_CONNECTED; i++) delay(250);
  return WiFi.status() == WL_CONNECTED;
}

bool connectMqtt() {
  mqtt.setServer(MQTT_HOST, MQTT_PORT);
  for (int i = 0; i < 3; i++) {
    if (mqtt.connect(CLIENT_ID, TOPIC_STATUS, 1, true, "offline")) return true;
    delay(1000);
  }
  return false;
}

void goToSleep() {
  esp_sleep_enable_timer_wakeup(SLEEP_MIN * 60ULL * 1000000ULL);
  esp_deep_sleep_start();
}

void setup() {
  Serial.begin(115200);
  pinMode(PIN_PROBE_PWR, OUTPUT);
  analogSetPinAttenuation(PIN_PROBE_ADC, ADC_11db);
  bootCount++;

  int raw = readRawMedian();
  if (CALIBRATION_MODE) {
    while (true) {
      Serial.printf("raw=%d\n", readRawMedian());
      delay(1000);
    }
  }
  float pct = rawToPercent(raw);

  bool changed = false;
  if (!alertActive && pct < ALERT_ON_PCT)  { alertActive = true;  changed = true; }
  if (alertActive && pct > ALERT_OFF_PCT)  { alertActive = false; changed = true; }

  if (connectWifi() && connectMqtt()) {
    char buf[160];
    snprintf(buf, sizeof(buf),
             "{\"moisture_pct\":%.1f,\"raw\":%d,\"rssi\":%d,\"boot\":%lu}",
             pct, raw, WiFi.RSSI(), (unsigned long)bootCount);
    mqtt.publish(TOPIC_STATUS, "online", true);
    mqtt.publish(TOPIC_TELE, buf, true);
    snprintf(buf, sizeof(buf), "{\"active\":%s,\"moisture_pct\":%.1f}",
             alertActive ? "true" : "false", pct);
    mqtt.publish(TOPIC_ALERT, buf, true);
    if (changed) Serial.println(alertActive ? "ALERT raised" : "ALERT cleared");
    mqtt.loop();
    delay(200);       // dem TCP-Stack Zeit zum Senden geben
    mqtt.publish(TOPIC_STATUS, "sleeping", true);
    mqtt.disconnect();
  }
  goToSleep();
}

void loop() {}

Die Messwerte beobachten

mosquitto_sub -h broker.connectmq.com -p 1883 -i watch-s5d1v8 \
  -t 'connectmq/demo/s5d1v8/garden/#' -v

Da die Telemetrie retained ist, zeigt der Subscriber sofort den neuesten Messwert, obwohl das Gerät fast die ganze Zeit schläft. Das Status-Topic zeigt Ihnen, ob der Knoten online ist, sleeping oder unerwartet weggefallen ist (offline, aus dem Last Will).

So funktioniert der Gießalarm

Mit einem einzigen Schwellwert würde der Alarm ständig an- und ausgehen, wenn die Messwerte um ihn herum pendeln, besonders direkt nach leichtem Regen oder wenn die Sonne den Boden erwärmt. Der Sketch verwendet eine Hysterese: Der Alarm geht unter 25 Prozent an und wird erst aufgehoben, wenn die Feuchte über 35 Prozent steigt. Das Flag alertActive liegt im RTC-Speicher (RTC_DATA_ATTR) und übersteht so den Deep Sleep.

Das Alarm-Topic ist retained und enthält immer den aktuellen Zustand, sodass jeder Verbraucher darauf reagieren kann:

  • eine Home-Assistant-Automatisierung, die Ihr Smartphone benachrichtigt, wie im Leitfaden zur Home-Assistant-MQTT-Automatisierung gezeigt;
  • ein Node-RED-Flow oder eine Python-Steuerung, die ein Ventil öffnet, wie im Tutorial zur automatischen Bewässerungsanlage beschrieben;
  • eine Schwellwert-Alarmregel im ConnectMQ-Portal auf moisture_pct, die Alarme auch dann protokolliert, wenn Ihr Heimserver offline ist.

Tipps zu Genauigkeit und Zuverlässigkeit

  1. Im echten Boden kalibrieren. Sand- und Lehmböden liefern bei gleichem Wassergehalt sehr unterschiedliche Messwerte.
  2. Einstecktiefe konstant halten. Lufteinschlüsse um die Sonde lassen die Werte stark abfallen; drücken Sie den Boden nach dem Einstecken an.
  3. Auf den Trend achten, nicht auf Einzelwerte. Eine über zwei Tage fallende Kurve ist aussagekräftiger als ein einzelner Messwert.
  4. Die Extreme des ADC meiden. Der ESP32-ADC ist nahe 0 und 4095 nichtlinear. Mit 11 dB Dämpfung deckt der nutzbare Bereich eine kapazitive Sonde bequem ab.
  5. Die Batterie überwachen. Ergänzen Sie einen Spannungsteiler an einem weiteren ADC1-Pin und nehmen Sie battery_v in die Payload auf; Details finden Sie im Artikel zum batteriebetriebenen ESP32-Sensor.

Batterielaufzeit

Bei Aufwachen alle 15 Minuten ist der Knoten pro Zyklus nur wenige Sekunden wach, die meiste Zeit davon wartet er auf die WLAN-Anmeldung. Eine statische IP sowie BSSID und Kanal des Routers können das spürbar verkürzen. Wählen Sie ein Board mit Spannungsregler mit geringem Ruhestrom und ohne dauerhaft aktiven USB-Chip und LED, denn viele Entwicklungsboards verbrauchen im "Schlaf" mehr als der ESP32 selbst. Für Felder fern von jedem WLAN ist ein LoRaWAN-Knoten mit derselben Sonde und einer Bridge vom Netzwerkserver das bessere Design; die Abwägungen beschreibt der Leitfaden zu Smart Farming IoT.

Einrichtung für den Dauerbetrieb

Der kostenlose öffentliche MQTT-Broker ist ideal zum Bauen und Testen von Prototypen, aber er ist geteilt, für jeden lesbar und nicht für Produktivdaten gedacht. Für eine dauerhafte Installation erstellen Sie einen privaten Broker und wechseln auf TLS:

  • binden Sie WiFiClientSecure.h ein, verwenden Sie WiFiClientSecure net; und net.setCACert(ISRG_ROOT_X1); mit dem Zertifikat ISRG Root X1;
  • ändern Sie den Port auf 8883;
  • verbinden Sie sich mit mqtt.connect("YOUR_CLIENT_ID", "YOUR_USERNAME", "YOUR_PASSWORD", TOPIC_STATUS, 1, true, "offline");
  • verschieben Sie die Topics auf Ihr eigenes Präfix, zum Beispiel farm1/garden/bed1/telemetry. Gartenbaubetriebe mit mehreren Standorten und Gewächshäusern gliedern das Präfix sinnvollerweise nach Standort, Halle und Zone, genau wie ein Werk seine Topics nach Anlagenebenen ordnet.

TLS verlängert jeden Wachzyklus um ein bis zwei Sekunden, ein geringer Preis dafür, dass Ihre Daten privat bleiben. Ein verwalteter MQTT-Broker erspart Ihnen außerdem, einen Broker in dem Netzwerk zu betreiben, von dem die Sensoren abhängen. Weitere Projekte dieser Art finden Sie im Leitfaden zur IoT-Automatisierung.

Überwachen Sie Ihren Boden mit ConnectMQ

ConnectMQ gibt Ihren Sensoren einen privaten, per TLS gesicherten Broker mit Live-Topic-Explorer, Dashboard und Schwellwert-Alarmregeln für Warnungen bei trockenem Boden. Erstellen Sie unter app.connectmq.com einen kostenlosen Serverless-Broker, ohne Kreditkarte, und ändern Sie drei Zeilen im Sketch, um live zu gehen.

Häufig gestellte Fragen

Warum zeigt mein kapazitiver Bodenfeuchtesensor bei trockenem Boden höhere Werte?

So funktionieren kapazitive Sonden: Die Ausgangsspannung sinkt, wenn die Dielektrizitätskonstante mit dem Wassergehalt steigt. Der Sketch kehrt die Skala bei der Umrechnung in Prozent um.

Kann ich mehrere Sonden an einem ESP32 betreiben?

Ja. Nutzen Sie weitere ADC1-Pins (GPIO 32, 33, 35, 36, 39), kalibrieren Sie jede Sonde einzeln und veröffentlichen Sie jede auf einem eigenen Topic oder als Felder in einer gemeinsamen JSON-Nachricht.

Wie tief sollte der Bodenfeuchtesensor stecken?

In der Wurzelzone der Kultur, bei Gemüse und Töpfen typischerweise 5 bis 15 cm. Stecken Sie ihn nur bis zur markierten Linie ein, damit die Elektronik oberhalb des Bodens bleibt.

Wie oft sollte ein Bodenfeuchtesensor über MQTT veröffentlichen?

Alle 15 bis 60 Minuten genügt völlig. Die Bodenfeuchte ändert sich langsam, und längere Intervalle verlängern die Batterielaufzeit erheblich.

Verwandte Artikel

Zigbee2MQTT einrichten: Vom Koordinator bis zum Dashboard

Installieren Sie Zigbee2MQTT mit Docker, konfigurieren Sie Koordinator und MQTT-Verbindung, lernen Sie Geräte an und benennen Sie sie um, steuern Sie sie per MQTT und zeigen Sie ihre Zustände auf einem Dashboard an, zuerst getestet auf einem kostenlosen öffentlichen MQTT-Broker.

8 Min. Lesezeit

Alle Artikel →

Ihr privater MQTT-Broker ist nur wenige Klicks entfernt

Konto anlegen, Broker-Zugangsdaten erhalten und das erste Gerät verbinden — ohne Server, die installiert, gepatcht oder skaliert werden müssen.