概要
Arduinoのmillis()をdelay()の代わりにタイミングをとるために利用する際に、オーバーフローしたときの挙動に関する実験です。Arduino UnoとESP-WROOM-32について試してみました。
Arduinoのmillis()は、プログラムを起動してから経過した時間をミリ秒単位で返す関数ですが、32ビットの整数型なので、約49日でオーバーフローします。ネット上では、約49日や50日で、millis()はオーバーフローするので対策が必要という意見を見かけます。実際にオーバーフローしたらどうなるのかを確認し、どういう対策が必要なのかを考えてみました。
と言っても、実際に約49日動かし続けたわけではなく、unsigned longの変数の最大値付近の動作を軽く試してみただけです。
結論としては、タイミングをとるために、ある時点でのmillis()の値と最新のmillis()の差分をとり、一定時間(ただしunsigned logに収まる範囲)を経過したかどうかを調べるだけなら、何も考えなくてもOK(対策は不要)、です。
実験
スケッチ
以下のスケッチを、Arduino UnoとESP-WROOM-32で動かしてみました。timerというunsigned longの変数に、4294967290を代入し、prevというunsigned longの変数に代入した4294967285を引いた結果を、diffというunsigned longの変数に代入して、それぞれの値を10進数と2進数で表示するものです。
|
|
結果
Arduino UnoとESP-WROOM-32で試した結果を、以下に示します。COM3がUnoで、COM4がESP-WROOM-32です。


Arduino UnoでもESP-WROOM-32でも、同じ結果となりました。
- timerは、4294967295になった後、0に戻る。
- (timer - prev)は、timerが0に戻った後も、単調に増加している。
このため、ある時点でのmillis()の値を保存しておき、その後、現在のmillis()の値を引いて、時間の差分を取得する処理では、オーバーフローを考えなくてもOKです。もちろん、約49日以上待つことはできませんが。
とはいえ、unsignedの引き算はいろいろ考えることがあり、難しいですね。
バージョン
Hardware: | Arduino Uno/ESP-WROOM-32 |
Software: | Arduino 1.8.4/Arduino core for the ESP32/ESP-WROOM-32 |
最終更新日
August 25, 2019