質問: indata * 5; sno++; //データ数を確認しやすくするため,各データにシリアル番号を付ける Serial.print(sno); Serial.print(","); Serial.println(indata); delayMicroseconds(5000); } } 試したこと――――――――――――――――――――――――――――――――――― 例えば,delay(500)の場合,ループ回数は10秒間で18回程度,delay(100)では80~90回程度となります. とりあえず遅延時間を小さくした場合,最大で360回程度(10秒間当たり)になります. 一方で,delayMicroseconds()を用いた場合,ループ回数は増加するのですが,遅延時間を変更しても一様に1200回程度(10秒間当たり)になります. 単純に考えれば,delayMicroseconds()では1秒間当たり100回以上ループしているので,delay(100)でももう少し正確に動作してもよい気がするのですが,そういうものではないのでしょうか. 補足情報――――――――――――――――――――――――――――――――――― 言語:スケッチ 使用ハード:arduino uno
回答: delay(), delayMicroseconds()の精度の問題もあると思いますが、loop() の中で何かのアクション後に一定時間次のアクションを無効化する場合 millis() で時間計測を行うのが一般的だと思います。 理由は主に次の2点です。 1. 監視対象の入力ポート(例えばボタン)が複数あるループ監視処理に対応できない。例えばBUTTON-A、BUTTON-Bがあり、それぞれが押されたらLED-A、LED-Bを点灯し、10秒後に消灯というループを考えたとき、もしBUTTON-AがHIGH -> LED-A点灯 -> delay(10000) としてしまうと、delay()中にBUTTON-BがHIGHになっても検出できない。 2. 入力イベント(例えばボタン=HIGH)を検出してから、delay() をコールするまでの処理時間はゼロではないため、delay(10000) のように固定値をセットしてしまうと、その処理時間分の遅延がループごとに累積することで、実際の時刻系と差異が発生してしまう。 millis() によるシステム時間を使ったループは例えば以下のようになります。 ``` #define MILLISECONDS_TO_WAIT 500 unsigned long time_zero = millis(); boolean button_is_high = false; void loop() { if (!button_is_high) { if (digitalRead(BUTTON) == HIGH) { button_is_high = true; time_zero = millis(); indata = analogRead(0); stress = indata * 5; sno++; //データ数を確認しやすくするため,各データにシリアル番号を付ける Serial.print(sno); Serial.print(","); Serial.println(indata); } } if (button_is_high) { if (millis() - time_zero > MILLISECONDS_TO_WAIT) { button_is_high = false; } } } ``` delay() は一般的に、外部デバイスへの出力ピンにシグナルした後で入力ピンからシグナルを検出する時に、デバイス側の制約によって数ミリ秒経過後でないと入力シグナルが安定しないので、ほんの少し WAIT させる、というような場合に使用されます。delay() の使い方については公式ドキュメントにも以下の注意書きがあります。 > > delay()を使えば簡単にLEDをチカチカさせることができます。また、スイッチのバウンス対策のためにdelay()を使っているスケッチもよく見られます。ただし、こうしたdelay()の使い方には不利な点があります。delay()の実行中は、計算やピン操作といった他の処理が実質的に止まってしまうのです。delay()の代わりにmillis()を使って時間を測り、タイミングをコントロールするほうがいいでしょう。熟練したプログラマーは、よほどスケッチが簡単になる場合を除き、10ms以上のイベントのコントロールにdelay()を使うことは避けるでしょう。 > > > ご参考になれば。