よく知られているArduino関数は、パラメータとして指定されたミリ秒の量のためにプログラムを一時停止するdelay()
です。
millis()
, 一方、プログラムの起動から経過したミリ秒の量を返す関数です。
一見すると、この機能の有用性を疑うかもしれません。 事実、それは多くのシナリオで非常に有用であり、しばしばdelay()
を完全に”置き換える”ということです。 まず、millis()
をdelay()
とほぼ同じように使用する方法を見てみましょう。
タイミングの問題は、しばしばプログラミングに存在します。
遅延のようなmillis()を使用する()
int period = 1000;unsigned long time_now = 0;void setup() {Serial.begin(115200);}void loop() {time_now = millis(); Serial.println("Hello"); while(millis() < time_now + period){//wait approx. ms}}
各ループ反復の終了時にコードを1000msだけ一時停止させたい場合は、上記のコードは少しばかげています。 代わりにdelay(1000)
を使用できます。 上記のコードと最後にdelay(1000)
が付いているコードの唯一の違いは、上記のコードのループが毎秒1回非常に正確に実行されることです。 delay(1000)
のコード内のループは、Serial.println("Hello")
の実行にも時間がかかるため、少し頻繁に実行されません。
delay()の代わりにmillis()を使用するのはなぜですか?
ここでは、millis()
とdelay()
の2つの利点を見ていきます。
正確なタイミング
最初に説明する利点は正確なタイミングです。 コード面では、最後の章でこれを説明しました。 millis()
を使用すると、実行時間に関係なく、ループが必要なだけ頻繁に実行されるようにすることができます(明らかに、実行時間が目的の期間より短い時間で delay()
では、ループの実行時間の長さがわからないため、これは不可能です。
このような正確なタイミングは、特定の周波数でサンプリングしたり、フィルタを実行したりするときに非常に便利です。
ノンブロッキング
millis()
のもう一つの利点は、”待っている”間にコードを実行することを妨げないことです。
うまを印刷したい”こんにちは”のシリアル回第二に、他のものを知ることができるからです。 これは、コード全体を一時停止するため、delay()
では不可能です。 ここでは、これを行うことができます一つの方法です:
int period = 1000;unsigned long time_now = 0;void setup() {Serial.begin(115200);}void loop() {if(millis() >= time_now + period){time_now += period;Serial.println("Hello");} //Run other code}
このコードのチャンクは、シリアルを印刷しないときにプログラムの残りの部分をブロックしないことを除いて、最初のチャンクにかなり似ています。
例:単純なスケジューラ
特定のビットのテキストを異なる間隔で出力するスケジューラを作成する簡単な例を書いてみましょう。
#define INTERVAL_MESSAGE1 5000#define INTERVAL_MESSAGE2 7000#define INTERVAL_MESSAGE3 11000#define INTERVAL_MESSAGE4 13000unsigned long time_1 = 0;unsigned long time_2 = 0;unsigned long time_3 = 0;unsigned long time_4 = 0;void print_time(unsigned long time_millis);void setup() {Serial.begin(115200);}void loop() {if(millis() >= time_1 + INTERVAL_MESSAGE1){time_1 +=INTERVAL_MESSAGE1;print_time(time_1);Serial.println("I'm message number one!");} if(millis() >= time_2 + INTERVAL_MESSAGE2){time_2 +=INTERVAL_MESSAGE2;print_time(time_2);Serial.println("Hello, I'm the second message.");} if(millis() >= time_3 + INTERVAL_MESSAGE3){time_3 +=INTERVAL_MESSAGE3;print_time(time_3);Serial.println("My name is Message the third.");} if(millis() >= time_4 + INTERVAL_MESSAGE4){time_4 += INTERVAL_MESSAGE4;print_time(time_4);Serial.println("Message four is in the house!");}}void print_time(unsigned long time_millis){Serial.print("Time: ");Serial.print(time_millis/1000);Serial.print("s - ");}
シリアルモニターの最初の60秒は次のようになります:
これは、コード内の実行を同期するための便利で簡単な方法です。 他のコードも同時に実行することができます。
micros()と
はdelay()
と同じようにdelayMicroseconds()
、millis()
はmicros()
と呼ばれるマイクロ秒バージョンを持っています。 より良い解決策が必要な場合は、micros()
を使用する方法があります。
しかし、micros()
はmillis()
の50日と比較して約70分後にオーバーフローすることに注意してください。 これは、関数の戻り値がゼロからすべてやり直すことを意味します。
もっと重要なこと:オーバーフローの問題をすべて一緒に回避する方法を学ぶには、このブログ記事を読んでください。
概要
millis()
とmicros()
は、タイミングタスクを扱うときに使用するのに非常に便利な関数です。 これらを認識していない場合は、代わりにdelay()
を使用する可能性がありますが、必ずしもうまく機能するとは限りません(まったくの場合)。
より多くのArduinoのヒント&トリックについては、私たちのArduinoのチュートリアルブログカテゴリをチェックしてください。 同様に、将来的にはより多くのArduino関連のコンテンツをお楽しみに!