/*-----( Importa le librerie necessarie)-----*/ #include "LiquidCrystal.h" #include "Wire.h" #include #include DS3231 Clock; RTClib myRTC; //DateTime now = myRTC.now(); // se inserisco l'istruzione qui, come globale, Arduino si blocca anche se la compilazione e il caricamento sono OK // perché il programma funzioni è necessario ripeterla in ogni loop usandola come variabile locale /*-----( Dichiarazione delle costanti )-----*/ #define pulsRIGHT 0 // sono i numeri associati ad ogni intervallo #define pulsUP 1 // della lettura analogica dei pulsanti di DFROBOT #define pulsDOWN 2 #define pulsLEFT 3 #define pulsSELECT 4 #define pulsNONE 5 #define pompa 3 // associo a "pompa" il numero tre che poi utilizzo come numero del piedino nell'istruzione digitaWrite(piedino, stato) #define valvola_1 11 // associo a "valvola_1" il numero 11 #define valvola_2 12 // associo a "valvola_2" il numero 12 #define valvola_3 13 // associo a "valvola_3" il numero 13 /*-----( Dichiarazioni Variabili globali)-----*/ int lcd_key = 0; int adc_key_in = 0; int adc_key_prev = 0; boolean fatto=false; //boolean pompa_on = true; boolean valvola_1_on =true; boolean valvola_2_on =false; boolean valvola_3_on=false; byte alle_ore=0; byte tempo_v1=0; byte tempo_v2=0; byte tempo_v3=0; byte tempo_totale=0; byte Year=21; byte Month=5; byte Day=30; byte Hour=21; byte Minute=48; byte Second=00; byte tempo_rimasto=0; int anno; int a=0; // indirizzi della EEPROM su cui scrivere o leggere il dato int t_t=1; int v1=3; int v2=4; int v3=5; int t1=6; int t2=7; int t3=8; LiquidCrystal lcd(8, 9, 4, 5, 6, 7); //Sono i piedini usati dal display DFROBOT void setup() /*---- SETUP: Viene letto solo alla partenza ----*/ { Serial.begin(9600); // attiva la porta seriale verso il PC Wire.begin(); // Fa partire la comunicazione con l'orologio lcd.begin(16, 2); // Fa partire l'oggetto display lcd pinMode(pompa, OUTPUT); // dichiaro l'uso dei piedini pinMode(valvola_1, OUTPUT); pinMode(valvola_2, OUTPUT); pinMode(valvola_3, OUTPUT); digitalWrite(pompa, HIGH); // dichiaro lo stato dei piedini digitalWrite(valvola_1, HIGH); // i relais scattano con il piedino basso digitalWrite(valvola_2, HIGH); digitalWrite(valvola_3, HIGH); lcd.clear(); lcd.setCursor(0,0); // alla partenza descrivo il software e come si usa lcd.print("Irrigatore 2021"); lcd.setCursor(0,1); lcd.print("di Pino Grasso"); delay (3000); lcd.clear(); lcd.setCursor(0,0); lcd.print("Puls SELECT "); lcd.setCursor(0,1); lcd.print("setta orologio"); delay (3000); lcd.clear(); lcd.setCursor(0,0); lcd.print("Puls LEFT setta"); lcd.setCursor(0,1); lcd.print("irrig. max 58min"); delay (3000); lcd.clear(); lcd.setCursor(0,0); lcd.print("Puls UP e DOWN"); lcd.setCursor(0,1); lcd.print("cambiano valori"); delay (3000); lcd.clear(); lcd.setCursor(0,0); lcd.print("Indicazioni"); lcd.setCursor(0,1); lcd.print("attuali "); delay (3000); }/*--(Fine setup )---*/ void loop() /*----( LOOP: Gira costantemente)----*/ { alle_ore = EEPROM.read(a); // leggo i dati registrati sulla EEPROM tempo_totale=EEPROM.read(t_t); valvola_1_on= EEPROM.read(v1); valvola_2_on= EEPROM.read(v2); valvola_3_on= EEPROM.read(v3); tempo_v1 = EEPROM.read(t1); tempo_v2 = EEPROM.read(t2); tempo_v3 = EEPROM.read(t3); DateTime now = myRTC.now(); anno=now.year(), DEC; // leggo l'orologio e metto i dati nelle variabili Year=anno-2000; // now.year ritorna un numero a 4 cifre mentre l'orologio vuole solo le ultime due Month=now.month(), DEC; Day=now.day(), DEC; Hour=now.hour(),DEC; Minute=now.minute(),DEC; Second=now.second(),DEC; lcd.clear(); // pulisco, posiziono il cursore e scrivo lcd.setCursor(0,0); // la data, ore e minuti che segna l'orologio lcd.print(anno); lcd.setCursor(4,0); lcd.print("/"); lcd.setCursor(5,0); lcd.print(Month); lcd.setCursor(7,0); lcd.print("/"); lcd.setCursor(8,0); lcd.print(Day); lcd.setCursor(10,0); lcd.print(" "); lcd.setCursor(11,0); lcd.print(Hour); lcd.setCursor(13,0); lcd.print(":"); lcd.setCursor(14,0); lcd.print(Minute); lcd.setCursor(0,1); // alla riga sotto scrivo lcd.print("Ore "); // le indicazioni attuali per l'irrorazione lcd.setCursor(4,1); lcd.print(alle_ore); lcd.setCursor(7,1); lcd.print("per "); lcd.setCursor(11,1); lcd.print(tempo_totale); lcd.setCursor(14,1); lcd.print("mn"); // controlla se e' stato pigiato qualche pulsante adc_key_prev = lcd_key ; // Mette da parte il valore che c'era nella variabile delle letture lcd_key = read_LCD_buttons(); // Mette il valore ritornato dalla funzione read_LCD_button in lcd_key if (adc_key_prev != lcd_key) // se i valori sono diversi da prima qualcuno sta pigiando un bottone { if (lcd_key == pulsSELECT) // se il pulsante premuto e' SELECT salta alla funzione setta orologio { setta_orologio(); } if (lcd_key == pulsLEFT) // se il pulsante premuto e' LEFT salta alla funzione setta irrora { setta_irrora(); } } delay(100); if (valvola_1_on == false) {tempo_v1=0;} // se non si vuole usare una valvola setta a zero il tempo di apertura if (valvola_2_on == false) {tempo_v2=0;} if (valvola_3_on == false) {tempo_v3=0;} // salta a irrora all'ora giusta e se i minuti trascorsi dall'inizio dell'ora sono minori del tempo di irrigazione if (Hour == alle_ore && Minute < tempo_totale){irrora();} } // Chiusura LOOP principale /*-----( Dichiarazione di funzioni)-----*/ // funzione che legge il valore sul piedino Analogico 0 // a seconda del numero letto riconosce quale pulsante sia stato pigiato e ritorna quel numero a chi l'ha chiamata. int read_LCD_buttons() { adc_key_in = analogRead(0); // legge il valore del piedino A0 delay(5); //aspetta 5 millisecondi. Incrementare questo valore se le letture sono sbagliate int k = (analogRead(0) - adc_key_in); //mettiamo dentro k la differenza tra il valore letto e zero if (5 < abs(k)) return pulsNONE; // se il valore letto e' minore di cinque la funzione ritorna che nessun bottone e' stato pigiato if (adc_key_in > 1000) return pulsNONE; if (adc_key_in < 50) return pulsRIGHT; if (adc_key_in < 195) return pulsUP; if (adc_key_in < 380) return pulsDOWN; if (adc_key_in < 555) return pulsLEFT; if (adc_key_in < 790) return pulsSELECT; return pulsNONE; // ritorna questo valore quando nessun valore letto corrisponde al valore definito per i pulsanti } // FUNZIONE CHE CAMBIA I VALORI ALL'OROLOGIO int setta_orologio() { Clock.setClockMode(false); // set to 24h //setClockMode(true); // set to 12h lcd.clear(); lcd.setCursor(1,0); lcd.print("anno?"); do{ adc_key_prev = lcd_key ; lcd_key = read_LCD_buttons(); if (adc_key_prev != lcd_key) // se i valori sono diversi da prima qualcuno sta pigiando un bottone { if (lcd_key == pulsSELECT){fatto=true;} if (lcd_key == pulsUP){Year=Year+1;} if (lcd_key == pulsDOWN){Year=Year-1;} if (Year < 21) {Year=21;} // controllo i valori limite if (Year > 99) {Year=99;} } lcd.setCursor(1,1); lcd.print(Year); } while (fatto==false); delay (1000); fatto=false; lcd.clear(); lcd.setCursor(1,0); lcd.print("mese?"); do{ adc_key_prev = lcd_key ; lcd_key = read_LCD_buttons(); if (adc_key_prev != lcd_key) // se i valori sono diversi da prima qualcuno sta pigiando un bottone { if (lcd_key == pulsSELECT){fatto=true;} if (lcd_key == pulsUP){Month=Month+1;} if (lcd_key == pulsDOWN){Month=Month-1;} if (Month<1){Month=1;} // controllo i valori limite if (Month>12){Month=12;} } lcd.setCursor(1,1); lcd.print(Month); } while (fatto==false); delay (1000); fatto=false; lcd.clear(); lcd.setCursor(1,0); lcd.print("giorno?"); do{ adc_key_prev = lcd_key ; lcd_key = read_LCD_buttons(); if (adc_key_prev != lcd_key) // se i valori sono diversi da prima qualcuno sta pigiando un bottone { if (lcd_key == pulsSELECT){fatto=true;} if (lcd_key == pulsUP){Day=Day+1;} if (lcd_key == pulsDOWN){Day=Day-1;} if (Day<1){Day=1;} // controllo i valori limite if (Day>31){Day=31;} } lcd.setCursor(1,1); lcd.print(Day); } while (fatto==false); delay (1000); fatto=false; lcd.clear(); lcd.setCursor(1,0); lcd.print("ore?"); do{ adc_key_prev = lcd_key ; lcd_key = read_LCD_buttons(); if (adc_key_prev != lcd_key) // se i valori sono diversi da prima qualcuno sta pigiando un bottone { if (lcd_key == pulsSELECT){fatto=true;} if (lcd_key == pulsUP){Hour=Hour+1;} if (lcd_key == pulsDOWN){Hour=Hour-1;} if (Hour<1) {Hour=1;} // controllo i valori limite if (Hour>24) {Hour=24;} } lcd.setCursor(1,1); lcd.print(Hour); } while (fatto==false); delay (1000); fatto=false; lcd.clear(); lcd.setCursor(1,0); lcd.print("minuti?"); do{ adc_key_prev = lcd_key ; lcd_key = read_LCD_buttons(); if (adc_key_prev != lcd_key) // se i valori sono diversi da prima qualcuno sta pigiando un bottone { if (lcd_key == pulsSELECT){fatto=true;} if (lcd_key == pulsUP){Minute=Minute+1;} if (lcd_key == pulsDOWN){Minute=Minute-1;} if (Minute<0) {Minute=0;} // controllo i valori limite if (Minute>58) {Minute=58;} } lcd.setCursor(1,1); lcd.print(Minute); } while (fatto==false); delay (1000); fatto=false; lcd.clear(); lcd.setCursor(1,0); lcd.print("modifico data"); modifica_orologio(); // salto alla funzione che modifica l'orologio delay (2000); } // FUNZIONE CHE MODIFICA L'OROLOGIO int modifica_orologio(){ Clock.setYear(Year); // uso le istruzioni presenti Clock.setMonth(Month); // nella libreria DS3231 Clock.setDate(Day); // per modificare i dati dell'orologio //Clock.setDoW(DoW); Clock.setHour(Hour); Clock.setMinute(Minute); Clock.setSecond(Second); } /* FUNZIONE PER SETTARE ORA DI IRRIGAZIONE, TEMPO DI IRRIGAZIONE E STRUMENTI DI IRRIGAZIONE */ int setta_irrora() { alle_ore = EEPROM.read(a); // leggo i valori salvati nella EEPROM valvola_1_on = EEPROM.read(v1); valvola_2_on = EEPROM.read(v2); valvola_3_on = EEPROM.read(v3); tempo_v1 = EEPROM.read(t1); tempo_v2 = EEPROM.read(t2); tempo_v3 = EEPROM.read(t3); tempo_totale=EEPROM.read(t_t); lcd.clear(); lcd.setCursor(0,0); lcd.print("Alle ore?"); // pulisco display e chiedo delay (100); // a che ora deve iniziare l'irrorazione fatto=false; do{ lcd_key = 5; adc_key_prev = lcd_key ; delay (100); lcd_key = read_LCD_buttons(); //delay (10); if (adc_key_prev != lcd_key) // se i valori sono diversi da prima qualcuno sta pigiando un bottone { if (lcd_key == pulsLEFT){fatto=true;} //delay (100); if (lcd_key == pulsUP){alle_ore=alle_ore + 1;} if (lcd_key == pulsDOWN){alle_ore=alle_ore - 1;} if (alle_ore > 23) {alle_ore=0;} // controllo i valori limite if (alle_ore < 0) {alle_ore=0;} } lcd.setCursor(0,1); lcd.print(" "); lcd.setCursor(0,1); lcd.print(alle_ore); // delay (100); } while (fatto==false); delay (100); fatto=false; lcd.clear(); lcd.setCursor(0,0); lcd.print("Valvola 1 attiva?"); // chiedo se si vuole usare la valvola uno do{ adc_key_prev = lcd_key ; lcd_key = read_LCD_buttons(); delay (10); if (adc_key_prev != lcd_key) // se i valori sono diversi da prima qualcuno sta pigiando un bottone { delay (10); if (lcd_key == pulsLEFT){fatto=true;} if (lcd_key == pulsUP){valvola_1_on=false;} if (lcd_key == pulsDOWN){valvola_1_on=true;} } lcd.setCursor(0,1); lcd.print(" "); lcd.setCursor(0,1); if (valvola_1_on==true) {lcd.print("si");} if (valvola_1_on==false) {lcd.print("no");} delay (100); } while (fatto==false); delay (100); if (valvola_1_on==true) // se si vuole usare setto il tempo di utilizzo { fatto=false; lcd.clear(); lcd.setCursor(0,0); lcd.print("Tempo V1?"); do{ adc_key_prev = lcd_key ; lcd_key = read_LCD_buttons(); delay (10); if (adc_key_prev != lcd_key) // se i valori sono diversi da prima qualcuno sta pigiando un bottone { delay (10); if (lcd_key == pulsLEFT){fatto=true;} if (lcd_key == pulsUP){tempo_v1=tempo_v1+1;} if (lcd_key == pulsDOWN){tempo_v1=tempo_v1-1;} if (tempo_v1 < 1) {tempo_v1=1;} // controllo i valori limite if (tempo_v1 >58) {tempo_v1=58;} } lcd.setCursor(0,1); lcd.print(" "); lcd.setCursor(0,1); lcd.print(tempo_v1); delay (100); } while (fatto==false); delay (100); } fatto=false; lcd.clear(); lcd.setCursor(0,0); lcd.print("Valvola 2 attiva?"); // chiedo se si vuole usare la valvola due do{ adc_key_prev = lcd_key ; lcd_key = read_LCD_buttons(); delay (10); if (adc_key_prev != lcd_key) // se i valori sono diversi da prima qualcuno sta pigiando un bottone { delay (10); if (lcd_key == pulsLEFT){fatto=true;} if (lcd_key == pulsUP){valvola_2_on=false;} if (lcd_key == pulsDOWN){valvola_2_on=true;} } lcd.setCursor(0,1); lcd.print(" "); lcd.setCursor(0,1); if (valvola_2_on==true) {lcd.print("si");} if (valvola_2_on==false) {lcd.print("no");} delay (100); } while (fatto==false); delay (100); if (valvola_2_on==true) // se si vuole usare setto il tempo di utilizzo { fatto=false; lcd.clear(); lcd.setCursor(0,0); lcd.print("Tempo V2?"); do{ adc_key_prev = lcd_key ; lcd_key = read_LCD_buttons(); delay (10); if (adc_key_prev != lcd_key) // se i valori sono diversi da prima qualcuno sta pigiando un bottone { delay (10); if (lcd_key == pulsLEFT){fatto=true;} if (lcd_key == pulsUP){tempo_v2=tempo_v2+1;} if (lcd_key == pulsDOWN){tempo_v2=tempo_v2-1;} tempo_rimasto = 58-tempo_v1; if (tempo_v2 < 1) {tempo_v2=1;} // controllo che il tempo non superi il tempo di irrigazione massimo if (tempo_v2 > tempo_rimasto) {tempo_v2= tempo_rimasto;} // il tempo di irrigazione massimo e' 58 minuti } lcd.setCursor(0,1); lcd.print(" "); lcd.setCursor(0,1); lcd.print(tempo_v2); delay (100); } while (fatto==false); delay (100); } fatto=false; lcd.clear(); lcd.setCursor(0,0); lcd.print("Valvola 3 attiva?"); // chiedo se si vuole usare la valvola tre do{ adc_key_prev = lcd_key ; lcd_key = read_LCD_buttons(); delay (10); if (adc_key_prev != lcd_key) // se i valori sono diversi da prima qualcuno sta pigiando un bottone { delay (10); if (lcd_key == pulsLEFT){fatto=true;} if (lcd_key == pulsUP){valvola_3_on=false;} if (lcd_key == pulsDOWN){valvola_3_on=true;} } lcd.setCursor(0,1); lcd.print(" "); lcd.setCursor(0,1); if (valvola_3_on==true) {lcd.print("si");} if (valvola_3_on==false) {lcd.print("no");} delay (100); } while (fatto==false); delay (100); if (valvola_3_on==true) // se si vuole usare setto il tempo di utilizzo { fatto=false; lcd.clear(); lcd.setCursor(0,0); lcd.print("Tempo V3?"); do{ adc_key_prev = lcd_key ; lcd_key = read_LCD_buttons(); delay (10); if (adc_key_prev != lcd_key) // se i valori sono diversi da prima qualcuno sta pigiando un bottone { delay (10); if (lcd_key == pulsLEFT){fatto=true;} if (lcd_key == pulsUP){tempo_v3=tempo_v3+1;} if (lcd_key == pulsDOWN){tempo_v3=tempo_v3-1;} tempo_rimasto = 58 - (tempo_v1+tempo_v2); // controllo che il tempo non superi il tempo di irrigazione massimo if (tempo_v3 < 1) {tempo_v3=1;} //il tempo di irrigazione massimo e' 58 minuti if (tempo_v3 > tempo_rimasto) {tempo_v3=tempo_rimasto;} } lcd.setCursor(0,1); lcd.print(" "); lcd.setCursor(0,1); lcd.print(tempo_v3); delay (100); } while (fatto==false); delay (100); } if (valvola_1_on == false){tempo_v1=0;} if (valvola_2_on == false){tempo_v2=0;} if (valvola_3_on == false){tempo_v3=0;} tempo_totale=tempo_v1 + tempo_v2 + tempo_v3 ; EEPROM.update(a, alle_ore); // scrivo sulla EEPROM i valori delle variabili EEPROM.update(t_t, tempo_totale); // solo se sono diversi dai valori che c'erano prima EEPROM.update(v1, valvola_1_on); // con il comando update invece che write EEPROM.update(v2, valvola_2_on); EEPROM.update(v3, valvola_3_on); EEPROM.update(t1, tempo_v1); EEPROM.update(t2, tempo_v2); EEPROM.update(t3, tempo_v3); lcd.clear(); lcd.setCursor(1,0); lcd.print("Dati salvati"); delay (1000); } // FUNZIONE IRRORA void irrora() { DateTime now = myRTC.now(); Hour=now.hour(),DEC; Minute=now.minute(),DEC; if (Hour!=alle_ore){return;} if (Minute>=tempo_totale){return;} digitalWrite(pompa,LOW); // accendo la pompa if (valvola_1_on ==true) // se è previsto l'uso della valvola 1 { do { DateTime now = myRTC.now(); Minute=now.minute(),DEC; Second=now.second(),DEC; if (Minute>=tempo_v1){break;} // se l'orologio ha superato i minuti di irrigazione esco dal ciclo do-while digitalWrite(valvola_1, LOW); // apro la valvola 1 lcd.clear(); lcd.setCursor(0,0); // mostro sul display cosa succede lcd.print("Valvola 1 open"); lcd.setCursor(0,1); lcd.print("Per"); lcd.setCursor(4,1); lcd.print(tempo_v1); lcd.setCursor(7,1); lcd.print("Min"); lcd.setCursor(10,1); lcd.print(Minute-(tempo_v1)); // i minuti che mancano alla chiusura lcd.setCursor(14,1); lcd.print(60-Second); // e lo scorrere dei secondi delay (1000); }while(Minute <= tempo_v1); // continua a girare fino a quando non scade il tempo previsto digitalWrite(valvola_1, HIGH); // chiudo la valvola 1 } if (valvola_2_on ==true) // stesse operazioni per la valvola 2 { do{ DateTime now = myRTC.now(); Minute=now.minute(),DEC; if (Minute>=(tempo_v1+tempo_v2)){break;} Second=now.second(),DEC; digitalWrite(valvola_2, LOW); // apro la valvola 2 lcd.clear(); lcd.setCursor(0,0); lcd.print("Valvola 2 open"); lcd.setCursor(0,1); lcd.print("Per"); lcd.setCursor(4,1); lcd.print(tempo_v2); lcd.setCursor(7,1); lcd.print("Min"); lcd.setCursor(10,1); lcd.print(Minute-(tempo_v1+tempo_v2)); lcd.setCursor(14,1); lcd.print(60-Second); delay (1000); }while (Minute <= (tempo_v1+tempo_v2)); digitalWrite(valvola_2, HIGH); // chiudo la valvola 2 } if (valvola_3_on ==true) // stesse operazioni per la valvola 3 { do{ DateTime now = myRTC.now(); Minute=now.minute(),DEC; Second=now.second(),DEC; if (Minute>=tempo_v1+tempo_v2+tempo_v3){break;} digitalWrite(valvola_3, LOW); // apro la valvola 3 lcd.clear(); lcd.setCursor(0,0); lcd.print("Valvola 3 open"); lcd.setCursor(0,1); lcd.print("Per"); lcd.setCursor(4,1); lcd.print(tempo_v3); lcd.setCursor(7,1); lcd.print("Min"); lcd.setCursor(10,1); lcd.print(Minute-(tempo_v1+tempo_v2+tempo_v3)); lcd.setCursor(14,1); lcd.print(60-Second); delay (1000); }while (Minute <= (tempo_v1+tempo_v2+tempo_v3)); digitalWrite(valvola_3, HIGH); // chiudo la valvola 3 } digitalWrite(pompa,HIGH); // alla fine spengo anche la pompa }