Quando millis() dá a volta
Parte da seção Temporização sem delay do Journey de Arduino da Coddy. Lição 17 de 18.
Um unsigned long para em 4,294,967,295. Após cerca de 49,7 dias, millis() chega a esse valor e começa novamente em 0. Isso é chamado de transbordamento.
Um tipo menor mostra a mesma coisa. Um unsigned int para em 65535:
unsigned int a = 65530;
a = a + 10; // 65540 não cabe: a agora é 4A subtração dá a volta da mesma maneira, e isso a torna segura: um relógio que começou em 65530 e agora marca 4 contou 10 passos, e 4 menos 65530, armazenado em um unsigned int, é exatamente 10. Da mesma forma, millis() - start sempre representa o tempo desde start, mesmo quando ocorre um transbordamento.
Somar não é seguro. Em now >= start + interval, a soma pode passar do limite e dar a volta para um número pequeno, fazendo com que o temporizador termine imediatamente. E quando now já deu a volta, mas a soma ainda não, ele nunca termina. Sempre subtraia:
if (now - start >= interval) {
// concluído
}Desafio
MédioNinguém consegue esperar 49 dias por um teste, então este sketch fornece à função isDone() horários próximos à volta do contador e imprime suas respostas. Ela diz "done" cedo demais e "waiting" para sempre. Corrija a linha em isDone() para que compare o tempo decorrido desde start com interval.
Pressione Executar, leia as quatro respostas, corrija a linha e, em seguida, pressione Verificar.
Experimente você mesmo
const unsigned long interval = 2000;
// O temporizador que começou em start já terminou no instante now?
bool isDone(unsigned long start, unsigned long now) {
return now >= start + interval; // corrija esta linha
}
// Exibe quanto tempo se passou e o que isDone() retorna.
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() para em 4294967295 e depois recomeça em 0
test(4294966000, 4294966500); // logo antes da volta ao início
test(4294966000, 4294967200); // ainda antes dela
test(4294966000, 900); // o relógio passou por 0
test(4294964000, 500); // um temporizador que começou antes
}
void loop() {
}
Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Temporização sem delay
Pratique por conta própria: Playground de Arduino