Il y a une chose importante dont vous devez vous souvenir lorsque vous travaillez avec du temps sur un Arudino de n'importe quelle forme:
- Chaque opération prend du temps.
Votre fonction foo () prendra un certain temps. Quelle est cette heure, nous ne pouvons pas le dire.
Le moyen le plus fiable de gérer le temps est de ne compter que sur le temps de déclenchement, et non de déterminer quand le prochain déclenchement devrait avoir lieu.
Par exemple, prenez ce qui suit:
if (millis() - last > interval) {
doSomething();
last = millis();
}
La variable last
sera le temps que la routine a déclenché * plus le temps nécessaire doSomething
à l'exécution. Disons que interval
c'est 100 et qu'il doSomething
faut 10 ms pour s'exécuter, vous obtiendrez des déclenchements à 101 ms, 212 ms, 323 ms, etc. Pas les 100 ms que vous attendiez.
Donc, une chose que vous pouvez faire est de toujours utiliser le même temps indépendamment en vous en souvenant à un moment précis (comme le suggère Juraj):
uint32_t time = millis();
if (time - last > interval) {
doSomething();
last = time;
}
Maintenant, le temps qui doSomething()
prend n'aura plus aucun effet. Vous obtiendrez donc des déclenchements à 101 ms, 202 ms, 303 ms, etc. Toujours pas tout à fait les 100 ms que vous vouliez - parce que vous cherchez plus de 100 ms qui se sont écoulées - et cela signifie 101 ms ou plus. Au lieu de cela, vous devez utiliser >=
:
uint32_t time = millis();
if (time - last >= interval) {
doSomething();
last = time;
}
Maintenant, en supposant que rien d'autre ne se passe dans votre boucle, vous obtenez des déclenchements à 100 ms, 200 ms, 300 ms, etc. Mais notez ce bit: "tant qu'il ne se passe rien d'autre dans votre boucle" ...
Que se passe-t-il si une opération de 5 ms se produit à 99 ms ...? Votre prochain déclenchement sera retardé jusqu'à 104 ms. C'est une dérive. Mais c'est facile à combattre. Au lieu de dire "l'heure enregistrée est maintenant", vous dites "l'heure enregistrée est 100 ms plus tard qu'elle ne l'était". Cela signifie que peu importe les retards que vous obtenez dans votre code, votre déclenchement sera toujours à des intervalles de 100 ms ou dérivera dans un intervalle de 100 ms.
if (millis() - last >= interval) {
doSomething();
last += interval;
}
Vous obtiendrez maintenant des déclenchements à 100 ms, 200 ms, 300 ms, etc. Ou s'il y a des retards dans d'autres bits de code, vous pouvez obtenir 100 ms, 204 ms, 300 ms, 408 ms, 503 ms, 600 ms, etc. Il essaie toujours de l'exécuter aussi près que l'intervalle que possible indépendamment des retards. Et si vous avez des retards supérieurs à l'intervalle, il exécutera automatiquement votre routine suffisamment de fois pour rattraper l'heure actuelle.
Avant de dériver . Maintenant, vous avez de la gigue .