Quando millis() riparte da zero
Fa parte della sezione Temporizzazione senza delay del percorso Arduino di Coddy. Lezione 17 di 18.
Un unsigned long si ferma a 4,294,967,295. Dopo circa 49.7 giorni, millis() lo raggiunge e riparte da 0. Questo fenomeno si chiama overflow.
Un tipo più piccolo mostra la stessa cosa. Un unsigned int si ferma a 65535:
unsigned int a = 65530;
a = a + 10; // 65540 non rientra nell'intervallo: a ora vale 4La sottrazione si comporta allo stesso modo e questo la rende sicura: un orologio partito da 65530 che ora segna 4 ha contato 10 passi, e 4 meno 65530, memorizzato in un unsigned int, è esattamente 10. Allo stesso modo, millis() - start indica sempre il tempo trascorso da start, anche in caso di overflow.
L'addizione non è sicura. In now >= start + interval, la somma può superare il limite massimo e ripartire da un numero piccolo, facendo scadere subito il timer. E quando now è ripartito da zero ma la somma no, il timer non scade mai. Sottrai sempre:
if (now - start >= interval) {
// fatto
}Sfida
MedioNessuno può aspettare 49 giorni per un test, quindi questo sketch fornisce a isDone() tempi vicini al rollover e stampa le sue risposte. Dice "done" troppo presto e "waiting" per sempre. Correggi l'unica riga in isDone() in modo che confronti il tempo trascorso da start con interval.
Premi Run, leggi le quattro risposte, correggi la riga, poi premi Check.
Provalo tu
const unsigned long interval = 2000;
// Il timer avviato a start è scaduto al momento now?
bool isDone(unsigned long start, unsigned long now) {
return now >= start + interval; // correggi questa riga
}
// Stampa il tempo trascorso e ciò che restituisce isDone().
void test(unsigned long start, unsigned long now) {
Serial.print(now - start);
Serial.print(" ms: ");
if (isDone(start, now)) {
Serial.println("done");
} else {
Serial.println("waiting");
}
}
void setup() {
Serial.begin(9600);
// millis() si ferma a 4294967295, poi riparte da 0
test(4294966000, 4294966500); // poco prima del ritorno a 0
test(4294966000, 4294967200); // ancora prima del ritorno a 0
test(4294966000, 900); // l'orologio ha superato lo 0
test(4294964000, 500); // un timer avviato in precedenza
}
void loop() {
}
Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.
Tutte le lezioni di Temporizzazione senza delay
Esercitati da solo: Playground Arduino