消費電流が激減! delayWDT関数を作ってみた
引き続きArduinoの話題です。
前回の記事ではdelay関数を動かす時に SLEEP_MODE_IDLE に入れて消費電流を減らしました。これは手軽に出来るのですが、消費電力が半分になる程度の効果しかありません。
そこで、思いっきり深いスリープである SLEEP_MODE_PWR_DOWN に入れて、消費電流を減らしてみます。
▼測定の様子

CPUの消費電流を直列に入れた1Ωのシャント抵抗で測定します。
こうやってCPUの消費電流を正確に測定できるようにしてプログラムを仕上げていきます。元のプログラムは、電池で動くアナログ気圧計を作った時のもので、これを整理して delayWDT という関数に仕上げました。
完成した、delayWDTの動作確認デモ用のスケッチ ← 新版(バグ修正済み)
このプログラムの中の delayWDT( ) という関数を呼ぶことで SLEEP_MODE_PWR_DOWN モードに入った状態のディレイを実行します。
この関数の引数に0から9までの値を入れることで、16msから8secまでの10種類のディレイが得られます。ディレイ時間は飛び飛びの値しか指定出来ないので、欲しい値が無い場合は、ループなどを使って自分で調整する必要があります。
この関数ではパワーダウンモードでスリープさせたCPUを、ウォッチドッグタイマー(WDT)割り込みで再起動させています。関数名のdelayWDTはそういう由来で命名しました。
delayの時間はウオッチドッグタイマー用のオシレーターで作られています。このオシレーターはCPUチップ内のCR発振器(周波数は約128kHz)で動いているので精度はあまり良くありません。でも小さな回路が低い周波数で動いているのでものすごく小さな電流で動かすことが出来ますきます。これがウォッチドッグタイマー割込みを使ったスリープが消費電流が少ない理由です。
なお、最初は delayDeepSleep なんてかっこいい名前で引数にミリセカンド単位の値を直接指定することも考えたのですが、プログラムがややこしくなるので止めました。実は妥協して16msくらいの粒度で動かすことも試したのですが、消費電流がやや多くなってしまうので止めました。
で、この delayWDT関数の効果ですが、
▼普通のdelay関数の消費電流

消費電流は16.264mA。16MHz動作のAtmega328Pとしては普通の値です。
▼delayWDT関数の消費電流

消費電流はたった28μA。
効果は圧倒的です。ArduinoのCPUを単体で電池駆動する時に役立つと思います。
但し、この関数ではCPUのクロックを完全に止めて深いスリープ状態に入れるので、タイマーなどの機能は停止します。タイマーの中断が許されない用途ではこの関数は使えません。他にも注意が必要な点がいろいろありますが、使い方によって変わってくるので全部書くのは無理です。
なお、この関数のベースとなったアイディアはArduino Sleep_Watchdog_Batteryからいただきました。
また、こうしたらもっと消費電力が減らせたよ、という情報があればコメントで教えていただくと嬉しいです。
【2016年4月15日追記】
本文中に「注意事項はいろいろある」と書いておいたのですが、下記は特に勘違いしやすいのでご注意ください。
1) この関数で消費電力が減るのはCPUのチップ(UNO なら ATmega328P)だけです。Arduino UNO の基板にはCPU以外にUSBシリアル変換チップなどが同居していて結構な電流を消費しているのですが、これらの同居人の消費電流を減らすことは出来ません。つまり、この関数を使っても、UNOなどのボードの状態では劇的に消費電流を減らすことは出来ません。本気で省エネ運転したい場合は、CPUのチップだけで単独動作させる必要があります。
2) delayWDT()関数を呼んだ瞬間にCPUのほとんどの機能は停止します。タイマーはもちろんですが、シリアルへのデーター出力も強制的に中断されます。つまり、もしシリアル通信を行っている最中にこの関数を呼び出すと文字化けします。これを防ぐにはdelay()などでちょっと待つ、あるいはSerial.flush関数で送信完了まで待つ必要があります。
【随時追記】
1) この関数が使えるCPUは Arduino UNOなどに使われている ATmega328Pだけです。アーキが同じmega8シリーズのCPUならたぶん大丈夫だと思いますが、やったことがないのでどういう動作になるか判りません。
また、ATmega328以外のCPUにこの関数を使うと最悪の場合、ヒューズビットの書き換えなどの手段を講じないとチップが使えなくなることがあるのでご注意ください。
ArduinoのCPUをスリープさせて消費電流を減らす関数 delayWDT2という関数を作りました。こちらの方がもっと消費電流が減るはずです。(2018/04/18)
前回の記事ではdelay関数を動かす時に SLEEP_MODE_IDLE に入れて消費電流を減らしました。これは手軽に出来るのですが、消費電力が半分になる程度の効果しかありません。
そこで、思いっきり深いスリープである SLEEP_MODE_PWR_DOWN に入れて、消費電流を減らしてみます。
▼測定の様子

