google-site-verification: google3bd66dd162ef54c7.html

Arduinoのmillis()関数が返す値は不連続な場合がある

 居酒屋ガレージ日記さんが、Arduinoのタイマー処理という記事を書かれています。Arduinoでは時間の粒度は4μsが最小なのですが、それだけでは説明できないジッタが発生しているのが気になっていたのですが、そうか、タイマー0の割込みの影響だったんですね。

 ちょうどArduinoを使ってパルスジェネレーターでも作ろうかと考えていたところだったので、こういう情報はすごく助かります。

 ところで、プログラム開始からの時間をミリセカンド単位で返すmillis()関数の説明の中に、
>正確には、システムクロック周波数16MHzの1/64の1/256で「1.024ms」。
>  (タイマー割り込み内では端数をうまく処理してmillis関数での誤差が出ないようにしています)
 うまく処理して誤差が出ないようにしてあります。と書かれています。また、このあたりの詳細は記事の中のリンク先で詳しい解説があります。
 Arduinoでの時間管理 [Arduino]:放課後マイコンクラブ

 ここで気になったのが、この補正方法だとmillis()が返す値が不連続になってしまいそうなことです。つまり、そのままだと時計としては遅れてしまうので、これを補正するためには時々値を一つ以上飛ばす必要があるはずです。mills()の戻り値は整数で一つづつ順番に数値が増えると思っていたのですが、1段飛ばしになることももありそうです。

 ならば、実際にmillis()の値の変化がどうなっているのかを確認するプログラムを作ってみました。
/* millis()の値の変化を表示するプログラム
* 2016/02/20 ラジオペンチ http://radiopench.blog96.fc2.com/ 
*
* 解説:millis()の値は普通は1.024ms毎に1ずつ増加する。このままでは時計に
* 対して遅れてしまうので、約42ms(1000/24)毎に一度に2つ値を増加させることで
* 補正を行っている。
* このプログラムはmillsの値を最初の500回分シリアルに出力するので、約42回
* 置きに値が飛んでいる様子が確認出来る。(42,85,127,,が無い)
*/

unsigned long LASTmills; // 前回のmillisの値
unsigned int T[500]; // 数値記録バッファ
int n = 0;

void setup() {
Serial.begin(9600);
LASTmills = millis();
while (n < 500) { // 指定回数だけ
if (millis() != LASTmills) { // millisの値が前回より変化していたら
LASTmills = millis();
T[n] = LASTmills; // 配列に値を記録
n++;
}
}
for (n = 0; n < 500; n++) {
Serial.println(T[n]); // 記録された値をシリアルに出力
}
}

void loop() { // 何もしないで待つ
}
 シリアルに直接出力していたのではとても間に合わないので、500回分をメモリに記録し、後でゆっくりとシリアルに出力するようにしてあります。

▼実行結果
シリアル出力の末尾
 500回のループなのに値が512になっています。補正のために値を飛ばしているからこうなったのでしょう。ん、511が無い。

▼先頭付近
42が無い
 予想通り42が抜けています。

 millis()関数は普段は1.024ms置きに値をインクリメント。これでは時計に対して遅れてしまうので、42.666(1000/24)回に一回だけ値を2つ増やすことで誤差を補正していることが確認出来ました。

◆まとめ
 millis()関数が返す値は連続した整数ではなく、部分的に不連続になっていました。なので、
 if( millis() == 42 ) { hoge; } と書くのは危険で、ものすごく原因が判り難いバグになってしまいます。ここは、
 if( millis() >= 42 ) { hoge; } と書くべきでしょう。

 重箱の隅をつつくような話ですみません。なお、この件を気付かせていただいた、居酒屋ガレージ日記さんに感謝します。
関連記事

コメントの投稿

管理者にだけ表示を許可する

カレンダー
09 | 2017/10 | 11
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31 - - - -
プロフィール

ラジオペンチ

Author:ラジオペンチ
電子工作を中心としたブログです。たまに近所(東京都稲城市)の話題など。60過ぎて視力や器用さの衰えを感じつつ日々挑戦!
コメントを入れる時にメールアドレスの記入は不要です。なお、非公開コメントは受け付けていません。

記事が気に入ったらクリックを!
最新記事
カテゴリ
最新コメント
リンク
FC2カウンター
検索フォーム
月別アーカイブ
RSSリンクの表示
QRコード
QRコード