Go Down

Topic: consigli sketch centralina irrigazione (Read 1 time) previous topic - next topic

luca90

ciao a tutti, ho da poco acquistato un'arduino mega per cercare di realizzare una centralina per la gestione dell'impianto di irrigazione del giardino.non avendo tante conoscenze di programmazione in c, ho cominciato a realizzare lo scketch e sono arrivato al risultato dello scketch allegato. lo scketch relativo al ciclo automatico funziona ma avrei bisogno di un consiglio sulla partenza del ciclo manuale in quanto, ho pensato di utilizzare lo stesso codice del programma automatico però settando l'ora e i minuti di inzio dando lo start dal display e quindi settando a 1 la variabile "start_man". il problema è che, ovviamente, i minuti continuano ad incrementare e il programma non va avanti. secondo voi devo rivedere la struttura del programma?
in allegato trovate lo scketch.
intanto vi ringrazio. ciao

lesto

scusa ma il programma è bello lungo da scorrere tutto.. qualche info su dove trovare il pezzo incriminato?
in oltre non capisco il problema... potresti spiegare meglio, indicando anche i passaggi dell'utente nel menu
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

luca90

ciao, grazie per la risposta. ho messo qua il codice (nello scketch allegato mi sono accorto che l'avevo cancellato), il mio problema è che le variabili ora_start_irri_man e minuti_start_irri_man continuano ad incrementare e se vedi la struttura della funzione "Irrigazione manuale" i minuti di fermata della prima zona li calcola sommando il tempo di irrigazione e i minuti di start irrigazione quindi il programma riparte sempre dall'inizio.
Code: [Select]

if(start_man==HIGH) {
  ora_start_irri_man=now.hour();
  minuti_start_irri_man=now.minute();
  irrigazione_manuale();
}
 
if(start_man==LOW)  {
      digitalWrite(rel1,LOW);
      digitalWrite(rel2,LOW);
      digitalWrite(rel3,LOW);
      digitalWrite(rel4,LOW);
      stato_ciclo=0;
}
void irrigazione_manuale()  {
 
  DateTime now = RTC.now();

 
  if(now.hour()==ora_start_irri_man && now.minute()==minuti_start_irri_man)  {
   
      if(tempo_irri_man1 !=0)  {
      digitalWrite(ev_zona1,HIGH);
      stato_ciclo=1;
      stato_sosta=1;
     
    }
    else  {
      digitalWrite(ev_zona1,LOW);
      stato_ciclo=10;
    }
  }
      if((stato_ciclo==1 || stato_ciclo==10) && now.minute()==minuti_stop_irri_man1)  {
        digitalWrite(ev_zona1,LOW);
        delay(1000);
        ora_irri_man2=now.hour();
        minuti_irri_man2=now.minute();
        stato_ciclo=0;
        stato_sosta=0;
    }
   
      if(now.hour()==ora_irri_man2 && now.minute()==minuti_irri_man2)  {
        if(tempo_irri_man2 !=0)  {
      digitalWrite(ev_zona2,HIGH);
      stato_ciclo=2;
      stato_sosta=2;
    }
    else  {
      digitalWrite(ev_zona2,LOW);
      stato_ciclo=11;
    }
    }

      if((stato_ciclo==2 || stato_ciclo==11) && now.minute()==minuti_stop_irri_man2)  {
        digitalWrite(ev_zona2,LOW);
        delay(1000);
        ora_irri_man3=now.hour();
        minuti_irri_man3=now.minute();
        stato_ciclo=0;
        stato_sosta=0;
      }
      if(now.hour()==ora_irri_man3 && now.minute()==minuti_irri_man3)  {
        if(tempo_irri_man3 !=0)  {
      digitalWrite(ev_zona3,HIGH);
      stato_ciclo=3;
      stato_fermata=0;
    }
    else  {
      digitalWrite(ev_zona3,LOW);
      stato_ciclo=12;
    }
    }
      if((stato_ciclo==3 || stato_ciclo==12)&& now.minute()==minuti_stop_irri_man3)  {
        digitalWrite(ev_zona3,LOW);
        delay(1000);
        ora_irri_man4=now.hour();
        minuti_irri_man4=now.minute();
        stato_ciclo=0;
        stato_sosta=0;
      }
      if(now.hour()==ora_irri_man4 && now.minute()==minuti_irri_man4)  {
      if(tempo_irri_man4 !=0)  {
      digitalWrite(ev_zona4,HIGH);
      stato_ciclo=4;
    }
    else  {
      digitalWrite(ev_zona4,LOW);
      stato_ciclo=13;
    }
      }
      if((stato_ciclo==4 || stato_ciclo==13) && now.minute()==minuti_stop_irri_man4)  {
        digitalWrite(ev_zona4,LOW);
        delay(1000);
        ora_irri_man5=now.hour();
        minuti_irri_man5=now.minute();
        stato_ciclo=0;
        stato_sosta=0;
      }
       

   
switch(stato_sosta)  {
case 1:

  if(stato_canc_grande==1 || stato_canc_piccolo==1)  {
    stato_fermata=1;
    minuti_fermata=now.minute();
    secondi_fermata=now.second();
  }
  if(stato_fermata==1)  {
   
    digitalWrite(ev_zona1,LOW);
  }
  if(stato_ciclo==1 && now.minute() >= minuti_fermata + 1 && now.second()==secondi_fermata)  {
    digitalWrite(ev_zona1,HIGH);
    minuti_fermata=0;
    stato_fermata=0;
  }
  break;
  case 2:
  if(stato_canc_grande==1 || stato_canc_piccolo==1)  {
    stato_fermata=1;
    minuti_fermata=now.minute();
    secondi_fermata=now.second();
  }
  if(stato_fermata==1)  {
   
    digitalWrite(ev_zona2,LOW);
  }
  if(stato_ciclo==2 && now.minute() >= minuti_fermata + 1 && now.second()==secondi_fermata)  {
    digitalWrite(ev_zona2,HIGH);
    minuti_fermata=0;
    stato_fermata=0;
  }
  break;
}
 
}

ciao e grazie!!

PaoloP

Ho letto velocissimamente il codice ma secondo me sbagli approccio.
Dovresti creare una funzione irrigazione() e il controllo dell'orario dovrebbe essere esterno a questa.
Se è attivata l'irrigazione automatica ad un certo orario chiami la funzione magari passandogli la zona, es. irrigazione(zona).
Se attivi l'irrigazione manuale non controlli l'orario e chiami direttamente la funzione per irrigare.
Tu invece azioni l'irrigazione manuale come irrigazione automatica con tempo di avvio l'ora corrente. Boh! Mi lascia un po' perplesso.  :smiley-roll-blue:
Code fast. Code easy. Codebender --> http://codebender.cc/?referrer=PaoloP

lesto

anche io approvo, in caso quella manuale metti una manciata di secondi dopo
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

luca90

ma quindi, secondo voi dovrei modificare anche la funzione dell'irrigazione automatica? intanto stasera cerco di provare a sistemare la funziobne manuale seguendo i vostri consigli e poi posto il risultato.però non ho ben capito come dovrei gestire i tempi dell'irrigazione manuale se non ho un tempo di partenza. ciao

PaoloP

Allora non ho capito io cosa intendi per irrigazione manuale.
Schiacci il pulsante e parte l'irrigazione? Ripremi il pulsante e si spegne?
Code fast. Code easy. Codebender --> http://codebender.cc/?referrer=PaoloP

luca90

scusate se sono stato poco chiaro, adesso cerco di spiegarmi meglio. nello scketch ho fatto 2 funzioni: 1 per l' irrigazione automatica e 1 per l'irrigazione manuale.
per l'irrigazione automatica io imposto tramite display l'ora e i minuti di partenza, i minuti di irrigazione di ogni singola zona, i giorni di irrigazione (se tutti i giorni o giorni pari o giorni dispari) e il giorno di non irrigazione(giorno in cui nel periodo estivo taglio l'erba) dopo aver impostato tutto tramite menù setto a HIGH la variabile (start_auto) cioè ON che dopo il controllo dei giorni di irrigazione impostati fa partire la funzione irrigazione(). nella funzione irrigazione quando l'rtc è uguale all'ora di start irrigazione fa partire la prima zona da irrigare( se il tempo della zona 1 è 0 allora parte direttamente dalla 2) e quando si verifica la condizione minuti_start_irri+minuti_irri1 spegne l'uscita della zona, aspetta 1 secondo(è ancora con il delay ma devo mettere il millis() e poi mi setta l'ora e i minuti di start della zona 2 perchè ho messo 2 variabili ora_start_irri2 e minuti_start_irri2 uguale rispettivamente a now.hour() e now.minute() e cosi via le zone successive. secondo voi la logica va bene? diciamo che di questa funzione l'unica cosa che mi piacerebbe aggiungere è la possibilità, se l'irrigazione è in corso, di stoppare il ciclo di irrigazione ponendo tramite display la variabile start_auto a LOW. per fare questo avevo provato a cambiare gli uguali negli if dell'orario con >= ma non funzionava.
passando alla funzione irrigazione_manuale() io ho usato la stessa funzione di quella automatica perchè a me serve che faccia la stessa cosa solo senza impostare l'ora e i minuti di inizio cioè tramite menù imposto i vari tempi di irrigazione e il ciclo parte dopo aver posto a HIGH la variabile start_man. quando dico di aver posto la variabile start(auto o man) a HIGH o LOW è perchè nel programma ho usato la libreria dei menù menWiz e quindi sulla schermata mi appare la scritta "start Irrigazione" con 2 possibilità o on(cioè mette a HIGH la variabile) o OFF(cioè mette a LOW la variabile). spero di essere stato più chiaro e mi scuso per il linguaggio poco tecnico del post.ciao e grazie a tutti!

luca90

#8
Apr 14, 2013, 09:44 pm Last Edit: Apr 14, 2013, 09:47 pm by luca90 Reason: 1
ciao, ho provato a migliorare un po il codice che gestisce l'irrigazione automatica. adesso ho implementato il sensore pioggia con la variabile start_irrigazione (uguale a 2 se è disattivato il sensore dal menù del display, a 1 se è attivato dal menù e il contatto è chiuso e a 0 se il sensore è aperto), poi sulla gestione degli orari ho usato i >= e <= per gestire l'intervallo tra i 2 tempi, così se metto OFF da menù, poi riportando in ON continua il ciclo(come uno stato di pausa). vorrei avere 1 o 2 secondi di riposo tra l'irrigazione da una zona all' altra, avevo messo un delay di 1 secondo ma, non so perchè, mi rallentava l'uso del menù.ho provato con il millis() tra una zona e l'altra con il codice così composto: dopo il digitalWrite (ev_zona1,LOW) avevo messo
ritardo=millis()+2000;
if(ritardo<millis() && ritardo>0)  {
ora_irri2=ora;
minuti_irri2=now.minute();  }
ma non funziona, l'idea era quelladi ritardare la lettura dell'ora di 2 secondi e quindi la seconda zona dovrebbe essere partita 2 secondi dopo ma purtroppo non è così. avrei bisogno di un consiglio su questo passaggio. ciao e grazie
Code: [Select]

if(start_irrigazione==1 || start_irrigazione==2)  {
   
  if((ora>=ora_start_irri && now.minute()>=minuti_start_irri) && (ora<=ora_stop_irri1 && now.minute()<=minuti_stop_irri1))
   {
     if(tempo_irri1 !=0)  {
     digitalWrite(ev_zona1,HIGH);
     stato_ciclo=1;
     stato_sosta=1;
   }
   else  {
     digitalWrite(ev_zona1,LOW);
     stato_ciclo=10;
   }
   }
     if((stato_ciclo==1 || stato_ciclo==10) && now.minute()==minuti_stop_irri1)    {
       digitalWrite(ev_zona1,LOW);
       stato_ciclo=0;
       stato_sosta=0;
       ora_irri2=ora;
       minuti_irri2=now.minute();
       
   }
   
     if((ora>=ora_irri2 && now.minute()>=minuti_irri2) && (ora<=ora_stop_irri2 && now.minute()<=minuti_stop_irri2))  {
       if(tempo_irri2 !=0)  {
     digitalWrite(ev_zona2,HIGH);
     stato_ciclo=2;
     stato_sosta=2;
   }
   else  {
     digitalWrite(ev_zona2,LOW);
     stato_ciclo=11;
   }
   }

     if((stato_ciclo==2 || stato_ciclo==11) && now.minute()==minuti_stop_irri2)  {
       digitalWrite(ev_zona2,LOW);
       ora_irri3=ora;
       minuti_irri3=now.minute();
       stato_ciclo=0;
       stato_sosta=0;
     }
     if((ora>=ora_irri3 && now.minute()>=minuti_irri3) && (ora<=ora_stop_irri3 && now.minute()<=minuti_stop_irri3))  {
       if(tempo_irri3 !=0)  {
     digitalWrite(ev_zona3,HIGH);
     stato_ciclo=3;
     stato_fermata=0;
   }
   else  {
     digitalWrite(ev_zona3,LOW);
     stato_ciclo=12;
   }
   }
     if((stato_ciclo==3 || stato_ciclo==12)&& now.minute()==minuti_stop_irri3)  {
       digitalWrite(ev_zona3,LOW);
       
       ora_irri4=now.hour();
       minuti_irri4=now.minute();
       stato_ciclo=0;
       stato_sosta=0;
     }
     if(now.hour()==ora_irri4 && now.minute()==minuti_irri4)  {
     if(tempo_irri4 !=0)  {
     digitalWrite(ev_zona4,HIGH);
     stato_ciclo=4;
     stato_sosta=0;
     stato_fermata=0;
   }
   else  {
     digitalWrite(ev_zona4,LOW);
     stato_ciclo=13;
   }
     }
     if((stato_ciclo==4 || stato_ciclo==13) && now.minute()==minuti_stop_irri4)  {
       digitalWrite(ev_zona4,LOW);
       
       ora_irri5=now.hour();
       minuti_irri5=now.minute();
       stato_ciclo=0;
       stato_sosta=0;
     }
       

   
switch(stato_sosta)  {
case 1:

 if(stato_canc_grande==1 || stato_canc_piccolo==1)  {
   stato_fermata=1;
   minuti_fermata=now.minute();
   secondi_fermata=now.second();
 }
 if(stato_fermata==1)  {
   
   digitalWrite(ev_zona1,LOW);
 }
 if(stato_ciclo==1 && now.minute() >= minuti_fermata + 2 && now.second()==secondi_fermata)  {
   digitalWrite(ev_zona1,HIGH);
   minuti_fermata=0;
   stato_fermata=0;
 }
 break;
 case 2:
 if(stato_canc_grande==1 || stato_canc_piccolo==1)  {
   stato_fermata=1;
   minuti_fermata=now.minute();
   secondi_fermata=now.second();
 }
 if(stato_fermata==1)  {
   
   digitalWrite(ev_zona2,LOW);
 }
 if(stato_ciclo==2 && now.minute() >= minuti_fermata + 2 && now.second()==secondi_fermata)  {
   digitalWrite(ev_zona2,HIGH);
   minuti_fermata=0;
   stato_fermata=0;
 }
 break;
}
 }
if(start_irrigazione==0)  {
  digitalWrite(ev_zona1,LOW);
  digitalWrite(ev_zona2,LOW);
  digitalWrite(ev_zona3,LOW);
  digitalWrite(ev_zona3,LOW);
 stato_irrigazione=6;
}
}



luca90

ciao, avrei bisogno di un'aiuto riguardante il mio progetto della centralina per l'irrigazione del giardino.
ho modificato leggermente lo scketch in modo tale da poter mettere in pausa e riprendere l'irrigazione. quindi nella gestione degli orari ho usato il >= e non ==. questo è la parte di codice relativa ad ogni zona:
Code: [Select]

if((ora>=ora_start_irri && now.minute()>=minuti_start_irri) && (ora<=ora_stop_irri1 && now.minute()<=minuti_stop_irri1))
    {
      if(tempo_irri1 !=0)  {
      digitalWrite(ev_zona1,HIGH);
      stato_ciclo=1;
      stato_sosta=1;
    }
    else  {
      digitalWrite(ev_zona1,LOW);
      stato_ciclo=10;
    }
    }


il problema si presenta quando un'irrigazione è a cavallo tra 2 ore diverse(ad esempio l'ora di start irrigazione è 21:55 e il tempo di irrigazione della zona è 10 minuti) quindi l'ora di stop irrigazione di quella zona sarà 22:05. io i minuti li ho gestiti così:
Code: [Select]

minuti_stop_irri1 = minuti_start_irri + tempo_irri1;
   minuti_stop_irri2 = minuti_irri2 + tempo_irri2;
   minuti_stop_irri3 = minuti_irri3 + tempo_irri3;
   minuti_stop_irri4 = minuti_irri4 + tempo_irri4;
   ora_stop_irri1=ora_start_irri;
   ora_stop_irri2=ora_irri2;
   ora_stop_irri3=ora_irri3;
   ora_stop_irri4=ora_irri4;
     
   if (minuti_stop_irri1>=60)  {
      ora_stop_irri1=ora_start_irri+1;
      minuti_stop_irri1=minuti_stop_irri1-60; }
   if (minuti_stop_irri2>=60)  {
      ora_stop_irri2=ora_irri2+1;
      minuti_stop_irri2=minuti_stop_irri2-60; }
   if (minuti_stop_irri3>=60)  {
      ora_stop_irri3=ora_irri3+1;
      minuti_stop_irri3=minuti_stop_irri3-60; }
   if (minuti_fermata>=60)  {
      minuti_fermata=minuti_fermata-60; }

il problema si presenta perchè la condizione dei minuti non si avvera. violevo sapere se sbaglio io nella gestione o se c'è qualche modo per aggirare il problema. le variabili sono di tipo intero e sono settate tramite display. ciao e grazie

leo72

La gestione dell'avvio ed arresto di operazioni in base ad un orario non è semplice come sembra.

Una prima soluzione è quella di usare una variabile di stato (per evitare di compiere il controllo più di una volta) e fare un doppio check su ore e minuti.
Un'altra alternativa è quella di fare il controllo usando i timestamp. Se usi o hai usato Linux sai di cosa parlo. Altrimenti detto stringatamente il timestamp come il numero di secondi a partire da un istante prefissato. 

In questo modo tutti gli orari diventano semplici variabili unsigned long che contengono il tempo espresso in secondi. Fissi l'inizio ad una data epoca, mettiamo il 1° gennaio 2013 per comodità, dopodiché conti i secondi da lì. Fare un allarme con inizio/fine è facile perché non devi fare altro che calcolarti il timestamp dell'orario di inizio e poi sommare la durata dell'evento e controllare poi questo dato.

Per calcolare il timestamp esistono diverse funzioni. Se guardi la mia libreria swRTC nel suo codice ci sono le funzioni per estrarre il timestamp da una certa data oppure per calcolarlo.

luca90

ciao, io nel circuito ho un ds1307 come rtc mentre ho visto che la tua libreria è un rtc software. ti spiego meglio lo scketch: io imposto tramite display l'ora di start irrigazione e i minuti di start irrigazione(sono due variabili di tipo int), poi setto i minuti di irrigazione di ogni zona ad esempio 5 minuti. per calcolarmi l'ora di fine irrigazione faccio i calcoli che vedi nel mio post precedente. io uso la libreria RTCLib e ho visto la funzione now.unixtime che dovrebbe essere come i timestamp di cui mi parlavi. adesso sto provando a fare delle prove. pensavo di settare il now.unixtime all'ora di start irrigazione e poi convertire i minuti di irrigazione della zona in secondi e calcolarmi così la fine dell'irrigazione. può funzionare? potresti spiegarmi meglio la soluzione con la variabile di stato? grazie e ciao

leo72

Sì l'Unixtime è un timestamp come epoca Unix, ossia 1970.0.
Va bene anche quella.

luca90

ciao, ho provato a ristrutturare il codice in questo modo. ho usato delle variabili unsigned long chiamate secondi_start_irri1,secondi_start_irri2, ecc.
sembra funzionare ma volevo sapere se è corretta così la struttura del codice.ciao
le variabili tempo_irri sono moltiplicate x60 perchè sono espresse in minuti.
Code: [Select]

   if(ora==ora_start_irri && now.minute()==minuti_start_irri && now.second()==0)
    {
      secondi_start_irri1=now.unixtime();
    }
    if(now.unixtime()<secondi_start_irri1 + (tempo_irri1 *60))  {
      if(tempo_irri1 !=0)  {
        digitalWrite(ev_zona1,HIGH);
      stato_ciclo=1;
      stato_sosta=1;
    }
      }
    else  {
     digitalWrite(ev_zona1,LOW);
     stato_ciclo=10;
    }
   
      if(now.unixtime()==secondi_start_irri1 + (tempo_irri1 *60))      {
        digitalWrite(ev_zona1,LOW);
        stato_ciclo=0;
        stato_sosta=0;
        secondi_start_irri2=now.unixtime();
    }
   
      if((now.unixtime()>secondi_start_irri1 + (tempo_irri1 *60)) && (now.unixtime()<secondi_start_irri2 + (tempo_irri2 *60)))  {
        if(tempo_irri2 !=0)  {
      digitalWrite(ev_zona2,HIGH);
      stato_ciclo=2;
      stato_sosta=2;
    }
    else  {
      digitalWrite(ev_zona2,LOW);
      stato_ciclo=11;
    }
    }
        if (now.unixtime()==secondi_start_irri2 + (tempo_irri2 *60))  {
        digitalWrite(ev_zona2,LOW);
        secondi_start_irri3=now.unixtime();
        stato_ciclo=0;
        stato_sosta=0;
      }
      if ((now.unixtime()>secondi_start_irri2 + (tempo_irri2 *60)) && (now.unixtime()<secondi_start_irri3 + (tempo_irri3 *60)))  {
        if(tempo_irri3 !=0)  {
      digitalWrite(ev_zona3,HIGH);
      stato_ciclo=3;
      stato_fermata=0;
    }
    else  {
      digitalWrite(ev_zona3,LOW);
      stato_ciclo=12;
    }
    }
      if(now.unixtime()==secondi_start_irri3 + (tempo_irri3 *60))  {
        digitalWrite(ev_zona3,LOW);
        stato_ciclo=0;
        stato_sosta=0;
        secondi_start_irri4=now.unixtime();
      }

leo72

Il tuo mi pare un uso promiscuo, fai ancora i controlli su ore:minuti:secondi. Trasporta tutto internamente in timestamp e lascia solo la visualizzazione classica sul display per l'utente. Al programma non gline importa se sono le 11:34:56 del giorno x oppure 134567546 secondi dall'epoca scelta  ;)

Go Up