CPUの消費電流を直列に入れた1Ωのシャント抵抗で測定します。
こうやってCPUの消費電流を正確に測定できるようにしてプログラムを仕上げていきます。元のプログラムは、電池で動くアナログ気圧計を作った時のもので、これを整理して delayWDT という関数に仕上げました。
完成した、delayWDTの動作確認デモ用のスケッチ ← 新版(バグ修正済み)
このプログラムの中の delayWDT( ) という関数を呼ぶことで SLEEP_MODE_PWR_DOWN モードに入った状態のディレイを実行します。
この関数の引数に0から9までの値を入れることで、16msから8secまでの10種類のディレイが得られます。ディレイ時間は飛び飛びの値しか指定出来ないので、欲しい値が無い場合は、ループなどを使って自分で調整する必要があります。
この関数ではパワーダウンモードでスリープさせたCPUを、ウォッチドッグタイマー(WDT)割り込みで再起動させています。関数名のdelayWDTはそういう由来で命名しました。
delayの時間はウオッチドッグタイマー用のオシレーターで作られています。このオシレーターはCPUチップ内のCR発振器(周波数は約128kHz)で動いているので精度はあまり良くありません。でも小さな回路が低い周波数で動いているのでものすごく小さな電流で動かすことが出来ますきます。これがウォッチドッグタイマー割込みを使ったスリープが消費電流が少ない理由です。
なお、最初は delayDeepSleep なんてかっこいい名前で引数にミリセカンド単位の値を直接指定することも考えたのですが、プログラムがややこしくなるので止めました。実は妥協して16msくらいの粒度で動かすことも試したのですが、消費電流がやや多くなってしまうので止めました。
で、この delayWDT関数の効果ですが、
▼普通のdelay関数の消費電流

消費電流は16.264mA。16MHz動作のAtmega328Pとしては普通の値です。
▼delayWDT関数の消費電流

消費電流はたった28μA。
効果は圧倒的です。ArduinoのCPUを単体で電池駆動する時に役立つと思います。
但し、この関数ではCPUのクロックを完全に止めて深いスリープ状態に入れるので、タイマーなどの機能は停止します。タイマーの中断が許されない用途ではこの関数は使えません。他にも注意が必要な点がいろいろありますが、使い方によって変わってくるので全部書くのは無理です。
なお、この関数のベースとなったアイディアはArduino Sleep_Watchdog_Batteryからいただきました。
また、こうしたらもっと消費電力が減らせたよ、という情報があればコメントで教えていただくと嬉しいです。
【2016年4月15日追記】
本文中に「注意事項はいろいろある」と書いておいたのですが、下記は特に勘違いしやすいのでご注意ください。
1) この関数で消費電力が減るのはCPUのチップ(UNO なら ATmega328P)だけです。Arduino UNO の基板にはCPU以外にUSBシリアル変換チップなどが同居していて結構な電流を消費しているのですが、これらの同居人の消費電流を減らすことは出来ません。つまり、この関数を使っても、UNOなどのボードの状態では劇的に消費電流を減らすことは出来ません。本気で省エネ運転したい場合は、CPUのチップだけで単独動作させる必要があります。
2) delayWDT()関数を呼んだ瞬間にCPUのほとんどの機能は停止します。タイマーはもちろんですが、シリアルへのデーター出力も強制的に中断されます。つまり、もしシリアル通信を行っている最中にこの関数を呼び出すと文字化けします。これを防ぐにはdelay()などでちょっと待つ、あるいはSerial.flush関数で送信完了まで待つ必要があります。
【随時追記】
1) この関数が使えるCPUは Arduino UNOなどに使われている ATmega328Pだけです。アーキが同じmega8シリーズのCPUならたぶん大丈夫だと思いますが、やったことがないのでどういう動作になるか判りません。
また、ATmega328以外のCPUにこの関数を使うと最悪の場合、ヒューズビットの書き換えなどの手段を講じないとチップが使えなくなることがあるのでご注意ください。
ArduinoのCPUをスリープさせて消費電流を減らす関数 delayWDT2という関数を作りました。こちらの方がもっと消費電流が減るはずです。(2018/04/18)
- 関連記事
-
- 外付け部品無しでArduinoの電源電圧を測定する
- ArduinoのCPU温度センサーの値を読む
- 消費電流が激減! delayWDT関数を作ってみた
- Arduinoでdelay関数を実行時の消費電流を減らす
- ATmega328用の電源電流測定アダプタの製作