Gestire una pausa con Millis()

Salve, da qualche giorno ho ripreso in mano un mio vecchio progetto che ho iniziato tempo fa ma che non ho mai portato a termine per vari impegni, una centralina antifurto a solo scopo didattico. Questa centrale si attiva e disattiva attraverso 2 sensori RFID (uno remoto, ovvero invia il suo stato attraverso un modulo nrf11 e uno locale, collegato direttamente alla centrale). In oltre è presente un modulo 433mhz che riceve lo stato di alcuni sensori pir e un relè che attiva e disattiva una sirena. Lo so che per quanto posso fare un lavoro bene la seguente centrale è sempre vulnerabile, questa centrale non sarà installata veramente in un appartamento, ma è solamente una mia soddisfazione personale di portare un progetto al termine.
Ho scritto la seguente funzione che richiama altre funzioni che attivano/disattivano la centrale in base allo stato ricevuto da uno dei due sensori RFID:

unsigned long previousMillis = 0; 
const long interval = 20000; 
bool statoCentalina ()
{
/* Controllo lo stato dell'RFID locale */
  if(getUID()){
    if(stato==false){
      stato=true;
    }
    else
      stato=false;
  }
/* */
/* Controllo lo stato dell'RFID remoto */
  delay(5);
  radio.startListening();
  if ( radio.available()) {
    radio.read(&stato, sizeof(stato));
    Serial.println(stato);
  }
/* */

/* in base allo stato ricevuto da uno dei due RFID attivo o disattivo l'antifurto */
  if (stato==true && count==0) //se lo stato ricevuto è true..
  { 
    flag=true;
    inizializzazione (); 
    Serial.print("L'antifurto sara' attivato fra\t");
    Serial.print (interval/1000);
    Serial.print("\tsecondi.\n");
    unsigned long currentMillis = millis();
    if (currentMillis - previousMillis >= interval) {
        previousMillis = currentMillis;
        //qua voglio che la funzione inserito() venga eseguita dopo 20 secondi, valore impostato attraverso la variabile "interval"
        inserito (); //vado ad inserire l'allarme e comunico il nuovo stato della centrale al sensore RFID
        count=1;
        flag=false;
    }
  }
  if (stato==false && count==1)
  {
    count=0;
    //previousMillis=0;
    disinserito ();
    inizializzazione ();
  }

  if (stato==false && flag==true)
  {
    flag=false;
    count=0;
    previousMillis=0;
    annullaInserimento ();
    inizializzazione ();
  }
/* */
  return stato;
}

se lo stato ricevuto è "true" richiamo la funzione predefinita "millis()" poiche voglio che l'antifurto venga inserito dopo 20 secondi (valore stabilito dalla variabile interval), infatti come facile intuire, se l'utente attiva la centralina dall'RFID locale, appena passa davanti a un sensore la centrale manda in allarme la sirena, bisogna quindi dare all'utente il tempo di uscire dalla zona dei sensori.
Ebbene, questo tempo che deve trascorrere prima che venga inserito l'antifurto non è sempre 20 secondi, a volte meno, altre volte invece viene inserito all'istante. Sapreste dirmi cosa posso correggere?
Grazie in anticipo.

const long interval = 20000;

non deve più essere const ma variare secondo la logica che ti serve e che non ho visto descritta per cui l'aiuto si limita a questo per ora.

… e, parlando di millis(), è comunque bene che sia una “unsigned long:wink:

Guglielmo

...inoltre la variabile 'previousMillis' deve essere impostata al valore attuale di millis() solo nel momento esatto da cui si vuole iniziare a contare il tempo, e non in altri momenti, e men che meno va messa a zero.

maubarzi:
const long interval = 20000;

non deve più essere const ma variare secondo la logica che ti serve e che non ho visto descritta per cui l'aiuto si limita a questo per ora.

