gestione millis nel ciclo if/else (in sostituzione del delay)

Buonasera,
mi chiamo Emanuele e nella programmazione sono alle prime armi.
Mi servirebbe un po’ di aiuto…sono 3 giorni che cerco una soluzione consultando forum,manuali e youtube ma non ne vengo a capo :frowning:

Ho scritto uno sketch (Arduino Uno) che dopo mille intoppi finalmente funziona correttamente, il problema è che faccio un massiccio impiego del delay per entrambe le condizioni “if” e questo mi preclude la possibilità di eseguire altre istruzioni necessarie alla realizzazione del progetto.
L’esecuzione parte da in interruttore che se aperto o chiuso avvia una condizione o l’altra e che a loro volta pilotano un servo e un relè con l’uno o l’altro “comportamento”.
La cosa assolutamente imperativa è che una volta completato il ciclo relativo non deve assolutamente essere ripetuto fino al prossimo cambio di stato dell’interruttore.

byte mela;
const int Aancora =  13;
#include <Servo.h>
Servo portelli;
int chiuso = 150;
int aperto = 50;
const int relepompa = 4;

void setup () { 
  if ( digitalRead (2)==HIGH)  mela=1; 
  if ( digitalRead (2)==LOW)  mela=0; 
  pinMode(Aancora, OUTPUT);
  portelli.attach(6);
  portelli.write(chiuso);
  pinMode(relepompa, OUTPUT);
  digitalWrite(relepompa, LOW);
  Serial.begin(9600);
}
void loop(){ 

  
  if ( digitalRead (2)==HIGH && mela==1) {
    mela=0, Serial.println(" stato di immersione");
    digitalWrite(Aancora, LOW);
    digitalWrite(relepompa, LOW);
    portelli.write(aperto);
    delay(10000);
    portelli.write(chiuso);
    }
  
  if ( digitalRead (2)== LOW && mela==0) {
    mela=1, Serial.println(" stato di sollevamento");
    portelli.write(chiuso);  
    digitalWrite(relepompa, HIGH);
    delay(8000);
    digitalWrite(relepompa, LOW);
    digitalWrite(Aancora, HIGH);
    delay(10000);
    digitalWrite(relepompa, HIGH);
    delay(2000);
    digitalWrite(relepompa, LOW);
    }
  delay (20);
}

_2stadio_U47.ino (1019 Bytes)

Buonasera, essendo il tuo primo post, nel rispetto del regolamento della sezione Italiana del forum (… punto 13, primo capoverso), ti chiedo cortesemente di presentarti IN QUESTO THREAD ([u]spiegando bene quali conoscenze hai di elettronica e di programmazione[/u] ... possibilmente [u]evitando[/u] di scrivere solo una riga di saluto) e di leggere con MOLTA attenzione il su citato REGOLAMENTO ... Grazie.

Guglielmo

P.S.: Qui una serie di link utili, [u]NON[/u] necessariamente inerenti alla tua domanda: - serie di schede by xxxPighi per i collegamenti elettronici vari: ABC - Arduino Basic Connections - pinout delle varie schede by xxxPighi: Pinout - link [u]generali[/u] utili: Link Utili

Ok ho fatto la presentazione dove indicato e grazie per i link sempre utili ed interessanti.

Come dicevo sono giorni che ci sbatto la testa e non sono capace di trovare una soluzione, il fatto che il codice venga eseguito una sola volta con le mie attuali limitate conoscenze non mi permette di usare il millis…

Emanueleb: ... con le mie attuali limitate conoscenze non mi permette di usare il millis...

Guarda che non è nulla di trascendentale (è solo un contatore che avanza sempre al passare del tempo) e richiede solo di applicarsi un momento a studiare come si usa la funzione millis(), prima QUI, poi QUI e QUI e QUI e [u]tutti gli articoli[/u] che sono in QUESTA pagina ... ... vedrai che dopo molte cose ti saranno più chiare.

Guglielmo

