3.29. 低消費電力モードとスリープモード¶
バッテリー駆動のカメラや断続的にしか動作しないセンサーは、CPUを常にフルスピードで動かしておく必要はありません。machine モジュールは、段階的に深くなる4つの省電力状態を提供しています。active、idle()、lightsleep()、deepsleep() です。深い状態になるほどチップのより多くの部分がオフになり消費電力を節約できますが、その代わり復帰に時間がかかります。適切な状態を選ぶことは、カメラがどれだけ電力を節約できるかと、何かが起きたときにどれだけ速く反応できるかとのトレードオフです。
3.29.1. Active¶
デフォルトの状態です。CPUはPythonを実行しており、すべてのペリフェラルにクロックが供給され、消費電流は最大になります。カメラのロジック電源で数十ミリアンペア、それに加えて接続されたアクセサリがそこから引く分があります。
3.29.2. idle()¶
machine.idle() は、いずれかの 割り込み(ペリフェラル、タイマー、ピンIRQ)が発生するまでCPUクロックをゲートします。RAMは生きており、ペリフェラルはオンのまま、クロックも動き続けます。停止するのはCPU自体だけで、処理すべき作業があるとマイクロ秒単位で復帰します。
外部で何かが起こるのを待つタイトなポーリングループの内側で使います。
import machine
while not button_pressed():
machine.idle()
CPUは while のチェック自体でサイクルを消費するのをやめ、次のイベントが到着すると自然に復帰します。1回あたりの節約はわずかですが、数百万回実行されるループでは積み重なって大きくなります。
3.29.3. lightsleep()¶
machine.lightsleep() は次に深い段階です。CPUは完全に停止し、チップの内部クロックのほとんどがオフになりますが、RAMとペリフェラルの状態は保持されます。復帰ソースが発生すると、スクリプトは lightsleep を呼び出したまさにその場所から再開します。変数、開いているハンドル、保留中のデータはすべて無傷のまま、ミリ秒単位で復帰します。
import machine
from machine import Pin
wake_pin = Pin("P0", Pin.IN, Pin.PULL_UP)
wake_pin.irq(lambda _: None, trigger=Pin.IRQ_FALLING, wake=machine.SLEEP)
while True:
do_work()
machine.lightsleep() # wakes on a falling edge on P0
復帰ソース(ここではピンIRQ)は、スリープ呼び出しの 前 に設定しておく必要があります。アクティブモードと比べて消費電力は大幅に下がります。正確な数値はボードや、まだ設定されているペリフェラルによって異なります。
3.29.4. deepsleep()¶
machine.deepsleep() は最も深い状態です。CPUは停止し、ペリフェラルは電源が切られ、RAMの内容が失われることがあります。電力を消費し続けるのは復帰回路と、わずかな常時オンのロジックだけです。
復帰ソースが発生すると、チップは メインスクリプトの先頭からブート します。deepsleep は戻りません。スクリプトは machine.reset_cause() を使って、deepsleepからの復帰を、新規の電源投入やハードリセットと区別します。
import machine
if machine.reset_cause() == machine.DEEPSLEEP_RESET:
# Woke from deepsleep -- restore state from non-volatile storage,
# take a measurement, etc.
pass
else:
# Fresh boot
pass
do_work()
machine.deepsleep(60_000) # arm RTC wake for 60 s, sleep, then restart
deepsleep() へのミリ秒引数は、内部的にオンチップのRTCアラームをセットします。ほとんどの他のタイマーは電源が切られているため、スリープ中の復帰タイミングを担うのはRTCです。引数なしで deepsleep() を呼び出すと、復帰は別途設定したソース(ピンIRQ、外部からセットしたRTCアラームなど)に委ねられます。
スクリプトが再起動するため、次の反復で必要なものはすべて main.py の冒頭で再構築するか、フラッシュ(またはそれを備えた部品ではRTCのバックアップレジスタ)に永続化する必要があります。Deepsleepは最大の省電力をもたらしますが、最も多くのプログラム再構成を強いられます。アプリケーションは、RAMに状態を持つ長時間動作するループではなく、スリープで区切られた一連の短い「測定バースト」として振る舞う必要があります。
3.29.5. 状態の選び方¶
適切な状態は、カメラが何を待っているかによって決まります。
ミリ秒単位で待つタイトなポーリングループ。
idle()を使います。1サイクルあたりの節約はわずかですが、全体では大きく、復帰は目に見えません。イベント間で数秒から数分アイドル。
lightsleep()を使います。状態が保持され、復帰は速く、消費電力はアクティブモードのほんの一部です。短い作業のバースト間で数分以上アイドル。
deepsleep()を使います。チップはイベント間で実質的にオフになり、スクリプトの構造は「復帰、測定、スリープ」のループに変わります。
どの状態であっても、復帰ソース は状態そのものと同じくらい重要です。タイマーでのみ復帰するdeepsleepはデューティサイクル化された測定ループであり、ピンIRQで復帰するlightsleepはイベント駆動のセンサーです。machine モジュールのスリープ関数、RTC アラーム、irq() を組み合わせることで、これらの構成要素が手に入ります。