Kapazitiven Bodenfeuchtesensor (HW-390) für ESP8266, ESP32 und Raspberry Pi Pico W mit Alexa bauen
In diesem Teil zeigen wir dir, wie du einen kapazitiven Bodenfeuchtesensor baust, der sich an einen ESP32, ESP8266 oder Raspberry Pi Pico W anschließen lässt. Sobald alles eingerichtet ist, kannst du die Bodenfeuchte mit Amazon Alexa abfragen, Alexa nach Informationen dazu fragen, sie in der Sinric Pro App überwachen und eine Push-Benachrichtigung senden, wenn der Boden trocken oder nass ist.

Voraussetzungen :
- ESP32, ESP8266 oder Raspberry Pi Pico W x 1.
- Kapazitiver Bodenfeuchtesensor (HW-390) x 1.
- Pflanze mit Topf x 1.
- Jumperkabel.
Hinweis: Beim ESP32 ist ADC2 (GPIO04, GPIO02, GPIO15) instabil, solange WLAN verwendet wird.
Kurze Einführung in den kapazitiven Bodenfeuchtesensor
Kapazitive Bodenfeuchtesensoren messen den elektrischen Widerstand zwischen zwei Sonden. Der Widerstand ändert sich je nach Wassermenge im Boden. Der Sensor ist mit einem Mikrocontroller (MCU) verbunden, der die Kapazität zwischen den Sonden misst. Die Schaltung des HW-390 wandelt die Kapazitätsmessung in ein Spannungssignal (ADC) um, das dann an die MCU gesendet wird. Die MCU kann mit diesem Signal die Bodenfeuchte anzeigen oder andere Geräte steuern.
Hinweis: Dünger und Korrosion können die Genauigkeit des Sensors mit der Zeit verringern.
Verdrahtung des kapazitiven Bodenfeuchtesensors

| MCU | GPIO-Pin |
|---|---|
| ESP32 | 34 (Analog ADC1_CH6) |
| ESP8266 | A0 |
| Pico W | GP26 (ADC0) |
Prüfen wir zuerst, ob der Sensor richtig verdrahtet ist und funktioniert.
#if defined(ESP8266)
const int adcPin = A0;
#elif defined(ESP32)
const int adcPin = 34;
#elif defined(ARDUINO_ARCH_RP2040)
const int adcPin = 26;
#endif
void setup() {
Serial.begin(9600);
pinMode(adcPin, INPUT);
}
void loop() {
Serial.println(analogRead(adcPin));
delay(1000);
}

Jetzt rechnen wir den analogen Eingangswert in einen Prozentwert um.
#if defined(ESP8266)
const int adcPin = A0;
#elif defined(ESP32)
const int adcPin = 34;
#elif defined(ARDUINO_ARCH_RP2040)
const int adcPin = 26;
#endif
const int DRY = 720; // TODO: This is value when soil is dry. Adjust according to your usecase
const int WET = 560; // TODO: This is value when soil is wet. Adjust according to your usecase
void setup() {
Serial.begin(9600);
pinMode(adcPin, INPUT);
}
void loop() {
int sensorVal = analogRead(adcPin);
int percentage = map(sensorVal, WET, DRY, 100, 0);
Serial.printf("Sensor value: %d percentage: %d%%\r\n", sensorVal, percentage);
delay(1000);
}

Schritt 1 : Mit Sinric Pro verbinden
Schritt 1.1 : Eigenen Gerätetyp für den kapazitiven Bodenfeuchtesensor anlegen.
Sinric Pro hat keinen eingebauten Gerätetyp für einen kapazitiven Bodenfeuchtesensor. Deshalb legen wir mit der Funktion Device Template einen eigenen Gerätetyp für den kapazitiven Bodenfeuchtesensor an, um Folgendes zu sehen:
-
Der Boden ist nass oder trocken
-
Feuchtigkeitswert.
Hinweis: Mit der weiter unten beschriebenen Importfunktion für Gerätevorlagen kannst du dir das Anlegen der kompletten Vorlage sparen.
-
Melde dich bei deinem Sinric Pro Konto an und gehe zu Device Templates
-
Klicke auf Add Device Template. Gib als Name und Beschreibung Capacitive Soil Moisture Sensor ein und wähle Capacitive Soil Moisture Sensor als Gerätetyp