Ti dico come faccio io di solito: Prima mi scrivo (con l'esperienza puoi anche non scrivere più) la cose da fare, nella giusta sequenza Poi lo rileggo, "giocando a farle" nella mia testa, un po' come quando ero all'asilo, non sto scherzando, tento sempre di stare a basso livello Quando il "gioco" gira bene comincio a buttare giù righe di codice Fino a che non gira bene, non so per esempio se mi accorgo che non ho spento una pompa, correggo e ricomincio a "giocare" Prova a scrivermi cosa devi fare

a parte il discorso sui millis() che diventa semplice dopo averci studiato giusto un pochino. Nel tuo sketch mancano alcuni commenti che aiuterebbero a capire cosa vuoi fare... Ad esempio da quello che ho capito si tratta si un sottomarino o simili per acquario a questo punto cosa significa la variabile "mela"? nel setup se il contatto 2 (che non si sa cosa sia) diventa alto cambi lo stato di mela e poi nel loop ricontrolli ancora il contatto 2 e anche mela ( ma mela è intimamente legata al contatto 2, cioè non ci sarà mai la situazione contatto2 =low e mela=1 per cui...) e Aancora che è? in questo caso il led

È solo una battuta: E se fosse la macchina della strega? La macchina per pompare il veleno nella mela per Biancaneve?

Ok ho aggiunto la descrizione voce per voce…

byte mela;                                        // mela = nome di fantasia
const int Aancora =  13;                          //abilita/disabilita l'uso dell'ancora su altro controller esterno, 
#include <Servo.h>                                   //almeno fino a quando non riesco ad integrare iil millis per 
Servo portelli;                                      //eliminare l'altro controller ed integrare qui tutto il codice...
int chiuso = 150;
int aperto = 50;
const int relepompa = 4;

void setup () { 
  if ( digitalRead (2)==HIGH)  mela=1; 
  if ( digitalRead (2)==LOW)  mela=0; 
  pinMode(Aancora, OUTPUT);
  portelli.attach(6);
  portelli.write(chiuso);  
  pinMode(relepompa, OUTPUT);
  digitalWrite(relepompa, LOW);
  Serial.begin(9600);
}
void loop(){ 
  if ( digitalRead (2)==HIGH && mela==1) {
    mela=0, Serial.println(" stato di immersione");  //verfica se il pulsante è in on:
    digitalWrite(Aancora, LOW);                      //ancora disabilitata
    digitalWrite(relepompa, LOW);                    //pompa spenta
    portelli.write(aperto);                          //portelli aperti 
    delay(10000);                                    //atesa allagamento comparti
    portelli.write(chiuso);                          //portelli chiusi
    }
  if ( digitalRead (2)== LOW && mela==0) {
    mela=1, Serial.println(" stato di sollevamento"); //verfica se il pulsante è in off:
    portelli.write(chiuso);                           //portelli chiusi
    digitalWrite(relepompa, HIGH);                    //pompa attiva 
    delay(8000);                                      //tempo necessario allo svuotamento dei comparti
    digitalWrite(relepompa, LOW);                     //pompa spenta 
    digitalWrite(Aancora, HIGH);                      //ancora abilitata
    delay(10000);                                     //pausa per convogliare l'ultimo deflusso in zona pompa 
    digitalWrite(relepompa, HIGH);                    //attivazione pompa
    delay(2000);                                      //tempo necessario per eliminare l'ultimo deflusso raccolto
    digitalWrite(relepompa, LOW);                     //pompa spenta
    }
  delay (20);
}

>Emanueleb: .. perdona la franchezza :confused: , ma ... da tuo codice si capisce che tu di Arduino NON sai quasi nulla e che scrivi istruzioni in un oridine che difficilmente potrà portare a qualche cosa che funzioni.

Ora, noi qui aiutiamo a correggere, ma le BASI uno se le deve fare studiando ... ... se uno mi inizia una setup() con una digitalRead() senza neanche aver definito se il pin che usa è di INPUT o di OUTPUT significa appunto che di Arduino NON ha studiato NULLA.

Quindi ... prima di andare avanti ... tocca che almeno ti studi QUESTO prosegui con con QUESTO (che sono [u]veramente le BASI[/u]) e acquisti qualche buon libro (es. QUESTO) ... dopo di che ti riavvicini al tuo programma sapendo cosa stai facendo. :)

