Spiegazioni per millis()

--- Questo thread è stato creato separandolo dal PRECEDENTE in cui l'OP si è cancellato. - gpb01

buona sera a tutti, sto leggendo con molto interesse tutti i vari post su questo argomento, perchè son in corso d'opera con un progettino.

Ho letto tutti i vari articoli di Leo ecc, ma resta il fatto che a quanto pare non mi è di facile comprensione la partenza del millis, e la struttura dell'if per il conteggio.

So che per voi è storia antica, ma è da poco che ho cominciato con Arduino e vorrei approfondire.
Grazie per l'interesse e il tempo dedicatomi...

la storia dei millis è come un orologio e un foglio di carta
se devi fare qualche cosa (tipo spegnere l'arrosto) tra 2 ore che fai?
ti segni sul pezzo di carta che ore sono adesso
e cominci a leggere il giornale
poi ogni tanto controlli se la differenza tra l'ora attuale e l'ora che ti sei scritto è uguale o maggiore di 2 ore
se non è vero non fai nulla e continui a leggere ancora una pagina di giornale
se è vero (sono passate le 2 ore), spegni l'arrosto :slight_smile:

oraInizioControllo = millis()

void loop() {
  if ((millis() - oraInizioControllo) >= 2Ore) {
     spegniArrosto
  }
  else {
     LeggiGiornale
  }
}

ok, solo che sto vedendo che per esempio tu il tempo corrente e il tempo da confrontare li metti tra parentesi, in altri sketch no.
per esempio alla fine dell'if alcuni aggiornano il tempo corrente con il tempo di partenza, altri no

alcuni resettano il tempo memorizzato con il tempo da far passare.

Vorrei capire questi modi di interpretare l' if e i vari confronti e aggiornamenti per poter gestire le pause o i tempi di conteggio tra una operazione e l'altra

grazie

kemosabesay:
ok, solo che sto vedendo che per esempio tu il tempo corrente e il tempo da confrontare li metti tra parentesi, in altri sketch no.

Però questo NON ha nulla a che vedere con millis(), questa è una domanda di BASE sulla sintassi del 'C' e, se ci pensi un'attimo, e ricordi le precedenze degli operatori in 'C', ti dovrebbe risultare chiaro che quelle parentesi servono SOLO per aumentare la leggibilità e NON hanno alcun effetto sul codice.

kemosabesay:
per esempio alla fine dell'if alcuni aggiornano il tempo corrente con il tempo di partenza, altri no

... ragionaci e capirai che dipende da quello che vuoi fare ... se è una cosa che fai "una tantum" non ti serve aggiornare nulla, ma se è una cosa che devi fare con una determinata "periodicità", ovviamnete devi aggiornare per poter calcolare quando è il prossimo momento in cui fare la cosa :slight_smile:

kemosabesay:
alcuni resettano il tempo memorizzato con il tempo da far passare.

... non mi è chiaro, cosa intendi ? Parli dell'aggiornamento del "oraInizioControllo" (per usare lo stesso nome di variabile usato da Patrick) ?

Se SI, allora li ci sono due strade ...
... se a te interessa avere un "intervallo di ripetizione" esattamente costante, incrementi la variabile del tempo esatto, se invece vuoi fare una cosa dopo X tempo dal aver terminato di farla (quindi tenendo in conto del tempo che occorre a fare la cosa) allora gli assegni il valore corrente di millis() per conteggiare da quel momento in poi.

Spero sia tutto chiaro ... comunque la cosa migliore per capire e prendere proprio l'esempio di Patrick e ragionarci sopra con calma :wink:

Guglielmo

Patrick_M:
se è vero (sono passate le 2 ore), spegni l'arrosto :slight_smile:

Mi sa che questo esempio te lo rubo :slight_smile:


Per il resto mi sembra che la maggior parte dei problemi non riguardino tanto millis ma come strutturare il codice per:

  • Fare qualcosa dopo un certo tempo (si carica la variabile tempo una volta all'inizio e si controlla quando è trascorso il tempo voluto).
  • Fare diverse cose in sequenza con tempi diversi (si parte come prima, ma alla fine di ogni "cosa" si ricarica la variabile tempo con il tempo attuale avanzando di fase per occuparsi della nuova "cosa").
  • Fare diverse cose indipendenti con tempi diversi (ogni "cosa" deve avere una sua variabile tempo personale).
  • Fare qualcosa ad intervalli precisi (la variabile tempo va incrementata esattamente del valore dell'intervallo voluto).

Claudio_FF:
Mi sa che questo esempio te lo rubo :slight_smile:

... omissis

:smiley:

Siete tutti molto gentili, ma vi sfrutto ancora un po.
Ho visto anche gli esempi che ha fatto Claudio_FF che sfruttando la logica del" ogni conteggio non influenza il programma..",
quindi vorrei capire come affrontare il problema del far fare due o piu cose contemporaneamente al programma...

grazie

fai lo stesso ragionamento di prima ma con 2 arrosti dove 1 cuoce in 2 ore e l'altro in 3 (sempre con il solito orologio e pezzo di carta) :wink:

Sfruttando l'ottimo esempio dell'arrosto e del giornale :slight_smile: immagina che ad un certo punto della giornata metti l'arrosto in forno e ti segni l'ora in cui l'hai messo in un foglio (Chiamiamolo Foglio1) sapendo che deve cuocere per due ore, a questo punto ti siedi a leggere il giornale e ogni tanto controlli che ore sono e fai la differenza con l'ora del Folgio1 se sono passate due ore sforni altrimenti ti rimetti a leggere il giornale.
Leggendo il giornale (e l'arrosto è sempre in forno da un po' di tempo quanto non è importante) ti accorgi che vuoi cuocere anche una torna nel microonde ( :o vabbé) allora vai e metti la torta nel microonde e ti segni su un altro foglio (che chiameremo Foglio2) l'ora in cui l'hai messa e ti rimetti a leggere il giornale.
Ogni tanto smetterai di leggere il giornale e controllerai se tra l'ora attuale e della del Foglio1 è trascorso il tempo necessario, se si sforni l'arrosto, altrimenti non fai nulla. Subito dopo aver controllato il Foglio1 controlli anche la differenza tra l'ra attuale e l'ora del Foglio2 per sapere se devi sformare la torta dal microonde, se si la sforni, altrimenti non fai nulla. In entrambe i casi dopo aver deciso se sfornare o no l'arrosto e se sfornare o no la torta poi ti rimetti a leggere.
Quindi Folgio1 e Foglio2 non sono altroché due variabili con due nomi differenti che verranno controllate da due if indipendenti

Mi sono sovrapposto con Patrick_M ma ho scritto troppo per non pubblicare :slight_smile:

kemosabesay:
quindi vorrei capire come affrontare il problema del far fare due o piu cose contemporaneamente al programma...

... "contemporaneamente" è una parolona e ... NON lo farai mai, hai una sola MCU con un solo "core" e quindi una sola cosa per volta. :wink:

Quello che fai è fare le cose in modo da non fermare mai il programma e fare un po' di una cosa ed un po' di un altra, scegliendo le opportune tempistiche, come ti ho già detto nel terzo punto del mio post #19 e come claudio_ff ti ha ribadito nel post #20.

Guglielmo

ok , adesso mi metto un po all'opera e faro' impazzire il mio Nano........
Posso continuare a rompervi..... man mano che proseguo?

Grazie ancora

kemosabesay:
Posso continuare a rompervi..... man mano che proseguo?

Il forum è qui per quello :wink: quando ti incagli posti il codice che hai prodotto e cosa non va e gli aiuti (di solito) arrivano

ora la culinaria è di moda :smiley: e allora ci adattiamo :wink:

allora, dopo aver scoperto che ho bruciato un Nano.... >:( >:( >:( ,
vi propongo questo primo pezzettino, so già che non funziona, e non vorrei la soluzione da voi ma spiegazioni sugli errori in modo da poter capire e poter correggere

 // *** PIN COLLEGATI
  
  const int frecce=11;
  const int Inclinometro=12;    //inclinometro

 // *** VARIABILI DI STATO

int Stato_Incl=0;       
  int Sirena= A0;               //sirena

// *** VARIABILI DI TEMPO
unsigned long tempo_mem=0;
unsigned long spegnimento=0;
unsigned long accensione=0;
const long T_Accendi = 5000;
const long T_Spegni = 3000;

void setup() {
pinMode (frecce, OUTPUT);
 pinMode (Inclinometro,INPUT);
         Serial.begin(9600); 
}

void loop() {
  Stato_Incl=digitalRead(Inclinometro);
  
  while (Stato_Incl==1);
{
    Serial.print(Stato_Incl);
  
        blinkveloce();
}

}
void  blinkveloce()
{
 
    static byte situazione = 0;
   
    tempo_mem = millis();
  if (situazione == 0  &&  tempo_mem - accensione >= 200) 
  {
    digitalWrite(frecce, HIGH);
       spegnimento = millis();
    situazione = 1;
  }
  else if(situazione == 1  &&  tempo_mem - spegnimento >= 400) 
  {
    digitalWrite(frecce, LOW);
        accensione = millis();
    situazione = 0;
  }
}

allora, dopo aver scoperto che ho bruciato un Nano.... >:( >:( >:( ,

cos'è un arrosto piccolo piccolo? :smiley:

passiamo al programma

 while (Stato_Incl == 1);  // <--- questo ";" è di troppo
  {
    Serial.print(Stato_Incl);

    blinkveloce();
  }

qui dici:
fino a che Stato_Incl è = 1 fai
...
...
quindi non esce dal ciclo while sino a che Stato_incl non cambia
e dentro a questo while chi fa cambiare Stato_Incl?

dentro blinkveloce la variabile tempo_mem puoi eliminarla così:

void  blinkveloce(){
  static byte situazione = 0;
  if (situazione == 0  &&  ((millis() - accensione) >= 200))  {
    digitalWrite(frecce, HIGH);
    spegnimento = millis();
    situazione = 1;
  }
  else if (situazione == 1  &&  ((millis() - spegnimento) >= 400))  {
    digitalWrite(frecce, LOW);
    accensione = millis();
    situazione = 0;
  }
}

a me piacciono le parentesi :slight_smile:

infatti a forza di parlare di arrosti e torte......
allora prima di far partire " blinkveloce" devo avere un controllo che gli dia un comando, ho bisogno di controllare incl con stato incl. Che non è altro che un pulsante, e che fino a quando è premuto - fa blinkveloce, quando è rilasciato no. Oppure?

sto vedendo che sia che inclinometro, e di conseguenza stato_incl, sia a 0 o a 1 blink parte lo stesso.......come mai????

riposta programma corretto perchè non mi torna... se la condizione è while(stato_incl==1) se è zero non ci entra
il problema era appunto che non ne usciva più

passo indietro,sennò impazzisco....
perchè se io scrivo questo non funziona

const int Frecce=11;           //frecce
  const int Inclinometro=12; 

int Stato_Incl;

void setup() {
 pinMode (Frecce, OUTPUT);
 pinMode (Inclinometro,INPUT);

}

void loop() {
 Stato_Incl=digitalRead(Inclinometro);
 while (Stato_Incl==0);
{digitalWrite(Frecce,!digitalRead(Frecce));
delay(500);

}}

mentre se scrivo questo si?????

const int Frecce=11;           //frecce
  const int Inclinometro=12; 

int Stato_Incl;

void setup() {
 pinMode (Frecce, OUTPUT);
 pinMode (Inclinometro,INPUT);

}

void loop() {
 Stato_Incl=digitalRead(Inclinometro);
 while (digitalRead(Inclinometro==HIGH);
{digitalWrite(Frecce,!digitalRead(Frecce));
delay(500);

}}

Nel primo caso una volta entrato nel while resti bloccato dentro perché la variabile 'Stato_Incl' non cambia più.

Nel secondo la variabile 'Stato_Incl' è del tutto inutile, perché la condizione del while legge direttamente l'ingresso (e lo legge ad ogni ciclo per cui si accorge quando cambia).