Abbiamo visto nei precedenti post come rilevare l’umidità del terreno con micro:bit per controllare l’irrigazione di una pianta, vediamo ora una soluzione estremamente economica che può essere adottata con Arduino e che mostrerò nel dettaglio durante il mio prossimo corso sulla realizzazione dei laboratori green.
Il funzionamento del sensore di umidità del suolo è estremamente semplice.
La sonda a forma di forcella, con due conduttori esposti, agisce come un resistore variabile (come un potenziometro) la cui resistenza varia in base al contenuto di acqua nel terreno.
La resistenza è inversamente proporzionale all’umidità del suolo:
- più acqua è presente nel terreno implica maggiore conduttività e quindi minore resistenza;
- meno acqua è presente nel terreno implica minore conduttività e quindi maggiore resistenza.
Pertanto il sensore fornisce una tensione di uscita proporzionale alla resistenza misurata, in tal modo possiamo determinare il livello di umidità.
La sonda ha la forma di una forcella su cui sono disposte delle piste conduttive esposte. Le forcelle saranno da inserire all’interno del terreno o in qualsiasi altro elemento di cui bisogna misurare l’umidità.
La forcella viene connessa ad un modulo elettronico e quest’ultimo dovrà poi essere connesso ad Arduino. Il modulo fornirà una tensione di uscita proporzionale alla resistenza rilevata dalla sonda, questa tensione verrà resa disponibile ad un pin analogico di Arduino, nell’esempio che segue collegheremo la sonda al pin A0.
Nella foto si notano, sulla sinistra i due pin a cui collegheremo i pin di uscita della forcella e sulla destra quattro pin:
- A0: uscita analogica
- D0: uscita digitale
- GND: ground
- Vcc: tensione positiva di alimentazione (da 3,3V a 5V)
Il modulo è dotato di un potenziometro per la regolazione della sensibilità dell’output digitale (DO). Con il trimmer sarà possibile impostare la soglia di sensibilità, in modo tale che, quando il livello di umidità e al di sopra o al di sotto di un determinato valore, sul D0 vi sarà un segnale HIGH che potrebbe, ad esempio, attivare un relè che controlla l’avvio di una pompa di irrigazione.
Sulla scheda sono presenti inoltre un LED che segnala il funzionamento della scheda ed un LED che segnala lo stato del pin D0.
Rilevazione dell’umidità del terreno tramite l’uscita analogica
Questo sensore, così come il “water sensor” di cui ne abbiamo analizzato il funzionamento nella precedente lezione, è soggetto a deterioramento se esposto ad ambiente umido. L’alimentazione applicata alla sonda accelera l’ossidazione delle parti conduttive della forcella. Per evitare un rapido degrado è consigliabile fornire alimentazione solo quando bisogna effettuare la lettura.
Per fornire alimentazione alla scheda solo nel momento della lettura adottiamo la stessa strategia che abbiamo adottato per il “water sensor” il Vcc della scheda lo colleghiamo ad un pin digitale. Questa scelta non preclude un funzionamento non corretto della scheda in quanto la corrente massima assorbita dal sensore, anche nella situazione di accensione contemporanea dei LED, è di circa 8 mA, quindi ben al di sotto della corrente massima che può fornire il singolo pin digitale di Arduino.
Calibrazione
Anche per questo sensore bisogna procedere con la calibrazione.
E’ opportuno effettuare la calibrazione sul terreno su cui verrà poi inserito in via definitiva il sensore. Terreni diversi possono influenzare il funzionamento del sensore.
Quindi disponete in un vaso terreno secco ed in un altro ponete terreno saturo di umidità.
Utilizzate lo sketch che segue per verificare le misure in caso di terreno secco e di terreno umido:
/* Prof. Maffucci Michele Data: 12/03/2022 Rilevazione umidità del terreno - v01 (Utilizzo del pin analogico del sensore) */ const byte alimentazioneSensore = 12; const byte pinSensore = A0; void setup() { // Impostiamo il pin digitale 12 come OUTPUT pinMode(alimentazioneSensore, OUTPUT); // All'avvio impostiamo a LOW il +Vcc del sensore digitalWrite(alimentazioneSensore, LOW); // impostiamo la velocità della porta seriale Serial.begin(9600); } void loop() { // Lettura del sensore Serial.print("Uscita analogica: "); Serial.println(leggiSensore()); Serial.println("-----------------------------"); Serial.println(); delay(3000); } // Funzione che permette la lettura del livello di // umidità del terreno int leggiSensore() { digitalWrite(alimentazioneSensore, HIGH); // attiva il sensore - viene fornita alimentazione delay(50); // breve attesa di 50 ms prima di effettuare la lettura int valoreUmidita = analogRead(pinSensore); // legge il valore e lo si memorizza nella variabile livelloLiquido digitalWrite(alimentazioneSensore, LOW); // togliamo alimentazione al sensore return valoreUmidita; // invia alla funzione chiamante il valore letto }
Sul monitor seriale ho rilevato i seguenti valori:
Terreno secco: ~ 300
Terreno completamente bagnato: ~ 950
Sicuramente dovrete fare un po’ di test prima di ottenere valori sufficientemente stabili per stabilire i limiti di attivazione del vostro sistema di irrigazione.
Attenzione che potreste ottenere valori diversi dai miei, questi valori dipendono, come detto sopra, dal terreno e dalla quantità di sali discoli nell’acqua.
Basandovi sui valori di calibrazione sarete in grado di stabilire quando il terreno è secco, quando è sufficientemente umido e quando è eccessivamente umido.
Di seguito lo sketch che rileva il livello di umidità in funzione della calibrazione effettuata. Inviamo tutti i messaggi sulla serial monitor.
/* Prof. Maffucci Michele Data: 12/03/2022 Rilevazione umidità del terreno - v02 (Utilizzo del pin analogico del sensore) */ const byte alimentazioneSensore = 12; const byte pinSensore = A0; // cambiare i valori in in funzione della calibrazione // Valore limite di terreno umido. // Valori inferiori indicano terreno troppo umido const int terrenoUmido = 300; // Valore limite di terreno secco. // Valori superiori indicano terreno troppo secco const int terrenoSecco = 950; void setup() { // Impostiamo il pin digitale 12 come OUTPUT pinMode(alimentazioneSensore, OUTPUT); // All'avvio impostiamo a LOW il +Vcc del sensore digitalWrite(alimentazioneSensore, LOW); // impostiamo la velocità della porta seriale Serial.begin(9600); } void loop() { // Lettura del sensore int umiditaTerreno = leggiSensore(); Serial.print("Uscita analogica: "); Serial.println(umiditaTerreno); Serial.println("-----------------------------"); Serial.println(); Serial.println("----- Stato del terreno -----"); Serial.println(); // verifica livello umidità del terreno if (umiditaTerreno < terrenoUmido) { Serial.println(" Terreno troppo umido"); Serial.println(); } else if (umiditaTerreno >= terrenoUmido && umiditaTerreno < terrenoSecco) { Serial.println("-----------------------------"); Serial.println("Umidità del terreno ottimale"); } else { Serial.println(" Terreno troppo secco"); Serial.println(); } Serial.println("-----------------------------"); Serial.println(); // Lettura ogni secondo // Per evidare il degrado del sensore leggere il valore // poche volte al giorno (1 o 2 volte al massimo) // (Potrebbe essere opportuno utilizzare un RTC per regolare il tempo di lettura) delay(3000); } // Funzione che permette la lettura del livello di // umidità del terreno int leggiSensore() { digitalWrite(alimentazioneSensore, HIGH); // attiva il sensore - viene fornita alimentazione delay(50); // breve attesa di 50 ms prima di effettuare la lettura int valoreUmidita = analogRead(pinSensore); // legge il valore e lo si memorizza nella variabile livelloLiquido digitalWrite(alimentazioneSensore, LOW); // togliamo alimentazione al sensore return valoreUmidita; // invia alla funzione chiamante il valore letto }
Rilevazione dell’umidità tramite l’uscita digitale
Rimuoviamo la connessione del pin analogico ed utilizziamo il pin digitale della scheda. Per la realizzazione dello sketch si tenga conto che l’uscita della scheda sarà:
- Terreno umido: uscita LOW – LED acceso
- Terreno secco: uscita HIGH – LED spento
Per impostare la sensibilità inserite la sonda nel terreno umido, ruotate il potenziometro in senso orario in modo che il LED di stato si accenda, poi ruotate il potenziometro in senso antiorario fino a quando il LED si spegne, in questo modo avrete calibrato il sensore.
Attenzione, potreste notare che durante la calibrazione, nella situazione limite, passaggio da secco a umido il LED Status passi da una luminosità intensa ad una meno luminosa, non preoccupatevi è un comportamento normale.
/* Prof. Maffucci Michele Data: 12/03/2022 Rilevazione umidità del terreno - v03 (Utilizzo del pin digitale del sensore) */ const byte alimentazioneSensore = 12; const byte pinSensore = 8; void setup() { // Impostiamo il pin digitale 12 come OUTPUT pinMode(alimentazioneSensore, OUTPUT); // All'avvio impostiamo a LOW il +Vcc del sensore digitalWrite(alimentazioneSensore, LOW); // Impostiamo il pin digitale 8 come OUTPUT pinMode(pinSensore, INPUT); // impostiamo la velocità della porta seriale Serial.begin(9600); } void loop() { // Lettura del sensore int umiditaTerreno = leggiSensore(); Serial.print("Uscita digitale: "); Serial.println(umiditaTerreno); Serial.println("-----------------------------"); Serial.println(); Serial.println("----- Stato del terreno -----"); Serial.println(); // verifica livello umidità del terreno if (umiditaTerreno) { Serial.println("Terreno troppo secco, irrigare!"); Serial.println(); } else { Serial.println("Umidità del terreno ottimale"); Serial.println(); } Serial.println("-----------------------------"); Serial.println(); // Lettura ogni secondo // Per evidare il degrado del sensore leggere il valore // poche volte al giorno (1 o 2 volte al massimo) // (Potrebbe essere opportuno utilizzare un RTC per regolare il tempo di lettura) delay(3000); } // Funzione che permette la lettura del livello di // umidità del terreno. // Restituisce: // 0: umidità ottimale // 1: terreno poco umido int leggiSensore() { digitalWrite(alimentazioneSensore, HIGH); // attiva il sensore - viene fornita alimentazione delay(50); // breve attesa di 50 ms prima di effettuare la lettura int valoreUmidita = digitalRead(pinSensore); // legge il valore e lo si memorizza nella variabile livelloLiquido digitalWrite(alimentazioneSensore, LOW); // togliamo alimentazione al sensore return valoreUmidita; // invia alla funzione chiamante il valore letto }
Buon Making green a tutti 🙂