Guglielmo

P.S.: ... youtube è pieno di tutorial sbagliati (almeno il 90%) quindi te lo sconsiglio come base di partenza ... prima studia la teoria, poi puoi guardare qualche tutorial riconoscendo chi racconta frescacce da chi dice cose serie.

Non è mica quello che ti avevo chiesto Comunque taca banda credo di aver capito Schiaccio bottone e si apre un portello Mollo il bottone e si chiude il portello e una serie di accendi spegni

Adesso, per cortesia, scrivimelo bene

Così va bene? (la parte della mela non è farina del mio sacco…)

byte mela;                                        // mela = nome di fantasia
const int Aancora =  13;                          //abilita/disabilita l'uso dell'ancora su altro controller esterno, 
#include <Servo.h>                                   //almeno fino a quando non riesco ad integrare iil millis per eliminare
Servo portelli;                                      //l'altro controller ed integrare qui tutto il codice...
int chiuso = 150;
int aperto = 50;
const int relepompa = 4;

void setup () { 
  pinMode(2, INPUT);
  if ( digitalRead (2)==HIGH)  mela=1; 
  if ( digitalRead (2)==LOW)  mela=0; 
  pinMode(Aancora, OUTPUT);
  portelli.attach(6);
  portelli.write(chiuso);  
  pinMode(relepompa, OUTPUT);
  digitalWrite(relepompa, LOW);
  Serial.begin(9600);
}
void loop(){ 
  if ( digitalRead (2)==HIGH && mela==1) {
    mela=0, Serial.println(" stato di immersione");  //verfica se il pulsante è in on:
    digitalWrite(Aancora, LOW);                      //ancora disabilitata
    digitalWrite(relepompa, LOW);                    //pompa spenta
    portelli.write(aperto);                          //portelli aperti 
    delay(10000);                                    //atesa allagamento comparti
    portelli.write(chiuso);                          //portelli chiusi
    }
  if ( digitalRead (2)== LOW && mela==0) {
    mela=1, Serial.println(" stato di sollevamento"); //verfica se il pulsante è in off:
    portelli.write(chiuso);                           //portelli chiusi
    digitalWrite(relepompa, HIGH);                    //pompa attiva 
    delay(8000);                                      //tempo necessario allo svuotamento dei comparti
    digitalWrite(relepompa, LOW);                     //pompa spenta 
    digitalWrite(Aancora, HIGH);                      //ancora abilitata
    delay(10000);                                     //pausa per convogliare l'ultimo deflusso in zona pompa 
    digitalWrite(relepompa, HIGH);                    //attivazione pompa
    delay(2000);                                      //tempo necessario per eliminare l'ultimo deflusso raccolto
    digitalWrite(relepompa, LOW);                     //pompa spenta
    }
  delay (20);
}

Emanueleb: il fatto che il codice venga eseguito una sola volta con le mie attuali limitate conoscenze non mi permette di usare il millis...

L'uso di millis è tutto qui.

Ma l'esecuzione va modificata da sequenziale (faccio tutti i singoli passi uno dopo l'altro) a ciclica (verifico se è il momento di fare qualcosa altrimenti proseguo senza mai fermarmi), come descritto qui e qui...

...e di cui si sta discutendo qui (se riesci a trasformare il tuo codice sequenziale in "situazioni" sei a cavallo).

byte mela;                      // mela = nome di fantasia

Ecco, questo è un esempio di commento che non aggiunge alcuna informazione utile alla comprensione. Quello che serve sapere è cos'è e cosa fa 'mela', ad esempio:

byte mela;  // variabile di stato per rilevare fronti
            // di commutazione del pulsante

E infatti dopo nel programma parli correttamente di 'stato' (immersione/sollevamento).

Molto corretto invece commentare le varie digitalWrite, infatti leggere solo HIGH o LOW non da immediatamente idea di quale operazione viene svolta (accenderà? spegnerà?), il commento lo specifica bene.

Volendo è possibile ottenere la stessa chiarezza anche senza l'uso di commenti creando apposite "etichette" all'inizio del programma:

#define  POMPA_ACCESA  HIGH
#define  POMPA_SPENTA  LOW