- Klicke auf Capabilities.
Hier müssen wir die Funktionen unseres Bodenfeuchtesensors auswählen. Wir wollen wissen, ob der Boden nass oder trocken ist, und den Feuchtigkeitswert kennen. Ziehe also die Capabilities Range, Mode und Push Notification hinein.

-
Was ist die Range-Capability?
Mit der Range-Capability lässt sich eine Zahl darstellen, z. B. die aktuelle Geschwindigkeit eines Mixers.
-
Was ist die Mode-Capability?
Mit der Mode-Capability lässt sich ein Wert aus einer Liste vordefinierter Werte darstellen, z. B. das aktuelle Waschprogramm einer Waschmaschine.
-
Was ist die Push-Notification-Capability?
Mit der Notification-Capability kannst du aus dem Code heraus eine Push-Benachrichtigung senden.
Klicke auf die Schaltfläche Configure und richte die beiden Capabilities wie unten gezeigt ein.

Klicke zum Speichern auf Save.

Klicke auf Save, um die Vorlage zu speichern.

Jetzt siehst du die Vorlage, die wir gerade angelegt haben.
Eine vorhandene Vorlage importieren?
Wenn du keine Lust hast, alle Mode- und Range-Werte von Hand einzurichten, kannst du die Importfunktion verwenden.

Füge diese Vorlage ein:
{
"name": "Capacitive Soil Moisture Sensor",
"description": "Capacitive Soil Moisture Sensor",
"deviceTypeId": "6522320f2b090cc39f39fb32",
"capabilities": [
{
"id": "5ff0b41b994fd31b7d5e8961",
"mode": {
"instanceId": "modeInstance1",
"locale": "en-US",
"modeName": "Moisture",
"nonControllable": true,
"modeValues": [
"Wet",
"Dry"
]
}
},
{
"id": "5ff0b45f994fd31b7d5e89c2",
"range": {
"instanceId": "rangeInstance1",
"locale": "en-US",
"rangeName": "Moisture Level",
"minimumValue": 1,
"maximumValue": 100,
"precision": 1,
"unitOfMeasure": "5ffbeefbfaa11451974c6bbd",
"presets": [],
"nonControllable": true
}
},
{
"id": "62a707bd9e2f39090569e2d3"
}
]
}
Diesen Code auf GitHub Gist ansehen
-
Melde dich bei deinem Sinric Pro Konto an, öffne links das Menü Devices und klicke auf die Schaltfläche Add Device (oben links).
-
Gib als Gerätenamen Garden und als Beschreibung My Garden ein und wähle den Gerätetyp Capacitive Soil Moisture Sensor.

-
Klicke auf den Tab Others und dann auf Save
-
Die nächste Seite zeigt die Zugangsdaten, die das eben angelegte Gerät für die Verbindung braucht.

-
Kopiere Device Id, App Key und App Secret. Halte diese Werte geheim. TEILE SIE NICHT IN ÖFFENTLICHEN FOREN!
-
Klicke auf Code Generator, um den Code zu erzeugen. Klicke auf Download, um den Code herunterzuladen.

Schritt 2 : Mit Sinric Pro verbinden
Schritt 2.1 Sinric Pro Bibliothek installieren

