Primo progetto... irrigazione

Ciao nuovamente a tutti!
vorrei rendervi partecipi del mio primo lavoro con Arduino. Ecco gli elementi: Arduino UNO, LCD 16x2 con regolazione contrasto, un led, un pulsante ed un interruttore.
Il funzionamento previsto è che l'interruttore decide se l'irrigazione lavorerà in maniera automatica e programmata (fase che svilupperò non appena avrò anche un RTC...) oppure in modalità manuale. La modalità manuale prevede, l'avvio del ciclo completo di 3 irrigatori oppure l'avvio di ogni singolo irrigatore. La scelta della modalità manuale si basa sul numero di volte che si preme il pulsante: 1 volta parte il ciclo automatico, 2 volte parte solo il primo irrigatore, 3 volte parte il secondo irrigatore,4 volte parte il terzo irrigatore, 5 volte o più il led lampeggia velocemente per segnalare una selezione errata.
Il prossimo passo, oltre al modulo RTC per il timer è la ethernet shield per il controllo da remoto ma... una cosa alla volta!!

Critiche e/o consigli? :slight_smile:

Allego il codice perché è un po' troppo lungo...

irrigazione.txt (10.4 KB)

  1. usa il tasto CTRL+T che ti sistema il codice come indentazione.
    2.Potresti spezzare il codice in più funzioni per renderlo più chiaro.
    Ad esempio sposti le due parti dentro i due if in due funzioni void, la loop diventa microscopica:
...
void loop() {
  StatoInt = analogRead(INTERRUTTORE);
  Serial.println(StatoInt);
  if (StatoInt <1000) {
    IrrigazAuto();    // chiama funzione 
  }
  else {   // StatoInt >= 1000
    IrrigazManuale();  
  }
}  // fine loop

// ******* IrrigazAuto
// * Funzione per ... che fa ....
void IrrigazAuto()
{ digitalWrite(LED, HIGH);
  delay(300);
  digitalWrite(LED, LOW);
  delay(300);
  digitalWrite(LED, HIGH);
  delay(300);
  digitalWrite(LED, LOW);
  delay(300);
  lcd.clear();
  lcd.begin(16, 2);
  lcd.setCursor(2, 0);
  lcd.print("Irrigazione");
  lcd.setCursor(1, 1);
  lcd.print("Giardino AUTO");
//codice per programmazione giornaliera  
}

