2019年10月25日 | 更新。 |
delay関数は、Arduinoの標準関数のひとつで、指定した時間だけ、ms単位で処理を中断する働きをします。
参考:1msは1/1000秒です。
delay関数の引数は1つで、処理を中断したい時間をms単位で表わした数値を整数で渡します。
例えば、処理を100ms(0.1秒)中断したいなら、次の様に記述します。
delay(100);
処理を中断したい時間は32ビット符号なし整数で指定するので、0~4,294,967,295ms(232-1ms)の範囲で指定できます。
参考:中断したい時間に最大の4,294,967,295msを指定した場合、約49.7日間(4,294,967,295÷1000÷60÷60÷24≒49.7)処理を停止します。
delay関数には返り値はありません。
なお、delay関数は空ループを回す事により処理を中断しているので、処理を中断している間もマイコンのCPUは動作を続け、電流を消費し続けます。CPUを停止して、マイコンの消費電流を減らした状態で処理を中断したいなら、マイコンをスリープモードにする必要があります。
例えば1時間に1度だけ温度を測定し、それをSDカードに記録したいという様な場合は、温度を測定してSDカードに結果を記録する間だけCPUが動作していれば十分です。温度を測定していない間、delay関数でマイコンを待機させると、待機している間も同じように電流を消費し続けますので、電池で動作する回路の場合、電池寿命が極端に短くなります。
この例の様に、動作しなければいけないのは短時間で、大半の時間を待機しているマイコン回路の消費電力を低減するために、Arduinoを含む多くのマイコンには、スリープモードやスタンバイモード、低消費電力モードなどと呼ばれる特別な動作モードが用意されています。スリープモードではCPUが停止して、必要な情報を覚えておくRAMなど、必要最低限の回路だけが動作する様になっています。
Arduinoに搭載されているマイコンにも、スリープモードを使う機能がありますが、残念ながら、Arduinoにはスリープモードを簡単に使える様にする仕組みがありません。スリープモード関係のプログラム(スケッチ)を組むには、Arduinoの特徴である便利な環境(初心者にも使いやすい標準関数など)を離れ、マイコンメーカーが提供している機能を直接使って組む必要があります。ですから、通常のArduinoのスケッチを組むよりも難しい作業になります。
ところで、マイコンがスリープモードに入ってしまうと、CPUが停止してしまうので、CPU自らが作業を再開する事はできなくなります。CPUの外部から何らかの合図を送って、スリープモードを解除しなければなりません。
タイマなどのマイコン内蔵の周辺回路をスリープモードの解除に使う場合もありますが、場合によってはスリープモードを解除するための外部回路を設計する必要が出てきます。この場合、ある程度高度なハードウェアの知識が要求され、さらにスリープモードを扱うハードルが高くなります。
せっかく勉強をしてスリープモードを使うスケッチを作っても、別のマイコンを搭載したArduinoに機種変更した場合、スリープモードの機能や使い方に互換性がないため、スリープモード関係のプログラムは一から組み直しになってしまいます。
参考までに、Arduino Unoでスリープモードを使うプログラムを作る際に参考になるページを紹介しておきます。
参考リンクの1つ目のページは、AVRマイコンでスリープモードを使う方法について書かれたページです。Arduino UnoもATmega328PというAVRマイコンを使っていますので、このページの情報が参考にできます。
参考リンクの2つ目のページは、ATmega328Pを使って作ったArduino互換機をスリープモードにする方法を説明しているページです。Arduino Unoのユーザーは、こちらのページの情報の方がより直接的に役立つでしょう。
ただし、参考リンクの2つ目のページの方法を、本物のArduino UnoやArduino Unoの全ての機能を実現した互換機で実行しても、このページで紹介している様に、数μAにまで消費電流が減らないので、注意が必要です。(リンク先では本物のArduino Unoを使って消費電流を測定していますが、Arduino Uno全体の消費電流を測定しているのではなく、ATmega328Pというマイコンの消費電流だけを測定している事に注意が必要です)
Arduino Unoやその完全な互換機は、メインのマイコン(ATmega328P)だけではなく、ATmega328PをUSBに接続するための第2のマイコン(ATmega16U2)を搭載しています。消費電力をμAオーダーまで下げるには、ATmega16U2もスリープモードにする必要がありますが、ユーザーの作ったスケッチを実行するATmega328Pから、第2のマイコンであるATmega16U2に、スリープモードに移行する様に働きかける手段がありません。
またArduino Unoやその完全な互換機には、3.3V電源出力がありますが、5V電源を3.3Vに降圧するためのLDOという部品も、わずかに消費電流を消費し続けます。
もし、USBとの通信機能や3.3V電源が必要ないなら、それらの不必要な回路を取り除いた、簡略化されたArduino Uno互換機を自作しないと、μAオーダーの低消費電流は実現できません。
delay関数の使用例として、1分に1回、アナログ入力端子であるA0ピンに入力された電圧を測定し、その結果をシリアルポート(TXピン)に出力するスケッチをリスト1に示します。シリアルモニタ等で測定結果を見る事ができます。
void setup()
{
pinMode(A0,INPUT); // A0ピンを入力モードにする。
Serial.begin(9600); // シリアルポートを9600bpsで開く。
} // setup
void loop()
{
Serial.println(analogRead(A0)); // A0ピンの電圧を読み取って、シリアルポートに出力する。
delay(60000); // 1分間処理を中断。(1分=60秒=60,000ms) 処理中断中も消費電流が減らない事に注意。
} // loop
シリアルポートに出力されたデータを、Tera Termなどの、受信内容をテキストファイルに保存できるターミナルソフトで受信すると、入力電圧の長期的な変化を記録する装置(データロガー)ができます。アナログ電圧出力の温度センサをA0ピンに接続すれば温度の自動記録ができますし、充電中や放電中の電池の電圧をA0ピンに入力すれば、電池の充電特性や放電特性の自動測定ができます。