Der er en vigtig ting, du skal huske, når du arbejder med tiden på en Arudino af enhver form:
- Hver operation tager tid.
Din foo () -funktionen tager lang tid. Hvad den tid er, kan vi ikke sige.
Den mest pålidelige måde at håndtere tid på er at kun stole på tiden til udløsning, ikke til at træne, når den næste udløsende skal være.
Tag f.eks. følgende:
hvis (millis () - sidste > interval) {doSomething (); last = millis ();}
Variablen sidste
er det tidspunkt, som rutinen udløste * plus tiden doSomething
tog at køre . Så sig interval
er 100, og doSomething
tager 10 ms at køre, du får udløsninger på 101ms, 212ms, 323ms osv. Ikke de 100ms, du havde forventet.
Så en ting du kan gøre er at altid bruge den samme tid uanset ved at huske den på et bestemt tidspunkt (som Juraj foreslår):
uint32_t time = millis (); hvis ( tid - sidste > interval) {doSomething (); sidste = tid;}
Den tid, som doSomething ()
tager, har ingen indflydelse på noget. Så du får udløsninger ved 101ms, 202ms, 303ms osv. Stadig ikke helt de 100ms, du ønskede - fordi du leder efter mere som 100ms er gået - og det betyder 101ms eller mere. I stedet skal du bruge >=
:
uint32_t time = millis (); hvis (tid - sidste > = interval) {doSomething (); sidste = tid;}
Nu, forudsat at der ikke sker noget andet i din løkke, får du udløsninger på 100ms, 200ms, 300ms osv. Men bemærk den bit: "så længe intet andet sker i din sløjfe " ...
Hvad sker der, hvis en handling, der tager 5 ms, sker ved 99ms ...? Din næste udløsning bliver forsinket indtil 104 ms. Det er en drift. Men det er let at bekæmpe. I stedet for at sige "Den indspillede tid er nu" siger du "Den indspillede tid er 100 ms senere, end den var". Det betyder, at uanset hvilke forsinkelser du får i din kode, vil din udløsende altid være med 100 ms intervaller eller glide inden for et 100ms kryds.
if (millis () - sidste > = interval) { gør noget(); sidste + = interval;}
Nu får du udløsninger ved 100ms, 200ms, 300ms osv. Eller hvis der er forsinkelser i andre kodebit, kan du få 100ms, 204ms, 300ms, 408ms, 503ms, 600ms osv. Det forsøger altid at køre det så tæt på intervallet som muligt uanset forsinkelser. Og hvis du har forsinkelser, der er større end intervallet, kører det automatisk din rutine nok gange til at indhente det aktuelle tidspunkt.
Før du havde drift . Nu har du jitter .