non capisco perchè questa variabile non può essere costante se l'intervallo voglio che sia sempre di venti secondi. Più in la voglio implementare un altra funzione che mi permette di variare tale valore e di andarlo a memorizzare nella EEPROM, ma al momento non va bene se la rimango come costante?
Comunque la logica del loop è questa:
si parte dallo stato uguale a false, se passo una tessera vicino all'RFID diventa a true, a questo punto voglio che dopo 20 secondi venga attivato l'antifurto. In questa chiamiamola pausa di 20 secondi posso ripassare la tessera vicino all'RFID e annullare l'inserimento dell'antifurto (quindi stato ritorna a false), da notare che le due funzioni "disinserito ()" e "annullaInserimento ()" svolgono quasi le stesse funzioni, cambia solo che stampano cose diverse nella seriale.
Se ripasso di nuovo la tessera vicino all'RFID perchè voglio attivare l'antifurto, l'intervallo prima che questo venga attivato, non deve riprendere da dove si era fermato prima, ma deve essere sempre di 20 secondi. Passati questi 20 secondi, l'antifurto passa allo stato di attivo, quando voglio posso disattivarlo e non deve trascorrere nessuna pausa prima che venga disattivato.

Ogni volta che passi la tessera devi riprendere il tempo di millis(). Poi scrivi if(millis()-tempo>2000) fai quello che devi fare.

Datman:
Ogni volta che passi la tessera devi riprendere il tempo di millis().

Non ho ben capito, cioè devo impostare la variabile currentmillis in questi punti che ho segnato?

/* Controllo lo stato dell'RFID locale */
  if(getUID()){
    if(stato==false){
      stato=true;
      //in questo punto
    }
    else
      stato=false;
      //in questo punto
  }
/* */
/* Controllo lo stato dell'RFID remoto */
  delay(5);
  radio.startListening();
  if ( radio.available()) {
    radio.read(&stato, sizeof(stato));
    //in questo punto
    Serial.println(stato);
  }
/* */

Potrebbe spiegarsi meglio?

sembra che ho risolto il problema in questo modo:

bool statoCentalina ()
{
/* Controllo lo stato dell'RFID locale */
  if(getUID()){
    if(stato==false){
      stato=true;
    }
    else
      stato=false;
  }
/* */
/* Controllo lo stato dell'RFID remoto */
  delay(5);
  radio.startListening();
  if ( radio.available()) {
    radio.read(&stato, sizeof(stato));
    Serial.println(stato);
  }
/* */

/* in base allo stato ricevuto da uno dei due RFID attivo o disattivo l'antifurto */
  if (stato==true && count==0) //se lo stato ricevuto è true..
  { 
    flag=true;
    inizializzazione (); 
    Serial.print("L'antifurto sara' attivato fra\t");
    Serial.print (interval/1000);
    Serial.print("\tsecondi.\n");
    //unsigned long currentMillis = millis();
    if (millis() - previousMillis >= interval) {
        //previousMillis = currentMillis;
        previousMillis = millis();
        inserito (); //vado ad inserire l'allarme e comunico il nuovo stato della centrale al sensore RFID
        count=1;
        flag=false;
    }
  }
  if (stato==false && count==1)
  {
    count=0;
    //previousMillis=0;
    previousMillis = millis();
    disinserito ();
    inizializzazione ();
  }

  if (stato==false && flag==true)
  {
    flag=false;
    count=0;
    //previousMillis=0;
    previousMillis = millis();
    annullaInserimento ();
    inizializzazione ();
  }
/* */
  return stato;
}

Correggetemi se ce ancora qualcosa che non va.
Ciò che mi turba adesso è dato che si suppone che la centrale resta accesa 24 ore su 24 cosa succede quando la Variabile "previousMillis" va in overflow?

Adatta i tempi, cambia il tipo della variabile (e casta manualmente il tipo di millis()) da unsigmed long a int e te ne accorgi in 2^16/1000 secondi

cosmo96:
Ciò che mi turba adesso è dato che si suppone che la centrale resta accesa 24 ore su 24 cosa succede quando la Variabile "previousMillis" va in overflow?

Direi che di questo "falso problema" se ne è parlato centinaia di volte sul forum, per cui ... studia QUI.

Brevemente, se l'IF è fatto come si deve ... l'evento non ha alcun effetto.

Guglielmo

P.S.: ... e NON è "previousMillis" ad andare i overflow, ma il contatore che la funzione millis() restituisce

cosmo96:
cosa succede quando la Variabile “previousMillis” va in overflow?

Visto che hai scritto:

millis() - previousMillis >= interval

non succede nulla, il risultato è sempre corretto (conteggio binario circolare in modulo 232).

cosmo96:
non capisco perchè questa variabile non può essere costante

semplicemente rispondevo alla variazione che hai prospettato, cioè quella di rendere l’intervallo variabile…