// Arduino: Irrigatore a basso consumo - Low absorption sprinkler // RTC, sleep, interrupt, lcd 1620, I2C
U - irrigatore a basso consumo – Low absorption sprinkler (some
notes at section end)
Un sistema di irrigazione non e’ una novita’, ma questo e’ in grado di economizzare sia l’acqua che l’energia, in modo da poter funzionare, anche per mesi, senza la necessita’ di essere collegato alla rete elettrica e, se si dispone di una adeguata riserva di acqua, nemmeno alla rete idrica. Il programma infatti utilizza le funzioni sleep e interrupt di Arduino per massimizzare la durata della
batteria ed un misuratore di umidita’ del terreno, che acconsente all’erogazione di acqua solo quando il terreno e’ asciutto. Non dipendere dalla rete elettrica e nemmeno dalla rete idrica rende il sistema sicuro (in termini di danni provocati da infiltrazioni di acqua o da dispersioni elettriche) anche per coloro che pensano di allontanarsi da casa per lungo tempo, senza per questo perdere un balcone verde e fiorito.
Dal punto di vista tecnico il sistema resta “dormiente”, minimizzando il consumo di energia, sino a quando il suo orologio interno non gli invia un interrupt, una specie di squillo digitale, udibile solo dal computer. A questo punto Arduino si sveglia, controlla l’umidita’ del terreno e se al di sopra di una soglia predefinita’ attiva un rele’ che a sua volta attiva una pompa (o una elettrovalvola) che fa fluire acqua per un tempo predefinito o fino a quando il rilevatore di umidita’ non riscontra una soglia di umidita’ sufficiente a consentire alle piante di vivere bene fino al prossimo risveglio. Dopodiche’ Arduino si riaddormenta e resta in posizione di sleep (e quindi di basso consumo di energia) sino al prossimo interrupt.
In questo progetto Arduino utilizza un orologio digitale che deve essere inizializzato (e cioe’ regolato con data ed ora) prima di essere utilizzato. Una volta regolata l’ora poi non sara’ piu’ necessario alcun intervento poiche’ l’orologio e’ dotato di una sua pila interna che gli consente di mantenere, per anni, il controllo del tempo.
Per la regolazione iniziale dell’orologio utilizzare l’istruzione gia’ presente nella zona di setup del programma inserendo l’anno, il mese, il giorno, l’ora, i minuti ed i secondi correnti al posto dei valori predefiniti:
clock.setDateTime(2019, 5, 11, 17, 59, 50);
Dopo la inizializzazione dell’orologio e’ necessario cancellare detta istruzione e ricompilare il
programma.
Il programma e’ impostato per “risvegliare” Arduino alle ore 18:00 di ogni giorno. Qualora si volesse variare l’orario sara’ sufficiente modificare la prima istruzione della sezione di loop, inserendo l’ora, il minuto ed il secondo in cui si desidera il risveglio. Nel progetto e’ presente anche un pulsante attraverso il quale e’ possibile “risvegliare” Arduino anche al di fuori dell’orario programmato.
In quest’ultimo caso Arduino esegue’ i medesimi passaggi che esegue quando viene risvegliato dall’orologio e cioe’ controlla l’umidita’ del terreno e, se del caso, attiva il rele’ di irrigazione
// Arduino: Irrigatore a basso consumo - Low absorption sprinkler // RTC, sleep, interrupt, lcd 1620, I2C
Qui e qui sono presenti alcune note di approfondimento sulle funzioni interrupt e sleep di Arduino.
Quando il sistema e’ dormiente il consumo di energia si riduce a circa 0,12 watt (0,02 ampere per 6 volt) per cui, con una normale batteria per auto si puo’ mantenere il sistema attivo per mesi.
Qui il filmato di questo progetto.
Prima di compilare il programma bisogna, scaricare ed installare, se non gia’ fatto:
La libreria di gestione del display a cristalli liquidi, reperibile qui.
La libreria di gestione dell’orologio ds3231, reperibile qui Il programma utilizza anche le librerie: avr/sleep.h e Wire.h gia’ presenti, di default, nell’IDE.
Per installare una libreria:
Scaricarla mantenendola in formato compresso
Andare in IDE-> sketch-> importa libreria-> add library->
Individuare la cartella di download->
Fare doppio click sulla libreria da installare
Verificarne la presenza in IDE-> sketch-> includes Library-> Contributed library
Nota: Questo esercizio e questa nota sono parte di una serie che vede protagonisti Arduino ed alcuni dei componenti ad esso collegabili. Per la maggior parte degli esercizi e’ anche disponibile un filmato su youtube:
Esercizi facenti parte della raccolta
Filmati presenti su youtube
Informazioni su arduino e sui componenti collegabili (PDF scaricato nell’area di download)
Breve manuale di programmazione (PDF scaricato nell’area di download)
Per eventuali chiarimenti o suggerimenti sul contenuto di questa scheda scrivere a [email protected]
Here some notes about this project, translated by google translator
An irrigation system is not new, but this is able to economize both water and energy, so that it can work, even for months, without the need to be connected to electricity network and, if you have an adequate water tank, not even at water network.
In fact, program uses the Arduino sleep and interrupt functions to maximize battery life and a soil moisture meter, which allows water to be dispensed only when the soil is dry. Not depend from electricity grid and not even on water network, it makes the system safe (in terms of damage caused by water infiltration or electrical leakage) even for those who think leave home for a long time, without losing a green balcony flourished.
From a technical point of view, system remains "sleeping", minimizing energy consumption, until its internal clock sends an interrupt, a kind of digital ring, audible only from Arduino.
At this point Arduino wakes up, checks ground humidity and if over a predefined threshold, activates a relay which in turn activates a pump (or a solenoid valve) which makes water flow for a predefined time or up to when humidity is over a threshold sufficient to allow plants to well live until the next awakening. Then Arduino goes back to sleep and stays in sleep until the next interrupt.
In this project Arduino uses a digital clock that must be initialized (ie regulated with date and time) before being used. Once time has been set, then no more action will be necessary as watch is equipped with its own internal battery which allows it to maintain time control for years.
// Arduino: Irrigatore a basso consumo - Low absorption sprinkler // RTC, sleep, interrupt, lcd 1620, I2C
For clock initial setting, use instruction already present in program "setup" area, entering current year, month, day, hour, minutes and seconds:
clock.setDateTime(2019, 5, 11, 17, 59, 50);
After clock has been initialized you must cancel this instruction and recompile program. Program is set to "wake up" Arduino every day, at 18:00. Should you wish change the time, it will be sufficient modify the first instruction in the "loop" section, entering the awakening hour, minute and second .
In this project there is also a button through which it is possible "wake up" Arduino even outside the programmed time.
In the latter case Arduino performs the same steps it performs when is awakened by clock, ie controls the ground humidity and, if necessary, activates the irrigation relay.
Here and here are some notes on Arduino interrupt and sleep functions
When system is sleeping, energy consumption is reduced to about 0.12 watts (0.02 amps and 6 volts) so that with a normal car battery you can keep system active for months.
Here the project movie
Before proceeding to program compilation must be installed, if not already done, the libraries:
LiquidCrystal_I2C.h found here
ds3231, found here
For library installation, see process shown in previous projects, and summarized in:
library download in compressed form;
Installation via IDE-> sketch-> includes Library-> add .zip library
After installation please verify the library. It must be present in IDE-> sketch-> includes Library-> Contributed library
Note: This project and this note is part of a series that sees, as main characters, Arduino and some of connectable components. For most projects there is also a video on youtube.
Projects collection
Movies on youtube
About Arduino and components (italian; pdf will be downloaded in your download area
Quick programming guide (almost english; pdf will be downloaded in your download area)
For any questions or suggestions about this note (and on its english translation), please write to [email protected] (simple words and short sentences, please)
Materiali Modulo RTC DS3231
Sensore di umidita’ e relativo driver
Display lcd 1602 con driver I2C
Relay + pompa acqua o elettrovalvola
Resistenza da 220 ohm
pulsante
// Arduino: Irrigatore a basso consumo - Low absorption sprinkler // RTC, sleep, interrupt, lcd 1620, I2C
Schema
Nota: il collegamento tra la porta 0 (RX) e la resistenza da 220 ohm a sua volta collegata al pulsante di interrupt ed alla porta 2 serve a mantenere HIGH lo stato della porta 2 (sia con Arduino dormiente che con Arduino operativo). La pressione del pulsante collega la porta direttamente a terra (GND), provocandone il temporaneo cambiamento di stato, da HIGH a LOW
Note: link between pin 0 (RX) and 220 ohm resistance in turn connected to buttons and to pins 2 maintains pin 2 in HIGH status. Pressing button, connects pin directly to ground (GND), and causes a temporary change of state from HIGH to LOW
Programma
/* Attenzione: facendo il copia/incolla dal PDF all’IDE si perde la formattazione del testo. Per
rendere piu’ facilmente leggibile il programma e’ opportuno formattarlo subito dopo il
trasferimento nell’IDE, premendo CTRL+T.
Questo programma utilizza le funzioni sleep e interrupt per gestire un sistema di irrigazione
minimizzando il dispendio di acqua ed energia. Arduino e' normalmente in stato di sleep (una
funziona a bassissimo consumo di energia) e viene risvegliato, ad un orario rpedefinito (in questo
Download del programma via Dropbox Program download via Dropbox
// Arduino: Irrigatore a basso consumo - Low absorption sprinkler // RTC, sleep, interrupt, lcd 1620, I2C
caso alle 18:00 di ogni giorno) da un impulso lanciato da un orologio digitale (DS3231).
Il risveglio puo' anche essere manualmente provocato da un impulso lanciato da un pulsante.
Una volta sveglio controlla l'umidita del terreno e, se necessario, attiva un rele' che a sua volta
attiva un pompa (o un elettrovalcola che resta attiva per un tempo predefinito (in questo caso 15
secondi) o fino a quando l'umidita' del terreno raggiunge un limite predefinito, dopodiche Arduino
entra di nuovo in stato di sleep, in attesa del successivo impulso proveniente dall'orologio o dal
pulsante.
per ottenere questo risultato e' stato necessario modificare il funzionamento del pin SQW del modulo
DS3231 intervenendo su di un byte di controllo interno al modulo. Senza questa modifica il sistema
non riesce ad addormentarsi. Le istruzioni per la modifica di detto byte sono gia' presenti nel
programma.
Warning: cut&paste from PDF to IDE loses formatting. To restore it press CTRL + T.
Arduino wakes (from a sleep state) on interrupts launched from an external digital clock(DS3231 RTC)
or from a button. Once waked up, Arduino check soil moisture and, if necessary,turn on a relay to
activate a pump. Relay stay on for e predefined time (in this case 15 seconds) or untill soil
moisture rise a predefined level. To rise this goal must be change a control byte on DS3231
(instruction are already in program; without that change Arduino doesn't go to sleep mode even the
first time
*/
#include <Wire.h> //libreria wire, presente di default nell'IDE
#include <DS3231.h> // Libreria ds3231, https://github.com/jarzebski/Arduino-DS3231
#include <avr/sleep.h> // libreria avr/sleep, presente di default nell'IDE
#include <LiquidCrystal_I2C.h> // https://bitbucket.org/fmalpartida/new-liquidcrystal/downloads
// addr, en,rw,rs,d4,d5,d6,d7,bl,blpol
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // definisce il tipo di display
// LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
// ^ indirizzo alternativo, da attivare al posto della precedente istruzione se lcd non funziona
// ^^ Alternative address, to activate in place of previous instruction if LCD doesn't work
int wakePin = 2; // Pin per risveglio da ds3231- pin used for alarm clock (interrupt 0)
int portarisveglio = 3; // porta risveglio da pulsante - pin used for button wakuo (interrupy 1)
int relay = 4; // porta cui e' collegato il relay - relay pin
int statosensore = 0; // valore rilevato dal sensore di umidita' - value from moisture sensor
float momentoinizio; // momento inizio controllo umidita - moisture check, starting time
float momentocorrente; // momento corrente / current time
float durata = 15000; // millisec durata controllo e irrigazione - check and irrigation time
DS3231 clock;
RTCDateTime dt;
// nelle prossime righe sono presenti le diverse possibilita di attivazione dell'allarme, da
// utilizzare in fase di settaggio (nella sessione di loop)
// here some different alarm type, to use in loop section:
#define ALRM1_MATCH_EVERY_SEC 0b1111 // ogni secondo - once a second
#define ALRM1_MATCH_SEC 0b1110 // quando ricorre il secondo - when seconds match
#define ALRM1_MATCH_MIN_SEC 0b1100 // quando ricorrono min e sec. - when min and sec match
#define ALRM1_MATCH_HR_MIN_SEC 0b1000 // ora, minuto e secondo - hours, minutes, and seconds match
byte temp_buffer = 0b11110111; // configurazione byte che disabilita il pin SQW sul modulo DS3231.
// Sembra inutile, ma senza di questo arduino non si addormenta. Byte to disable the Ds3231 SQW pin,
// not logical yes, but without that the Arduino doesn't go to sleep mode even the first time
char print_date[16]; // data ed ora in formto stampa - current time in print format
//
// ****** routine di modifica del byte di controllo DS3231 - Set DS3121 SQW control bytes
//
void modificabyte (byte control, bool which) // Set DS3121 RTC control bytes
{
Wire.beginTransmission(0x68);
if (which) // which=false -> 0x0e, true->0x0f.
Wire.write(0x0f);
else
Wire.write(0x0e);
Wire.write(control);
Wire.endTransmission();
}
//
// ********** routine di sveglia lanciata da un iterrupt tramite un pulsante ***********
// ********** here the interrupt by button is handled after wakeup ***********
//
void svegliatiora1()
{
sleep_disable(); // disabilita la funzione sleep
detachInterrupt(1); // disabilita l'interrupt
// le due precedenti istruzioni devono essere le prime ad essere eseguite al momento del
// risveglio, in modo da evitare eventuali ulteriori interrupt derivanti dalla pressione del
// pulsante These two instruction must be execute at first after wake up
}
//
// ******** routine di sveglia, attivata dall'interrupt su allarme DS3231 *********
// Arduino: Irrigatore a basso consumo - Low absorption sprinkler // RTC, sleep, interrupt, lcd 1620, I2C
// ******** wake routine, activated on interrupt from ds3231 *********
//
void svegliatiora()
{
sleep_disable(); // disabilita la funziona sleep)
}
//
// ************** routine di "addormentamento" - sleep routine **************
//
void dormiora()
{
sleep_enable(); // abilita l'addormentamento del sistema
delay(100);
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // Seleziona la modalita' "power down", che massimizza
// il risparmio di energia - Select "power down mode" to maximize energy saving
attachInterrupt(1, svegliatiora1, LOW); // abilita la ricezione di un interrupt di tipo 1
// (tramite pulsante) e lancia la routine "svegliatiora1".
// Use interrupt #1 (from button on pin 3) and run "svegliatiora1" function
cli(); // disabilita l'interrupt - disable interrupts
sleep_bod_disable(); // disabilita il controllo interno di alimentazione (brown out detection)
sei(); // riabilita l'interrupt - enable interrupts
sleep_cpu(); // "addormenta" la cpu - sleep mode on cpu
}
//
//******* funzioni di preparazione al risveglio / wake preparation functions *****************
//
void sveglia ()
{
clock.clearAlarm1(); // elimina l'allarme (per evitare ulteriori indesiderati interrupt)
lcd.clear ();
lcd.backlight(); // accende lo schermo - turn on lcd back light
lcd.print("working.. ");
dt = clock.getDateTime(); // chiede l'ora dall'orologio digitale DS3231 - get time form DS3231
sprintf(print_date, " %02d:%02d:%02d ", dt.hour, dt.minute, dt.second);
lcd.setCursor (0, 1);
lcd.print(print_date); // visualizza il momento della sveglia - display wake time on lcd
delay (2000); // 2 secondi per leggere il display / 2 seconds to read display
}
//
//*********** funzioni di preparazione all'addormentamento - sleep preparation functions **********
//
void preparasonno ()
{
digitalWrite(relay, LOW); // disattiva il rele' - deactivate relay
dt = clock.getDateTime(); // chiede l'ora dall'orologio digitale DS3231 - get time form DS3231
sprintf(print_date, " %02d:%02d:%02d ", dt.hour, dt.minute, dt.second);
lcd.setCursor (0,1);
lcd.print (print_date); // visualizza momento addormentamento - display sleeping start time
lcd.setCursor (0, 1);
lcd.print ("standby & sleep ");
delay (2000); // 2 secondi per la lettura del display /2 secods to read display
lcd.noBacklight(); // spegne l'illuminazione dello schermo /turn off lcd back light
delay(500);
lcd.clear ();
}
//
// controlla umidita' ed attiva il rele / soil moisture control and, if necessary, relay activation
//
void controllaumidita ()
{
momentoinizio = millis(); // memorizza inizio controllo - store check activity start time
momentocorrente = millis (); // inizializza il momento corrente - store current time
while ((momentocorrente - momentoinizio) < durata) //ciclo di controllo / check moisture loop
{
momentocorrente = millis ();
dt = clock.getDateTime(); // chiede l'ora all'orologio DS3231 - get time form DS3231
sprintf(print_date, " %02d:%02d:%02d ", dt.hour, dt.minute, dt.second);
lcd.setCursor (0, 1);
lcd.print(print_date); // visualizza ora corrente - display current time
statosensore = analogRead(A0); // valore umidita- read value from moisture sensor
lcd.setCursor (0, 0);
lcd.print ("humidity: ");
lcd.print (statosensore); // espone il valore di umidita' rilevato /humidity value on lcd
lcd.print (" ");
delay (1000); // tempo di lettura del display - display reading time
if (statosensore <= 450) // verifica il livello di umidita' / check moisture level
{
digitalWrite(relay, LOW); // disattiva il rele' - deactivate relay
// Arduino: Irrigatore a basso consumo - Low absorption sprinkler // RTC, sleep, interrupt, lcd 1620, I2C
lcd.setCursor (0, 0);
lcd.print ("relay off ");
}
if (statosensore >= 750) // verifica il livello di umidita' / check moisture level
{
digitalWrite(relay, HIGH); // attiva il rele' - activate relay
lcd.setCursor (0, 0);
lcd.print ("relay on ");
}
delay (1000); // attende prima di un nuovo controllo - wait before new check
}
digitalWrite(relay, LOW); // disattiva il rele' - deactivate relay
lcd.setCursor (0, 0);
lcd.print ("relay off ");
delay (1000);
}
//
//
void setup()
{
Serial.begin(9600);
clock.begin();
modificabyte(temp_buffer, 0);
clock.armAlarm1(false);
clock.armAlarm2(false);
clock.clearAlarm1();
clock.clearAlarm2();
pinMode (relay, OUTPUT); // alla porta 4 e' collegato il relay /relay on pin 4
pinMode (portarisveglio, INPUT); // il pulsante e' collegato alla porta 3 / button on pin 3
pinMode(wakePin, INPUT); // pin 2 per allarme da DS3232 - pin 2 for alarm from ds3232
attachInterrupt(0, svegliatiora, FALLING); // attiva l'interrupts - enable intrrupts form ds3231
clock.setDateTime(2019, 5, 11, 17, 59, 50); /* inizializza l'orologio con data ed ora prefissata,
l'orologio deve essere inizializzato una sola volta, con data ed ora effettiva dopo di che
l'istruzione deve essere cancellata ed il programma deve essere ricompilato - initializes ds3231
with date and hour. Use only at the first launch for clock set. After that delete this instruction
and ricompile */
lcd.begin(16, 2); // inizializza il display
for (int i = 0; i < 3; i++) // fa lampeggiare per tre volte lo sfondo
{
lcd.backlight();
delay(250);
lcd.noBacklight();
delay(250);
}
lcd.backlight(); // termina mantenendo illuminato lo sfondo
lcd.setCursor(0, 0);
lcd.print("hallo! ");
lcd.setCursor (0, 1);
dt = clock.getDateTime(); // chiede l'ora dall'orologio digitale DS3231 - get time form DS3231
sprintf(print_date, " %02d:%02d:%02d ", dt.hour, dt.minute, dt.second);
lcd.print (print_date); // visualizza sul display il momento corrente - show current time
delay(2000);
}
//
//
void loop()
{
clock.setAlarm1(00, 18, 00, 00, ALRM1_MATCH_HR_MIN_SEC); //attiva l'interrupt (la sveglia) alle
// ore 18:00 di ogni giorno - set alarm at 18:00
delay (100);
preparasonno (); // funzioni di preparazione all'addormentamento / sleep preparation
dormiora(); // addormentamento - call sleep routine
// **** punto in cui il sistema rientra nella sezione di loop dopo il risveglio - arduino start
// working here after woke
sveglia (); // funzioni di preparazione alla sveglia /wake preparation functions
controllaumidita (); // controllo umidita irrigazione - checks humidity and irrigation
}