2.2 Vollständiger Code
CapacitiveSoilMoistureSensor.h
#ifndef _CAPACITIVESOILMOISTURESENSOR_H_
#define _CAPACITIVESOILMOISTURESENSOR_H_
#include <SinricProDevice.h>
#include <Capabilities/ModeController.h>
#include <Capabilities/RangeController.h>
#include <Capabilities/PushNotification.h>
class CapacitiveSoilMoistureSensor
: public SinricProDevice
, public ModeController<CapacitiveSoilMoistureSensor>
, public RangeController<CapacitiveSoilMoistureSensor>
, public PushNotification<CapacitiveSoilMoistureSensor> {
friend class ModeController<CapacitiveSoilMoistureSensor>;
friend class RangeController<CapacitiveSoilMoistureSensor>;
friend class PushNotification<CapacitiveSoilMoistureSensor>;
public:
CapacitiveSoilMoistureSensor(const String &deviceId) : SinricProDevice(deviceId, "CapacitiveSoilMoistureSensor") {};
};
#endif
sinricpro-capacitive-soil-moisture-sensor.ino
// #define ENABLE_DEBUG
#ifdef ENABLE_DEBUG
#define DEBUG_ESP_PORT Serial
#define NODEBUG_WEBSOCKETS
#define NDEBUG
#endif
#include <Arduino.h>
#ifdef ESP8266
#include <ESP8266WiFi.h>
#endif
#ifdef ESP32
#include <WiFi.h>
#endif
#include <SinricPro.h>
#include "CapacitiveSoilMoistureSensor.h"
// Grab it from https://portal.sinric.pro.
#define APP_KEY "" //Should look like "de0bxxxx-1x3x-4x3x-ax2x-5dabxxxxxxxx"
#define APP_SECRET "" //Should look like "5f36xxxx-x3x7-4x3x-xexe-e86724a9xxxx-4c4axxxx-3x3x-x5xe-x9x3-333d65xxxxxx"
#define DEVICE_ID "" //Should look like "6534xxxxxxxc08c6ea1b"
#define SSID "" // Your WiFi SSID
#define PASS "" // Your WiFi Password
#define BAUD_RATE 115200 // Change baudrate to your need (used for serial monitor)
#define EVENT_WAIT_TIME 60000 // send event every 60 seconds
#if defined(ESP8266)
const int adcPin = A0;
#elif defined(ESP32)
const int adcPin = 34;
#elif defined(ARDUINO_ARCH_RP2040)
const int adcPin = 26;
#endif
const int VERY_DRY = 720; // TODO: This is when soil is dry. Adjust according to your sensor
const int VERY_WET = 560; // TODO: This is when soil is wet. Adjust according to your sensor
const int NEITHER_DRY_OR_WET = 620; // TODO: This is when soil is neither wet or dry. Adjust according to your sensor
const int DRY_PUSH_NOTIFICATION_THRESHHOLD = 700; // TODO: This is when to send a push notification to the mobile phone. Adjust according to your sensor
const int UNPLUGGED = 735; // This is the value sensor produce when it's not in the ground.
int lastSoilMoisture = 0;
String lastSoilMoistureStr = "";
CapacitiveSoilMoistureSensor &capacitiveSoilMoistureSensor = SinricPro[DEVICE_ID];
void updateSoilState(String mode) {
capacitiveSoilMoistureSensor.sendModeEvent("modeInstance1", mode, "PHYSICAL_INTERACTION");
}
void updateMoistureLevel(int value) {
capacitiveSoilMoistureSensor.sendRangeValueEvent("rangeInstance1", value);
}
void sendPushNotification(String message) {
capacitiveSoilMoistureSensor.sendPushNotification(message);
}
void handleCapacitiveSoilMoistureSensor() {
if (SinricPro.isConnected() == false) {
return;
}
static unsigned long last_millis;
unsigned long current_millis = millis();
if (last_millis && current_millis - last_millis < EVENT_WAIT_TIME) return;
last_millis = current_millis;
int soilMoisture = analogRead(adcPin);
int percentage = map(soilMoisture, VERY_WET, VERY_DRY, 100, 0);
percentage = constrain(percentage, 1, 100);
Serial.printf("Soil Moisture: %d. as a percentage: %d%%\r\n", soilMoisture, percentage);
if (isnan(soilMoisture)) { // reading failed...
Serial.printf("Capacitive Soil Moisture Sensor reading failed!\r\n"); // print error message
return; // try again next time
}
if (soilMoisture == lastSoilMoisture) {
Serial.printf("Soil moisture did not changed. do nothing...!\r\n");
return;
}
// Determine Wet or Dry.
String soilMoistureStr = "";
if(soilMoisture > NEITHER_DRY_OR_WET) {
soilMoistureStr = "Dry"; // NOTE: must be Wet, Dry. This is from modes list in template.
} else {
soilMoistureStr = "Wet";
}
// Update Moisture label
if(lastSoilMoistureStr != soilMoistureStr) {
lastSoilMoistureStr = soilMoistureStr;
updateSoilState(soilMoistureStr);
}
delay(500);
// Update Moisture level label
updateMoistureLevel(percentage);
// Send push notifications
if(soilMoisture > DRY_PUSH_NOTIFICATION_THRESHHOLD) {
sendPushNotification("Plants are too dry. Time to water the plants!");
}
if(soilMoisture > UNPLUGGED) {
sendPushNotification("Sensor seems to be unhooked. Please check!");
}
lastSoilMoisture = soilMoisture; // save to compare next time.
}
/*********
* Setups *
*********/
void setupSinricPro() {
SinricPro.onConnected([]{ Serial.printf("[SinricPro]: Connected\r\n"); });
SinricPro.onDisconnected([]{ Serial.printf("[SinricPro]: Disconnected\r\n"); });
SinricPro.begin(APP_KEY, APP_SECRET);
};
void setupSensor() {
pinMode(adcPin, INPUT);
}
void setupWiFi() {
#if defined(ESP8266)
WiFi.setSleepMode(WIFI_NONE_SLEEP);
WiFi.setAutoReconnect(true);
#elif defined(ESP32)
WiFi.setSleep(false);
WiFi.setAutoReconnect(true);
#endif
WiFi.begin(SSID, PASS);
Serial.printf("[WiFi]: Connecting to %s", SSID);
while (WiFi.status() != WL_CONNECTED) {
Serial.printf(".");
delay(250);
}
Serial.printf("connected\r\n");
}
void setup() {
Serial.begin(BAUD_RATE);
setupSensor();
setupWiFi();
setupSinricPro();
}
/********
* Loop *
********/
void loop() {
SinricPro.handle();
handleCapacitiveSoilMoistureSensor();
}
Diesen Code auf GitHub Gist ansehen
Jetzt solltest du die Bodenfeuchte über Alexa und die Sinric Pro App sehen können
Alexa, wie ist die Feuchtigkeit (Name des Modes) im Garten (Gerätename)
Alexa, wie hoch ist der Feuchtigkeitswert (Name der Range) im Garten (Gerätename)


Schritt 3 : Sprachansagen!
✅ So funktioniert es:
1️⃣ Lege in SinricPro einen Switch an (dein geheimer Auslöser!)
2️⃣ Erstelle eine Alexa-Routine, die deine Nachricht ansagt, etwa „Zeit, den Garten zu gießen!“, sobald der Switch eingeschaltet wird
3️⃣ Sende aus deinem Code ein Power-State-Event, um diesen Switch einzuschalten
void triggerVoiceAnnouncement() {
SinricProSwitch& mySwitch = SinricPro[SWITCH_ID];
mySwitch.sendPowerStateEvent(true);
}
Fehlerbehebung
-
Google Home und SmartThings werden nicht unterstützt.
-
Weitere Details findest du auf unserer Seite zur Fehlerbehebung.
Verwandte Tutorials
- ESP32 oder ESP8266 mit Alexa und Google Home steuern
- Batteriebetriebener Bodenfeuchtesensor
- Füllstand eines Wassertanks mit einem HC-SR04 Ultraschallsensor
- Wasserleck-, Überschwemmungs- und Regensensor
Dieses Dokument ist Open Source. Einen Tippfehler entdeckt? Bitte erstelle ein Issue