質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.51%
Arduino

Arduinoは、AVRマイコン、単純なI/O(入出力)ポートを備えた基板、C言語を元としたArduinoのプログラム言語と、それを実装した統合開発環境から構成されたシステムです。

Q&A

解決済

2回答

29385閲覧

Arduinoのdelay関数が正確に動作しません(遅延します)

K.U.

総合スコア11

Arduino

Arduinoは、AVRマイコン、単純なI/O(入出力)ポートを備えた基板、C言語を元としたArduinoのプログラム言語と、それを実装した統合開発環境から構成されたシステムです。

0グッド

2クリップ

投稿2016/05/10 17:01

編集2016/05/10 20:06

デジタル回路初心者です.
arduinoを用いて正確なサンプリング時間を可能とするデータロガーの作製を目指しております.

アナログピンから電圧データを取り込み,シリアルウィンドウにテキストデータで表示します.
サンプリング時間はdelay関数で設定しています.
しかしながら,下記に示すプログラムではdelay関数が正確に動作しません.
delay(1000)では1秒刻みで動作しているようなのですが,遅延時間をこれより小さくすると指定した遅延よりさらに遅くなります.
arduinoで時間分解能が正確(サンプリング周波数が100~1kHz程度)なデータロガーを作ることは可能なのでしょうか.

ソースコード―――――――――――――――――――――――――――――――――――
const int BUTTON = 9;
int indata, val=0, sno=0;
float stress; //入力信号は圧力センサの電圧値

void setup(){
Serial.begin(9600);
pinMode(BUTTON, INPUT);
}

