Centralina irrigazione arduino imposta orario

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: Centralina irrigazione arduinoPer 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: lettura dei 5 pulsanti da arduino 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:

centralina irrigazione arduino Tabella pulsanti 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

Permanent link to this article: https://www.mauroalfieri.it/elettronica/centralina-irrigazione-arduino-imposta-orario.html

Lascia un commento

Your email address will not be published.

Questo sito usa Akismet per ridurre lo spam. Scopri come i tuoi dati vengono elaborati.