BLE Nano をあいかわらず触っている。どうしても消費電流の削減ができず3日ぐらい悩んだので、参考までに「どうすれば効率よく消費電流を削減できそうか」をしるす。
ドキュメントを良くよむこと
nRF51822_PS v3.1.pdf と nRF51_Series_Reference_manual v3.0.pdf というのが主要なドキュメントになる。前者には nRF51822 特有のことがら全般が書かれていて、こちらに消費電力や、ピンごとの物理仕様が書いてある。後者は nRF51 シリーズのシステムのドキュメントになっており、レジスタ仕様とかが書いてある。
消費電力の観点で考えると、まず nRF51822_PS v3.1.pdf に一通り目を通して、どの回路がどのぐらいの電力消費をするかを把握しておくと良い。
当然支配的なところから解決しないとどうしよもないので、大きいところをとりあえずおさえる。具体的には
- 16MHz HFCLK (クロックだけで約1mAぐらい食う)
- CPU (起きているときは 4mA ぐらい食う)
- Radio (送信出力ごとに最大電流が異なる 5.5〜16mA。かなり大きく見えるが BLE の場合送信にかける時間はかなり短いので、平均的には支配率はそれほど高くない)
スリープ中に 16MHz のクロックを切るためには
タイトルの 1mA という数字は HFCLK の消費のことを想定している。このクロックは必要ならば動くという挙動をする。CPU が動いているなら必ず動いている。
大事なのは以下の表 (nRF51822_PS v3.1.pdf から引用)
ここで HFCLK に依存しているブロックがスリープ中に一切ないようにしなければならない。nRF51_Series_Reference_manual v3.0.pdf のほうにはどのペリフェラルが HFCLK に依存しているかは書いてないので、この表はとても大事。
だいたいのブロックは必要なときだけ有効にして動かす系だけど、UART や TWI のようにだいたいオンにしてるみたいなペリフェラルもスリープ前に明示的にオフにする必要がある。というよりは必要なときだけオンにするという使いかたのほうが安全。
TWI なら
NRF_TWI0->ENABLE = TWI_ENABLE_ENABLE_Enabled << TWI_ENABLE_ENABLE_Pos; do_something(); NRF_TWI0->ENABLE = TWI_ENABLE_ENABLE_Disabled << TWI_ENABLE_ENABLE_Pos;
UART なら
NRF_UART0->ENABLE = (UART_ENABLE_ENABLE_Enabled << UART_ENABLE_ENABLE_Pos); NRF_UART0->TASKS_STARTTX = 1; NRF_UART0->TASKS_STARTRX = 1; // dummy send to wakeup... NRF_UART0->PSELTXD = 0xFFFFFFFF; NRF_UART0->EVENTS_TXDRDY = 0; NRF_UART0->TXD = 0; while (NRF_UART0->EVENTS_TXDRDY != 1); NRF_UART0->PSELTXD = tx; do_something(); while (NRF_UART0->EVENTS_TXDRDY != 1); uint32_t tx = NRF_UART0->PSELTXD; NRF_UART0->TASKS_STOPTX = 1; NRF_UART0->TASKS_STOPRX = 1; NRF_UART0->ENABLE = (UART_ENABLE_ENABLE_Disabled << UART_ENABLE_ENABLE_Pos);
みたいな感じになる。UART はなんかバグってるのかよくわからないけど、ダミーで一回書かないとちゃんと復帰しなくてこまった。mbed のライブラリにも同様のことが書いてある。
ペリフェラル以外
書きこみインターフェイス (デバッガ) で書きこんだ直後のプログラムはデバッグモードで動いていて、この状態だと上記と同じように 16MHz とデバッガ用の回路が動くようで、消費電力がまったく減らない。
この状態から抜けてノーマルモードで起動するには
- デバッガを切断したうえで、全ての電源供給をやめて、再度電源を入れなおす
- デバッガ起動中でもリセットピンでリセット可能にして、デバッガを切断するとともにピンリセットをかける
あたりがある。前者は若干めんどうなので、後者の方法のほうがおすすめ。
// Enable Pin-reset on DEBUG mode NRF_POWER->RESET = 1;
と main の冒頭あたりに書いておくと、デバッグモード中でもピンリセットがかけられる。「ピンリセットってどのピン?」と思うかもしれないが、SWDIO が nRESET と共用になっているので、書きこみ気から SWDIO/SWDCLK を抜いて GND に一瞬つなげばノーマルモードで起動するようになる。
BLE Nano 固有
BLE Nano は P0_19/D13 に LED がついてる。この LED は VDD に繋っており、負論理で光る。なので、この LED を消したいときは明示的に PullUp するか出力に設定して HIGH にする必要がある。
DigitalIn unused_p0_19(P0_19, PullUp);
備考
ちなみに英語で検索するときは nRF51 power consumption とかでググるのが良いです。