digitalWrite(relepompa, POMPA_ACCESA);

Grazie, ottimo consiglio! Adesso mi applico e vediamo se riesco a trasformarlo in ciclico...(dopo essermi ben documentato con tutti i link che ho ricevuto :) )

Ho appena finito di testarlo e funziona benissimo!
Grazie a tutti per le dritte e i link! :slight_smile: :slight_smile: :slight_smile: :slight_smile: :slight_smile: :slight_smile: :slight_smile: :slight_smile: :slight_smile: :slight_smile: :slight_smile:

#include <Servo.h>
Servo portelli;
int chiuso = 150;
int aperto = 50;

const int buttonPin = 2;    
const int ledPin =  13;      

unsigned long time;
unsigned long svuotamento; 
unsigned long latenzareflusso1;
unsigned long latenzareflusso2;
unsigned long allagamentocomparti;

int buttonState = 0;     


void setup() {
  portelli.attach(6);
  portelli.write(chiuso);
  pinMode(ledPin, OUTPUT);
  pinMode(buttonPin, INPUT);
  time=millis();
  svuotamento=millis();
  latenzareflusso1=millis();
  latenzareflusso2=millis();
  Serial.begin(9600);
  }

void loop() {
  time=millis();
  buttonState = digitalRead(buttonPin);


  if (( digitalRead (2)== LOW) && (time > svuotamento+500)
     && (time < svuotamento+8500)) {
     portelli.write(chiuso);
     digitalWrite(ledPin, HIGH);
     Serial.println(" stato di sollevamento");
     allagamentocomparti=millis();
     }
  if (( digitalRead (2)== LOW) &&(time > svuotamento+8500)){
     digitalWrite(ledPin, LOW);
     }  
  if (( digitalRead (2)== LOW) && (time > latenzareflusso1+18500) 
     && (time < latenzareflusso1+20500)) {
     digitalWrite(ledPin, HIGH);
     allagamentocomparti=millis();
     Serial.println(" stato di sollevamento2");
     }
  if (( digitalRead (2)== LOW) && (time > latenzareflusso1+20500)){
     digitalWrite(ledPin, LOW);
     } 
  if (( digitalRead (2)== LOW) && (time > latenzareflusso2+48500) 
     && (time < latenzareflusso2+50500)) {
     digitalWrite(ledPin, HIGH);
     allagamentocomparti=millis();
     Serial.println(" stato di sollevamento3");
     }
  if (( digitalRead (2)== LOW) && (time > latenzareflusso2+50500)){
     digitalWrite(ledPin, LOW);
     allagamentocomparti=millis();
     Serial.println(" stato di sollevamento3.1");
     } 
  if (( digitalRead (2)== HIGH) && (time > allagamentocomparti+500) 
     && (time < allagamentocomparti+15000)){
     portelli.attach(6);
     portelli.write(aperto);
     Serial.println(" stato di immersione");
     digitalWrite(ledPin, LOW);
     svuotamento=millis();
     latenzareflusso1=millis();
     latenzareflusso2=millis();
     }
  if (( digitalRead (2)== HIGH) && (time > allagamentocomparti+15000)){
     portelli.write(chiuso);
     digitalWrite(ledPin, LOW);
     svuotamento=millis();
     latenzareflusso1=millis();
     latenzareflusso2=millis();
     }
 delay(15);
 }

Scusate ma mi sono quasi commosso :sob: :sob: :sob: …nel rivedere questo

Claudio_FF:
L’uso di millis è tutto qui.

Per farla ancora più semplice pensa a quando sei nato(in quel momento è partito il tuo millis()), poi ad ogni età corrisponde un cronometro(unsigned long) …fatto questo non ti resta che far partire il cronometro,e fare quello che devi quando raggiunge oppure entro il tempo impostato,…poi quando hai fatto tutto, azzeri il cronometro(dichiarando che è = al tempo trascorso da quando 6 nato(millis()). :wink: :wink:

Puso: ... quando sei nato(in quel momento è partito il tuo millis()) ...

... ma se millis ha una durata di circa 49 giorni, quello e' il massimo della tua vita ? ... :P

(scusate, non ho proprio resistito :D)