Continuando nella realizzazione della tua centralina irrigazione arduino è giunto il momento di integrare i pulsanti ed il display LCD allo sketch di controllo della centralina irrigazione arduino: Per integrare pulsanti e display dovrai modificare lo sketch per consentirgli di gestire i nuovi componenti presenti. Non è nulla di nuovo, se hai letto gli articoli:
ed un precedente articolo:
Noterai che questo sketch è un insieme di parti provenienti da quegli articoli. Spesso quando realizzi un progetto prendi sketch o parti di sketch da differenti siti o da tuoi precedenti esperimenti e questo è senza dubbio uno di quei progetti in cui riutilizzare del buon codice già scritto in precedenza ti semplifica la vita e velocizza il raggiungimento del risultato.
Sketch della centralina irrigazione arduino
Lo sketch che riporto di seguito è stato arricchito e modificato con alcune funzioni:
/********************************************************** * Centralina irrigazione arduino * * Data creazione 20 maggio 2013 * Ultima modifica 30 luglio 2013 * * autore: Mauro Alfieri * web: mauroalfieri.it * tw: @mauroalfieri * /**********************************************************/ #include <Wire.h> #include <RTClib.h> #include <LiquidCrystal.h> /**********************************************************/ #define pinSettore1 5 #define pinSettore2 6 #define pinSettore3 7 #define pinSettore4 8 #define BUTTON A0 /**********************************************************/ int settore1[] = {15,40,15,41}; int settore2[] = {15,42,15,43}; int settore3[] = {15,44,15,45}; int settore4[] = {15,46,15,47}; int SELECT[] = {0,20}; // pulsante A int LEFT[] = {500,520}; // pulsante B int RIGTH[] = {670,690}; // pulsante C int UP[] = {760,780}; // pulsante D int DOWN[] = {810,830}; // pulsante E char buffer[10]; unsigned long time=0; unsigned long timeSet=0; int setModeTime=2000; /**********************************************************/ RTC_DS1307 RTC; LiquidCrystal lcd(4, 3, 10, 11, 12, 13); /**********************************************************/ void setup() { Serial.begin(9600); Serial.println( "START" ); Wire.begin(); RTC.begin(); lcd.begin(16, 2); pinMode( pinSettore1,OUTPUT ); pinMode( pinSettore2,OUTPUT ); pinMode( pinSettore3,OUTPUT ); pinMode( pinSettore4,OUTPUT ); RTC.sqw(0); //0 Led off - 1 Freq 1Hz - 2 Freq 4096kHz - 3 Freq 8192kHz - 4 Freq 32768kHz if (! RTC.isrunning()) { Serial.println("RTC is NOT running!"); RTC.adjust(DateTime(__DATE__, __TIME__)); } digitalWrite( pinSettore1,LOW ); digitalWrite( pinSettore2,LOW ); digitalWrite( pinSettore3,LOW ); digitalWrite( pinSettore4,LOW ); lcd.clear(); } /**********************************************************/ void loop() { if ( RTC.isrunning()) { DateTime now = RTC.now(); int _button = ctrlButton( analogRead( BUTTON ) ); if ( _button == 0 || _button > 1) { time = millis(); } Serial.print(now.year(), DEC); Serial.print('/'); Serial.print(now.month(), DEC); Serial.print('/'); Serial.print(now.day(), DEC); Serial.print(' '); Serial.print(now.hour(), DEC); Serial.print(':'); Serial.print(now.minute(), DEC); Serial.print(':'); Serial.print(now.second(), DEC); Serial.print(' pulsante: '); Serial.print(_button); Serial.println(); int _hour = now.hour(); int _minute = now.minute(); start_impianto( _hour, _minute ); view_date_time( now ); if (time > 0 && setModeTime < (millis() - time) ) { setMode( now ); } } } /**********************************************************/ void start_impianto( int _hour, int _minute ) { // Settore Uno if ( settore1[0] <= _hour && _hour <= settore1[2] && settore1[1] <= _minute && _minute <= settore1[3] ) { digitalWrite( pinSettore1,HIGH ); } else { digitalWrite( pinSettore1,LOW ); } // Settore Due if ( settore2[0] <= _hour && _hour <= settore2[2] && settore2[1] <= _minute && _minute <= settore2[3] ) { digitalWrite( pinSettore2,HIGH ); } else { digitalWrite( pinSettore2,LOW ); } // Settore Tre if ( settore3[0] <= _hour && _hour <= settore3[2] && settore3[1] <= _minute && _minute <= settore3[3] ) { digitalWrite( pinSettore3,HIGH ); } else { digitalWrite( pinSettore3,LOW ); } // Settore Quattro if ( settore4[0] <= _hour && _hour <= settore4[2] && settore4[1] <= _minute && _minute <= settore4[3] ) { digitalWrite( pinSettore4,HIGH ); } else { digitalWrite( pinSettore4,LOW ); } } /**********************************************************/ int ctrlButton( int button ) { if ( SELECT[0] <= button && button <= SELECT[1] ) { return 1; } if ( LEFT[0] <= button && button <= LEFT[1] ) { return 2; } if ( RIGTH[0] <= button && button <= RIGTH[1] ) { return 3; } if ( UP[0] <= button && button <= UP[1] ) { return 4; } if ( DOWN[0] <= button && button <= DOWN[1] ) { return 5; } return 0; } /**********************************************************/ void view_date_time ( DateTime now ) { lcd.clear(); sprintf(buffer, "%02d/%02d/%d", now.day(), now.month(), now.year()); lcd.setCursor(0,0); lcd.print( buffer ); char buffer[10] = ""; sprintf(buffer, "%02d:%02d:%02d", now.hour(), now.minute(), now.second()); lcd.setCursor(0,1); lcd.print( buffer ); delay(1000); } /**********************************************************/ void setMode( DateTime now ) { boolean setMode = true; int setModeLevel = 0; int _day = now.day(); int _month = now.month(); int _year = now.year(); int _hour = now.hour(); int _min = now.minute(); int _sec = now.second(); lcd.clear(); lcd.setCursor(0,0); sprintf(buffer, "%s: %02d", "Giorno", _day); delay( 1000 ); timeSet = millis(); while ( setMode ) { int _button = ctrlButton( analogRead( BUTTON ) ); if ( _button > 1 ) { timeSet = millis(); } lcd.setCursor(0,0); // Set Day if ( setModeLevel == 0 ) { if ( _button == 3 && _day < 31) { _day++; } if ( _button == 2 && _day > 1) { _day--; } sprintf(buffer, "%s: %02d", "Giorno", _day); } // Set Month if ( setModeLevel == 1 ) { if ( _button == 3 && _month < 12) { _month++; } if ( _button == 2 && _month > 1) { _month--; } sprintf(buffer, "%s: %02d", "Mese", _month); } // Set Year if ( setModeLevel == 2 ) { if ( _button == 3 && _year < 9999) { _year++; } if ( _button == 2 && _year > 1900) { _year--; } sprintf(buffer, "%s: %02d", "Anno", _year); } // Set Hour if ( setModeLevel == 3 ) { if ( _button == 3 && _hour < 24) { _hour++; } if ( _button == 2 && _hour > 1) { _hour--; } sprintf(buffer, "%s: %02d", "Ora", _hour); } // Set Minute if ( setModeLevel == 4 ) { if ( _button == 3 && _min < 60) { _min++; } if ( _button == 2 && _min > 1) { _min--; } sprintf(buffer, "%s: %02d", "Minuti", _min); } // Set Second if ( setModeLevel == 5 ) { if ( _button == 3 && _sec < 60) { _sec++; } if ( _button == 2 && _sec > 0) { _sec--; } sprintf(buffer, "%s: %02d", "Secondi", _sec); } lcd.print( buffer ); if ( _button == 5 ) { lcd.clear(); setModeLevel++; } if ( _button == 4 ) { lcd.clear(); setModeLevel--; } if ( setModeLevel > 5 ) { setModeLevel=0; } if (timeSet > 0 && (setModeTime*2) < (millis() - timeSet) ) { RTC.adjust(DateTime(_year, _month, _day, _hour, _min, _sec)); setMode = false; } delay(200); } }
come avrai notato è decisamente più lungo del suo predecessore, del resto deve fare più cose.
Le linee che restano invariate le puoi leggere negli articoli citati, decsrivo di seguito solo le linee aggiunte o modificate per aggiungere le nuove funzioni alla centralina irrigazione arduino.
Inizia dalla linea 014: in cui includi la classe LiquidCrystal.h che ti permette di gestire il display LCD della centralina irrigazione arduino;
linea 023: aggiungi la definizione di BUTTON ossia il pin a cui è collegata la pulsantiera alla centralina irrigazione arduino, come sai tutti i cinque pulsanti sono collegati al pin A0;
linee 032-036: sono le linee in cui definisci i valori di min e max per ciascun pulsante, prendi ad esempio la 032:
int SELECT[] = {0,20}; // pulsante A
questa linea indica allo sketch che i valori 0 e 20 appartengono all’array SELECT composto da due elementi. Quando verificherai il valore letto sul pin A0 se ricade nel’intervallo 0-20 saprai di aver premuto il pulsante A, come visto nell’articolo precedente e riportato nella figura: in aggiunta al riconoscimento del pulsante A ho assegnato all’array il nome SELECT perchè vorrei utilizzare questo pulsante con funzione di SELECT / INVIO nella scelta e conferma delle funzioni di menu;
linea 038: imposta una variabile di buffer da 10 caratteri che utilizzerai per scrivere sul display data ed ora dell’RTC; linee 039-040: definisci due variabile di tipo unsigned long in cui memorizzerai i tempi in millis() per scandire il tempo che passa ed entrare nella modalità di impostazione dell’ora;
linea 041: definisci una variabile di tipo integer in cui impostare il tempo minimo per cui il bottone SELECT deve essere premuto per entrare in modalità SET; linea 046: inizializza la classe LiquidCrystal con i pin definiti in questo articolo;
linea 056: inizializza l’istanza lcd con il metodo begin() della classe LiquidCrystal;
linea 074: pulisci entrambe le linee del display LCD 16×2; linea 082: ad ogni ciclo di loop() richiama la funzione ctrlButton( analogRead ( A0 ) ) che analizzeremo in seguito ed assegna alla variabile _button il valore restituito da tale funzione;
linea 085: controlla che il pulsante SELECT sia stato premuto, la funzione ctrlButton( analogRead( A0 ) ) restituisce il valore 1 se il pulsante SELECT è stato premuto. La pressione del pulsante imposta il valore della variabile time a millis() che ti servirà alla linea 107;
linee 098-099: aggiungi due linee di print del Serial Monitor per farti scrivere anche il valore ritornato dalla linea 082;
linea 104: sostituisci il precedente blocco di codice, la cui funzione era di attivare le zone dell’impianto corrispondente alla fascia oraria corretta, con il richiamo alla funzione start_impianto() al cui interno ho riportato l’intero blocco di codice.Questa operazione ha il vantaggio di avere una loop() più snella e facile da comprendere anche in futuro per aggiungervi altre funzioni o condizioni di funzionamento;
linea 105: richiama la funzione view_date_time() che visualizza sul display la data e l’ora dell’RTC;
linea 107: definisci la condizione con cui entri nella modalità di impostazione della data e dell’ora. Controlli che il tempo trascorso tra la pressione del pulsante e l’attuale valore di millis() superi il valore impostato come tempo di setModeTime, in tal caso richiami la funzione: setMode( now );
linee 113-135: definisci la funzione start_impianto() al cui interno è presente tutto il blocco di codice precedentemente presente nella funzione loop() e che fa il vero e proprio controllo dell’ora e dei minuti per attivare i singoli settori dell’impianto, se vuoi verificare come funziona puoi leggere l’articolo;
linee 139-149: definisci la funzione ctrlButton( button ) il cui scopo è valutare quale pulsante hai premuto, per farlo usi un gioco di confronti tra il valore button ed i valori di range definiti alle linee 032-036. Come avevi già visto gli ciascun array contiene i valori min e max di confronto, per cui se il valore button è 0,1,2,3,4,…20 ritorna il valore 1 che da questo momento sarà per te SELZIONA / INVIO / CONFERMA / SET in funzione del punto in cui lo valuti. In pratica la tabella seguente riporta i valori dei pulsanti e la loro funzione:
se nessuno dei range impostati corrisponde al valore letto sul pin analogico la funzione restituisce 0 con la linea 147;
linee 153-168: definisci la funzione view_date_time() richiamata nell’ultima linea del loop() la cui descrizione è quella definito nella funzione di loop() descritta nell’articolo “RTC shield DS1307: impostare data e ora” ed il cui scopo è quello di visualizzare sul display la data e l’ora corrente dell’RTC;
linee 172-250: definisci l’ultima funzione di questo script setMode() la cui funzione è di consentirti di impostare la data e l’ora dell’RTC. Questa funzione è stata dettagliatamente descritta nell’articolo “RTC shield DS1307: impostare data e ora” ed adattata per questo sketch, ecco come:
linea 190: assegna il valore di ritorno della funzione ctrlButton() alla variabile _button; linea 192: controlla che il valore di _button sia superiore a 1, questo comporta che stai continuando a premere dei pulsanti, per impostare data e ora, e fino a quando premi i pulsanti non devi salvare il dato nella RTC della centralina irrigazione arduino, per ottenere questo effetto continua a impostare timeSet come il valore di millis() corrente;
linea 244: quando il valore dell’operazione ( millis() – timeSet ) è maggiore del doppio del valore impostato nella variabile setModeTime esegui le linee 245 e 246;
linea 245: salva data ed ora corrente sull’RTC Shield;
linea 246: imposta la variabile booleana setMode a false in modo che lo sketch esca dal ciclo while e iniziato alla linea 189 e dalla funzione setMode();
Buona irrigazione !!!
Prima di inserire un commento, per favore, leggi il regolamento
65 pings
Skip to comment form