Há uma coisa importante que você precisa lembrar ao trabalhar com o tempo em um Arudino de qualquer forma:
- Toda operação leva tempo.
Sua função foo () levará um tempo. Que horas são, não podemos dizer.
A maneira mais confiável de lidar com o tempo é confiar apenas no tempo para acionar, e não trabalhar quando o próximo acionamento deve ser.
Por exemplo, tome o seguinte:
if (millis() - last > interval) {
doSomething();
last = millis();
}
A variável last
será o tempo que a rotina disparou * mais o tempo doSomething
necessário para executar. Digamos que interval
é 100 e doSomething
leva 10ms para funcionar, você receberá disparos a 101ms, 212ms, 323ms, etc. Não os 100ms que você estava esperando.
Portanto, uma coisa que você pode fazer é sempre usar o mesmo tempo, independentemente, lembrando-o em um momento específico (como sugere Juraj):
uint32_t time = millis();
if (time - last > interval) {
doSomething();
last = time;
}
Agora, o tempo doSomething()
gasto não terá efeito em nada. Então você terá disparos a 101ms, 202ms, 303ms, etc. Ainda não exatamente os 100ms que você queria - porque você está procurando mais de 100ms - e isso significa 101ms ou mais. Em vez disso, você deve usar >=
:
uint32_t time = millis();
if (time - last >= interval) {
doSomething();
last = time;
}
Agora, supondo que nada mais aconteça no seu loop, você recebe disparos a 100ms, 200ms, 300ms, etc. Mas observe o seguinte: "enquanto nada acontecer no seu loop" ...
O que acontece se uma operação que leva 5ms ocorrer a 99ms ...? Seu próximo disparo será atrasado até 104ms. Isso é uma deriva. Mas é fácil de combater. Em vez de dizer "O tempo gravado é agora", você diz "O tempo gravado é 100 ms depois do que era". Isso significa que, independentemente dos atrasos no código, o acionamento será sempre em intervalos de 100 ms ou será desviado dentro de um tick de 100 ms.
if (millis() - last >= interval) {
doSomething();
last += interval;
}
Agora você terá disparos em 100ms, 200ms, 300ms, etc. Ou, se houver atrasos em outros bits de código, você poderá obter 100ms, 204ms, 300ms, 408ms, 503ms, 600ms, etc. o intervalo possível, independentemente dos atrasos. E se você tiver atrasos maiores que o intervalo, ela executará automaticamente sua rotina vezes suficientes para acompanhar a hora atual.
Antes de você se desviar . Agora você tem instabilidade .