void loop(){
val = digitalRead(BUTTON); //スイッチを押すと取り込み開始
if(val == LOW){
return;
}
else{
indata = analogRead(0);
stress = 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

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

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() によるシステム時間を使ったループは例えば以下のようになります。

C

1#define MILLISECONDS_TO_WAIT 500 2unsigned long time_zero = millis(); 3boolean button_is_high = false; 4 5void loop() { 6 if (!button_is_high) { 7 if (digitalRead(BUTTON) == HIGH) { 8 button_is_high = true; 9 time_zero = millis(); 10 indata = analogRead(0); 11 stress = indata * 5; 12 sno++; //データ数を確認しやすくするため,各データにシリアル番号を付ける 13 Serial.print(sno); 14 Serial.print(","); 15 Serial.println(indata); 16 } 17 } 18 if (button_is_high) { 19 if (millis() - time_zero > MILLISECONDS_TO_WAIT) { 20 button_is_high = false; 21 } 22 } 23}

delay() は一般的に、外部デバイスへの出力ピンにシグナルした後で入力ピンからシグナルを検出する時に、デバイス側の制約によって数ミリ秒経過後でないと入力シグナルが安定しないので、ほんの少し WAIT させる、というような場合に使用されます。delay() の使い方については公式ドキュメントにも以下の注意書きがあります。

delay()を使えば簡単にLEDをチカチカさせることができます。また、スイッチのバウンス対策のためにdelay()を使っているスケッチもよく見られます。ただし、こうしたdelay()の使い方には不利な点があります。delay()の実行中は、計算やピン操作といった他の処理が実質的に止まってしまうのです。delay()の代わりにmillis()を使って時間を測り、タイミングをコントロールするほうがいいでしょう。熟練したプログラマーは、よほどスケッチが簡単になる場合を除き、10ms以上のイベントのコントロールにdelay()を使うことは避けるでしょう。

ご参考になれば。

投稿2016/05/11 01:25

編集2016/05/11 01:31
tkanda

総合スコア2425

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

K.U.

2016/05/11 11:25

 詳細にご教授いただき誠にありがとうございます.  これまで,delay関数とmillis関数の違いに関して特に意識しておらず,大変勉強になりました.  また,プログラムの方も添削していただき重ねて御礼申し上げます.  ちなみに作成いただいたプログラムに関して一点質問がございます.  直していただいたプログラムの5,7行目にて”!”や”true”を用いた構文に変更いただいておりますが,これも何かしらの理由があるのでしょうか.  millis関数を使う上で,このような構文にしたいただいたのでしょうか.
guest

0

Delay を使う事の是非に関しては、tkanda さんが書いていらっしゃるので、

arduinoで時間分解能が正確(サンプリング周波数が100~1kHz程度)な
データロガーを作ることは可能なのでしょうか.

分解能と、精度の違いについて理解していますか?
目標とする、周期が、100Hz~1KHz となっていますが、
安定度、精度、温度変化に対してはどの程度を目安としていますか?
単に、趣味の物、普通のデータロガー、計量検定機器程度、精密計測機器
目指すところによって、使用する技術の適否があります。
各部品においては、温度係数や、温度による精度があります。
一般的なマイコンに使われる、xtal やレゾネータの精度は高くありません。
⇒なので、RTCが無い場合時計の精度が出ない、有っても月差±十数秒等は、当たり前
月差±数秒を望むと途端に環境と価格の面で厳しくなります。
PCなどで、データロガーを作成する場合は、時刻の担保を考えます。
RTC毎に時計のズレが異なりますので、RTCの補正機能が付いているものもあり、
補正機能が無い場合は、時刻の合わせ込機能をプログラムで実装したりします。

RC発信程度で済む。:精度、安定度この程度で十分。
安い発信器モジュールと、マイコンのプリスケーラを使います。
発振器 の精度の良い物を使って足りる:このレベルで収めないと、
発振器だけで済まず高価になります。
発振器 の精度の良い物でも足りない。
温度管理された環境が用意できて、費用は掛かっても良い。

ソフトウェア的には、
例えば、100Hz を担保する場合は、
100Hz の間に、最低2回、もしくは、3回以上計測を行います。
値の処理としては、各種平均処理有無、変化量による除外処理等を考慮します。
定周期計測を行う場合は、割込み機能を使い、ポーリングの使用は避けます。
ポーリングで行うのは、割込みルーチンの結果を処理したり、
上位との通信処理や、定周期でなくても良い処理です。
割込みラインを使う場合、プリスケーラを使う場合で異なりますが、
プリスケーラを使う場合は、目的とする周期の10~100倍の
信号を入れて、割込みを発生させます。
⇒232c/422 のプリスケーラ用の周波数や、時計のクリスタルが中途半端な数字な理由を考えてみて下さい。

投稿2016/05/11 02:20

編集2016/05/11 02:29
daive

総合スコア2028

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

K.U.

2016/05/11 13:13

 詳細な解説をいただき誠にありがとうございます.  現在,普通のデータロガー程度の性能を目指しております.  必要な分解能は標本化定理とこれまでの経験則から100~1kHz程度と考えております.  測定は長くとも数十分程度を考えており,月差数十秒までの精度は必要ありません.精度は±10μsほどで問題ないかと考えております.  測定環境も室温であり高温や大きな温度変化は無いため,温度変化は特に意識しておりませんでした.  よって,外付けで水晶振動子やRTCモジュールがあれば十分でしょうか.現在,別件でRTCモジュール(DS1307)も購入したので,こちらの利用も考えております.  また,「100Hz の間に、最低2回、もしくは、3回以上計測を行います。」とのことですが,これはつまり,最低でも200Hz,もしくは300Hzのサンプリングが必要ということでしょうか.  ソフトウェア的な開発(割り込み処理や平均処理有無,除外処理等)に関しては,未だ噛み砕けていない状態です.こちらに関してはもう少々時間をかけて理解を進めていきたいと考えております.
daive

2016/05/11 21:59 編集

簡単な処では、三菱、オムロン、キーエンスのPLC用の、 アナログ入力モジュールの仕様、機能や データロガーなどから、調べてみてください。 データロガーでは、 ノイズを含めた、生値が欲しい場合 各種平均値が欲しい場合 変化量を逸脱した値は除外したい場合 などが有ったりします。 ⇒計測時に行うのか、後処理で行うのかは、システムの考え方次第。  短時間での計測では、単純に生値を取得して、後処理で対応が多い筈です。 ’ 計測時間が数十分であれば、数百円のモジュールでも 気付く程のズレは出ないと思います。 ズレがばれるのは、積算入力、時間積算、 アナログ値⇒積算化がある場合です。 ’ >これはつまり,最低でも200Hz,もしくは300Hzのサンプリングが >必要ということでしょうか 考え方と、仕様書の書き方次第になると思います。 >標本化定理とこれまでの経験則 であれば、必要無いと思われます。後処理をするのですよね? ' RTC:DS1307 https://www.maximintegrated.com/jp/products/digital/real-time-clocks/DS1307.html ついでに、 データロガーIC https://www.maximintegrated.com/jp/products/digital/data-loggers.html ’ 開発中、機能テストなどで、I2Cのチップでアドレス が同じ物を、どうしても使わなければならない場合は、 I2CマルチプレクサというICもあったりします。
K.U.

2016/05/21 14:09

 返信いただきありがとうございます.  確かに,製品化されているデータロガーのデータシート等を見て評価項目を知ることで,作製に当たりどのような情報が必要になるか勉強できそうです.  確認してみます.
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.51%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問