Problema millis come trascorrere del tempo e pulsante

Buongiorno a tutti, come mi avete consigliato in altri post ho iniziato a usare i millis anzichè il delay per la mia centralina del presepe in quanto avevo necessità di inserire delle subroutine.
Ho cercato su internet ma ho trovato tutti tutorial dove millis non viene usato come "scorrere del tempo".

Ho due problemi però:

  • una volta finito premuto il pulsante inizia il ciclo if = stato 1, una volta finito esegue l'else ma poi se premo di nuovo non succede niente

  • se premo il pulsante per esempio dopo 10 secondi da quando ho acceso arduino la giornata del presepio dura 10 secondi in meno....

Qualche consiglio??

Vi posto lo sketch

unsigned long currentMillis = 0; 
unsigned long tnotte = 14335;
unsigned long tgiorno = 22672;
unsigned long talba = 4000;
unsigned long tstato = 1;
unsigned long trascorso = 0;


int TouchSensor = 8;  // Collegato a pin SIG del sensore
int val = 0;          // si userà val per conservare lo stato del pin di input
int vecchio_val = 0;  // si userà vecchio_val per conservare lo stato del pin di input al passo precedente
int stato = 0;

void setup() {
 
   strip.setBrightness(BRIGHTNESS);
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'
  pinMode(lampioni,OUTPUT);//imposta il pin del Led come uscita
  pinMode(TouchSensor, INPUT); 
} 


void loop() {

 int val = digitalRead(TouchSensor);  // legge il valore dell'input e lo conserva

  // controlla se è accaduto qualcosa
  if ((val == HIGH) && (vecchio_val == LOW)) {
    stato = 1 - stato;
      
 vecchio_val = val;  
  }

 
   if (stato == 1) {
    
 unsigned long currentMillis = millis();
  if(currentMillis < tnotte) {
  //save the last time you blinked the LED
   tremolioon ();
   mezzanotte ();
  }
trascorso = tnotte;

if(currentMillis - trascorso< talba) {
  alba ();
}

 trascorso = (tnotte + talba);
  if(currentMillis - trascorso < tgiorno) {
   giorno();
   tremoliooff ();
  }
trascorso = trascorso + tgiorno;
if(currentMillis - trascorso < 10) {
   stato = 0;
      vecchio_val = 0;
   }
   
   } 

else {
     for(uint16_t i=0; i<strip.numPixels(); i++) {
    strip.setPixelColor(i, 10, 10 ,10 ); 
   }
strip.show(); // invii tutti i dati alla LED-s


}

}

In effetti hai usato millis in un modo un po' strano.

Considera millis come un orario.
Quando vuoi iniziare a misurare una cosa ti salvi l'orario di partenza.

unsigned long millisInizio = millis();

Diciamo che devi aspettare un minuti, quindi 60 secondi, quindi 60 mila millisecondi

#define INTERVALLO 60000

poi ad ogni giro dici: è passato tot tempo?

if (millis() - millisInizio >= INTERVALLO) {
  // Il tempo è trascorso
} else {
  // Il tempo non è ancora trascorso
}

Il trucco è impostare correttamente millisInizio quando inizia il monitoraggio di un certo evento.

Grazie,ho modificato il programma, ora funziona il pulsante tranne il fatto che non rispetta il tempo che ho stabilito nei #define... praticamente si accende tutto in sequeza

unsigned long millisInizio = 0; //will store last time LED was updated


#define tnotte 14335 // definisco il tempo di durata della fase del ciclo
#define tgiorno 22672
#define talba 4000

int TouchSensor = 8;  // Collegato a pin SIG del sensore
int val = 0;          // si userà val per conservare lo stato del pin di input
int vecchio_val = 0;  // si userà vecchio_val per conservare lo stato del pin di input al passo precedente
int stato = 0;

void setup() {
 
   strip.setBrightness(BRIGHTNESS);
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'
  pinMode(lampioni,OUTPUT);//imposta il pin del Led come uscita
  pinMode(TouchSensor, INPUT); 
} 


void loop() {

 int val = digitalRead(TouchSensor);  // legge il valore dell'input e lo conserva

  // controlla se è accaduto qualcosa
  if ((val == HIGH) && (vecchio_val == LOW)) {
    stato = 1 - stato;
      
 vecchio_val = val; // memorizza il valore precedente di val    
  }

 
   if (stato == 1) {
    
 unsigned long millisInizio = millis();
 
  if(millis() - millisInizio < tnotte) { // dalle ore 00 alle ore 7
   tremolioon ();
   mezzanotte ();

  }


if(millis() - millisInizio < talba) {  // dalle ore 7 alle ore 8
  alba ();
  
}

  if(millis() - millisInizio < tgiorno) {  // dalle ore 8 alle ore 18
   giorno();
   tremoliooff ();

  }

if(millis() - millisInizio > 10) {
   stato = 0;
      vecchio_val = 0;
   }
   
   } 

else {
     for(uint16_t i=0; i<strip.numPixels(); i++) {
    strip.setPixelColor(i, 10, 10 ,10 ); // imposti il colore del LED numero 'i'
   }
strip.show(); // invii tutti i dati alla LED-s


}

}

Hai messo

unsigned long millisInizio = millis();

senza condizioni, per cui viene fatto ad ogni loop.
Lo devi dichiarare come variabile globale (prima del setup per intenderci)
e dentro al loop, solo quando serve, devi impostare

millisInizio = millis();

altrimenti il test, ad es.

  if(millis() - millisInizio < tnotte) { // dalle ore 00 alle ore 7

risulta sempre vero perchè millisInizio e millis() differiscono di pochissimo visto che sono appena stati messi uguali.

Poi ogni funzione deve essere temporizzata con variabili differenti, altrimenti scattano veramente tutte assieme in sequenza, perchè appena impostata è vera per <tnotte ma è vera anche per <talba ecc.

E non terminano mai perchè non condizioni l'impostazione di millisInizio, come detto sopra.

Quindi:

  1. Dichiarare millisInizio come variabile globale
  2. Trovare un modo per capire quale delle 3 funzioni (notte, alba, giorno) devi eseguire in un dato momento
  3. Inizializzare tutta la partenza

Quindi una cosa di questo tipo (ovviamente da capire e riadattare):

unsigned long millisInizio;
char funzione; // 0=notte, 1=alba, 2=giorno

void setup() {
  millisInizio = millis();
  funzione = 0;
}

void loop() {
  if (funzione == 0) {
    if(millis() - millisInizio < tnotte) { // dalle ore 00 alle ore 7
      tremolioon ();
      mezzanotte ();
    } else {
      // La notte è finita, predisponiamo per l'alba.
      millisInizio = millis();
      funzione = 1;
    }
  } else if (funzione == 1) {
    if(millis() - millisInizio < talba) {  // dalle ore 7 alle ore 8
      alba ();
    } else {
      // L'alba è finita, predisponiamo per il giorno.
      millisInizio = millis();
      funzione = 2;
    }
  } else {
    if(millis() - millisInizio < tgiorno) {  // dalle ore 8 alle ore 18
       giorno();
       tremoliooff ();
    } else {
      // Il giorno è finito, predisponiamo per la notte.
      millisInizio = millis();
      funzione = 0;
    }
  }
}

Non ho dichiarato tutte le variabili e ho scritto direttamente qui, quindi mancano pezzi e non è detto che funzioni, va letto, capito e riadattato.

Non ho guardato come sono fatte le varie funzioni chiamate, ho assunto che siano da richiamare in modo continuo ad ogni iterazione del loop, altrimenti va gestito anche questo aspetto.

Grazie mille, ho capito il meccanismo proverò!!!