Come costruire un sensore capacitivo di umidità del suolo (HW-390) per ESP8266, ESP32, Raspberry Pi Pico W per Alexa
In questa parte ti guidiamo nella costruzione di un sensore capacitivo di umidità del suolo che può essere collegato a ESP32, ESP8266 o Raspberry Pi Pico W. Una volta configurato, potrai controllare il livello di umidità del suolo con Amazon Alexa, chiedere ad Alexa informazioni in merito e anche monitorarlo tramite l’app Sinric Pro, inviando una notifica push quando il suolo è asciutto o bagnato.

Prerequisiti :
- ESP32, ESP8266 o Raspberry Pi Pico W x 1.
- Sensore capacitivo di umidità del suolo (HW-390) x 1.
- Pianta in vaso x 1.
- Cavi jumper.
Nota: su ESP32, ADC2 (GPIO04, GPIO02, GPIO15) è instabile quando è in uso il Wi-Fi.
Breve introduzione al sensore capacitivo di umidità del suolo
I sensori capacitivi di umidità del suolo misurano la resistenza elettrica tra due sonde. La resistenza varia in base alla quantità d’acqua presente nel terreno. Il sensore è collegato a un microcontrollore (MCU), che misura la capacità tra le sonde. Il circuito HW-390 convertente la misura di capacità in un segnale di tensione (ADC), che viene poi inviato all’MCU. L’MCU può usare questo segnale per mostrare il livello di umidità del suolo o per controllare altri dispositivi.
Nota: fertilizzanti e corrosione possono ridurre nel tempo la precisione del sensore.
Cablaggio del sensore capacitivo di umidità del suolo

| MCU | Pin GPIO |
|---|---|
| ESP32 | 34 (Analogico ADC1_CH6) |
| ESP8266 | A0 |
| Pico W | GP26 (ADC0) |
Verifichiamo che il sensore sia collegato correttamente e funzioni.
#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);
}

Convertiamo l’ingresso analogico in un valore percentuale.
#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);
}

Passo 1 : Connettersi a Sinric Pro
Passo 1.1 : Creare un tipo di dispositivo personalizzato per il sensore capacitivo di umidità del suolo.
Sinric Pro non dispone di un tipo di dispositivo integrato per il sensore capacitivo di umidità del suolo, quindi creeremo un tipo di dispositivo personalizzato usando la funzione Device Template per vedere.
-
Suolo bagnato (Wet) o asciutto (Dry)
-
Livello di umidità.
Nota: puoi usare la funzione di importazione del template descritta più sotto per evitare di creare l’intero template da zero.
-
Accedi al tuo account Sinric Pro e vai su Device Templates
-
Fai clic su Add Device Template. Inserisci nome e descrizione come Capacitive Soil Moisture Sensor e seleziona Capacitive Soil Moisture Sensor come tipo di dispositivo

- Fai clic su Capabilities.
Qui dobbiamo selezionare le funzioni del nostro sensore di umidità del suolo. Vogliamo sapere se il suolo è bagnato o asciutto e il livello di umidità. Trasciniamo quindi le capability Range, Mode e Push Notification.

-
Cos’è la capability Range?
La capability Range può essere usata per rappresentare un numero. Ad es.: la velocità attuale di un frullatore.
-
Cos’è la capability Mode?
La capability Mode può essere usata per rappresentare un valore scelto da un elenco di valori predefiniti. Ad es.: il programma di lavaggio attuale di una lavatrice.
-
Cos’è la capability Push Notification?
La capability Notification offre la possibilità di inviare dal codice un messaggio di notifica push.
Fai clic sul pulsante Configure e configura le due capability come mostrato di seguito.

Fai clic su Save per salvare.

Fai clic su Save per salvare il template.

Ora puoi vedere il template che hai appena creato.
Importare un template esistente?
Se non hai voglia di configurare da zero tutti i Mode e i valori Range, puoi usare la funzione di importazione.

Incolla questo template:
{
"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"
}
]
}
Visualizza questo codice su GitHub Gist
-
Accedi al tuo account Sinric Pro, vai al menu Devices a sinistra e fai clic sul pulsante Add Device (in alto a sinistra).
-
Inserisci il nome del dispositivo Garden, la descrizione My Garden e seleziona come tipo di dispositivo Capacitive Soil Moisture Sensor.

-
Fai clic sulla scheda Others e fai clic su Save
-
La schermata successiva mostrerà le credenziali necessarie per collegare il dispositivo appena creato.

-
Copia Device Id, App Key e App Secret Tieni questi valori al sicuro. NON CONDIVIDERLI SU FORUM PUBBLICI !
-
Fai clic su Code Generator per generare il codice. Fai clic su Download per scaricarlo.

Passo 2 : Connettersi a Sinric Pro
Passo 2.1 Installa la libreria Sinric Pro

2.2 Codice completo
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();
}
Visualizza questo codice su GitHub Gist
Ora dovresti poter vedere l’umidità del suolo tramite Alexa e l’app Sinric Pro
Alexa, qual è l’umidità (nome del mode) in garden (nome del dispositivo)
Alexa, qual è il livello di umidità (nome del range) in garden (nome del dispositivo)


Passo 3 : Annunci vocali!
✅ Come funziona:
1️⃣ Aggiungi uno Switch in SinricPro (il tuo trigger segreto!)
2️⃣ Crea una Routine Alexa che pronunci il tuo messaggio “È ora di dare l’acqua al giardino!” quando lo Switch viene attivato
3️⃣ Invia dal tuo codice un evento di power state per attivare quello switch
void triggerVoiceAnnouncement() {
SinricProSwitch& mySwitch = SinricPro[SWITCH_ID];
mySwitch.sendPowerStateEvent(true);
}
Risoluzione dei problemi
-
Google Home o SmartThings non sono supportati.
-
Consulta la nostra pagina Risoluzione dei problemi per maggiori dettagli.
Tutorial correlati
- Come controllare un ESP32 o ESP8266 con Alexa e Google Home
- Sensore di umidità del suolo a batteria
- Livello di un serbatoio d’acqua con un sensore ultrasonico HC-SR04
- Sensore di perdite d’acqua, alluvioni e pioggia
Questo documento è open source. Hai trovato un errore di battitura? Crea una issue