Arudinoで時間を使って作業する際に覚えておかなければならない重要なことが1つあります。
foo()関数は、ある程度の時間がかかります。その時はなんて言えない。
時間を処理する最も信頼できる方法は、トリガーの時間のみに依存することであり、次のトリガーが必要なときのワークアウトではありません。
たとえば、次のようにします。
if (millis() - last > interval) {
doSomething();
last = millis();
}
変数last
は、ルーチンがトリガーした時間と、doSomething
実行にかかった時間です。したがってinterval
、100とするとdoSomething
、実行に10ミリ秒かかります。101ミリ秒、212ミリ秒、323ミリ秒などでトリガーが発生します。期待していた100ミリ秒ではありません。
したがって、できることの1つは、特定の時点でそれを覚えておくことで、常に同じ時間を使用することです(Jurajが示唆しています)。
uint32_t time = millis();
if (time - last > interval) {
doSomething();
last = time;
}
今、doSomething()
かかる時間は何にも影響を与えません。したがって、101ミリ秒、202ミリ秒、303ミリ秒などでトリガーが発生します。100ミリ秒以上経過していることを探しているため、101ミリ秒以上を意味します。代わりに使用する必要があります>=
:
uint32_t time = millis();
if (time - last >= interval) {
doSomething();
last = time;
}
ここで、ループで他に何も起こらないと仮定すると、100ms、200ms、300msなどでトリガーが発生します。しかし、ビットに注意してください:「ループで他に何も起こらない限り」 ...
5ミリ秒かかるオペレーションが99ミリ秒で発生した場合はどうなりますか?次のトリガーは104msまで遅延されます。それはドリフトです。しかし、戦闘は簡単です。「記録された時間は今です」と言う代わりに、「記録された時間はそれよりも100ms遅い」と言います。つまり、コードでどのような遅延が発生しても、トリガーは常に100ミリ秒間隔で行われるか、100ミリ秒のティック内でドリフトします。
if (millis() - last >= interval) {
doSomething();
last += interval;
}
これで、100ms、200ms、300msなどでトリガーが発生します。または、コードの他のビットに遅延がある場合、100ms、204ms、300ms、408ms、503ms、600msなどが発生する可能性があります。常に、遅延に関係なく可能な限り間隔。また、間隔よりも大きい遅延がある場合は、現在の時刻に追いつくのに十分なだけルーチンが自動的に実行されます。
ドリフトする前に。今、あなたはジッターを持っています。