// ******* IrrigazManuale
// * Funzione per ... che fa ....  con un pò di commenti, tra 1 anno chi si ricorda che fa stò codice ? 
void IrrigazManuale()
{ int reading = digitalRead(BUTTON);
  if (reading != lastButtonState) lastDebounceTime = millis();
  if ((millis() - lastDebounceTime) > debounceDelay) {
  ....eccetera
}

Non sapevo dl ctrl-T ! :astonished:
Grazie!
Appena implemento la programmazione automatica provvedo anche ad ottimizzarlo!

Non ci riesco... =(

ho utilizzato un counter ed un delay per attivare un relè per un tot di secondi ma ho capito che non va bene in quanto il delay blocca proprio arduino che non può ricevere altri comandi... quindi ho utilizzato il millis()

           if(readString.indexOf("IRR1=1") > 0) {// lettura del valore dal web
            starttime=millis();
            while (millis() <= starttime + (MinutiIrrigazione*60*1000)){
              digitalWrite(IRR1, LOW); // attivo relè
              IRRON1 = true;          //stato irrigatore per pagina web
              lcd.setCursor(0, 0);
              lcd.print("Irrigatore 1 MAN");
            }
          }

          if(readString.indexOf("IRR1=0") > 0) {// lettura del valore dal web
            //il led sarà spento
            digitalWrite(IRR1, HIGH); //spengo relè
            break;
            IRRON1 = false;
            lcd.setCursor(0, 0);
            lcd.print("  Irrigazione   ");
            lcd.setCursor(0, 1);
            lcd.print("    Giardino   ");
          }

e m i pare funzioni... ma se voglio annullare il funzionamento di questo relè manualmente come fare? Ho messo un comando break ma il problema è che dopo il break, il relè si disattiva ma poi non mi accetta altri comandi...
sbaglio qualcosa oppure utilizzate un altro metodo?

Grazie!

??? che c'entra break ?
Mica ti sei spiegato. Manualmente cosa vuol dire che hai aggiunto un pulsante?
Se si, devi gestire il pulsante, e cosa deve fare il pulsante? Spegne o deve ignorare i comandi da web?

Allora il tutto viene gestito tramite interfaccia web senza pulsanti fisici...
quello che faccio è semplicemente dire al sistema che se riceve una stringa che termina con IRR1=1 mi attiva il relè dell'irrigatore 1 mentre se riceve la stringa IRR1=0 disattiva il relè, e fin qui tutto funziona!

Il problema mi si presenta quando cerco di temporizzare l'attivazione del relè.
Escludendo l'uso del delay() perchè se dico di attivare il relè e poi metto un delay di 300000 (5 minuti), poi per 5 minuti l'arduino non accetta alcun comando.

Da qui ho provato ad utilizzare millis() nel caso di IRR1=1 ed ho inserito un break nel caso di IRR1=1.
Bene il break funziona e mi disattiva il relè ma poi non riesco a riattivarlo!!
E' normale così o sbaglio qualcosa?

No, la break no c'entra nulla, quando la incontra Arduino semplicemente esce dal ciclo in cui è quell'istruzione.
Tu non metti tutto il codice, quindi non saprei dirti, secondo me esce da un qualche tuo ciclo.

Secondo me devi cambiare la logica. Devi avere una variabile chiamata di statoRele, magari una byte che può assumere 2 valori, K_RELE_ACCESO e K_RELE_SPENTO

const byte K_RELE_ACCESO=1;
const byte K_RELE_SPENTO=1;
byte statoRele=K_RELE_SPENTO;

Quando ricevi IRR1=1 o IRR1=0 cambi solo il valore di questa variabile.
Poi alla fine della loop() potrai mettere un codice che verifica il valore di questa variabile di stato
e nel caso sia a K_RELE_ACCESO allora con la millis() verifichi se è passato il tempo e accendi il rele.

nid69ita:
.... secondo me esce dalla loop().

Nid ... da quando con una break si esce da una funzione ??? :astonished: :astonished: :astonished:

void loop() {}

è una funzione ... al limiti ci esci con una return di troppo ... ma difficilmente con una break :wink:

Guglielmo

gpb01:

nid69ita:
.... secondo me esce dalla loop().

Nid ... da quando con una break si esce da una funzione ??? :astonished: :astonished: :astonished:

void loop() {}

è una funzione ... al limiti ci esci con una return di troppo ... ma difficilmente con una break :wink:
Guglielmo

Mai... :grin: break esce solo da un ciclo. Nella fretta di rispondere... ho scritto una belinata.

Ho provato e riprovato.... :frowning:

  EthernetClient client = server.available();
  if (client) {
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        readString.concat(c); //memorizzo ogni carattere della stringa
        //if HTTP request has ended
        if (c == '\n' && currentLineIsBlank) {
          Serial.print(readString);
          if(readString.indexOf("IRR1=1") > 0) {// lettura del valore dal web
            for (int x = 0 ; x < 200 ; x++){
              digitalWrite(IRR1, LOW); //sengo il led
              Serial.println("Irrigatore 1 Acceso");
              Serial.println(x);
              IRRON1 = true;
            }
            digitalWrite(IRR1, HIGH); //sengo il led
            Serial.println("Irrigatore 1 Spento");
            IRRON1 = false; 
          }
 
          if(readString.indexOf("IRR1=0") > 0) {// lettura del valore dal web
            //il led sarà spento
            digitalWrite(IRR1, HIGH); //sengo il led
            Serial.println("Irrigatore 1 Spento");
            IRRON1 = false;
          }

Allora ho modificato un attimo il codice....
il problema è che quando passo via web la stringa IRR1=1 inizia un if al cui interno c'è un for (specie di timer) ma finchè il for non è completato anche se passo via web la stringa IRR1=0, questa non viene accettata fino alla fine del for...

cosa devo usare?

non puoi usare il ciclo for, il loop resta bloccato nella sua esecuzione finchè non è finito...
Se usi il millis risolvi il problema: leggi il comando, se devi accendere la valvola memorizzi il millis, poi la spegni se arriva il comando OFF oppure se trascorre il tempo X