BLE/iBeacon 消費電力ハック

![TEK0008.JPG](https://qiita-image-store.s3.amazonaws.com/0/11626/5588911c-edad-0300-1e1d-8e2db51a1ce1.jpeg)

本記事ではBLE/iBeaconの消費電力についてハックしていこうと思います。

低消費電力化が進むさまざまなIoTデバイスにおいて、消費電力は常に付きまとうテーマです。
本記事ではその電力を可視化することで理解を深めます。

本記事ではまず、ざっくりとiBeaconがどれくらい電池寿命がもつのかを評価サイトを見ていきます。そして、電池寿命に何が関わっているのかについて深掘りしていきます。


# 本記事の対象範囲
BLEに関する基本的な用語解説はしません。
以下３つの視点でBLE/iBeaconの消費電力を捉えていきます。

1. 第三者が計測した結果から大まかに見積もる（マネージャ/ソフトウェアエンジニアレベル）
2. 実測値からざっくり見積もる（組込みエンジニアレベル）
3. データシートから論理的に見積もる（2よりシビアな電力量計算レベル）

# iBeaconの電池寿命はどれくらいなのか

各社beaconの性能評価した非常に参考になるサイトがあります。

http://www.aislelabs.com/reports/beacon-guide/

このサイトでは
「アドバタイジングの設定によってどれくらい電池の持ち時間が変わるのか？」
という視点でとても興味深い結果を出しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11626/211fde5b-16a8-e6cf-a833-1a2b8b660944.png)


本記事で対象としているChipset の **Nordic** の列に注目すると
当然ですが横軸では電池が大きくなるほど寿命が長くなっています。

注目は Advertisement Interval が長くなるほど電力の持ちがよくなっている点です。
その数値にほぼ比例するように電池寿命が長くなっています。
CR2032 240mAhの行をグラフにした図が以下です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11626/0436c9b0-6f1a-3539-5c51-2a4cadb607ab.png)

Advertisement Interval 100msに対して900msでは実に10倍も電池が長持ちしています。
つまりこの Advertisement Interval（以下、アドバタイジングインターバル）が電池持ちに重要な値であることがわかります。

次にサイトではTxPowerについても言及しています。
TxPoewrの設定によって-30dBm〜0dBmで電波の届く距離が変わります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11626/167f8bce-c7d5-cf6d-e6f5-15abf06c1784.png)

-30dBmでは1Mまでしか届かないのに、0dBmにすると50M先まで届くという結果を出しています。
もちろん、それと引き換えに電力をより消費しています。

BLE/iBeaconの消費電力において、以下の２つが重要なファクターであることがわかります。

- アドバタイジングインターバル
- TxPower

この2つの要素について深く見ていきます。

# アドバタイジングインターバルとはどこの時間間隔のことを指しているのか

アドバタイジングインターバルとはどこの時間のことを指しているのでしょうか。

BLEは一瞬起きて電波を発し、すぐに寝る、ということを繰り返すことで低消費電力を実現しています。アドバタイジングインターバルとは、電波（アドバタイジング）を発したあと次の電波を発するまでの時間のことを指します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11626/036eee4e-1287-fb96-418c-4de33c26520e.png)

参考：http://www.ti.com/lit/an/swra475/swra475.pdf
（※図中 DelayについてはTipsにて）

この値を短くすることでアドバタイズ頻度が高くなり消費電力は高くなってしまいます。
しかし、セントラルから発見されやすくなりスキャン時間の短縮につながります。

## TxPower とは電波強度のこと

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11626/65e7200c-82a1-d419-695d-ade2ab8ef9e9.png)
画像引用元：https://community.estimote.com/hc/en-us/articles/201636913-What-are-Broadcasting-Power-RSSI-and-other-characteristics-of-beacon-s-signal-

TxPowerはBLEデバイスが発する電波強度です。
nRF51ではこのTxPowerを4dBm刻みで変更できるようになっています。
実際にiPhoneとBLEデバイスを近くにおいた状態でTxPowerを+4dBmすると、ちゃんと電波強度が+4dBm増すことがわかります。

TxPowerを高くすることで、消費電流が大きくなりますが
より遠くへ電波を届けることができます。
別の言い方をすると、障害物がある場合でもスマホへの通知が届きやすくなります。

# コードレベルでどのように調整するのか
具体的なコードは以下のようにします。これはnRF51のコードですが、他のBLEデバイスの開発環境にも同様のコードがあるでしょう。

## アドバタイジングインターバルの設定

```c
// アドバタイジングインターバル 100 msec ~ 10240 msec
#define ADVERTISING_INTERVAL_MSEC   (100)
#define NON_CONNECTABLE_ADV_INTERVAL    MSEC_TO_UNITS(ADVERTISING_INTERVAL_MSEC, UNIT_0_625_MS) // ユニット単位に変換
...
    static ble_gap_adv_params_t m_adv_params;
...
    m_adv_params.interval    = NON_CONNECTABLE_ADV_INTERVAL;
...
    sd_ble_gap_adv_start(&m_adv_params);

```

## TxPowerの設定

```c
// 電波強度 -20, -16, -12, -8, -4, 0, 4 dBm から選択
#define TX_POWER_LEVEL (4)
...
    sd_ble_gap_tx_power_set(TX_POWER_LEVEL);
```

# どのように実測するか

実際にアドバタイジングインターバル/TxPowerが変化する様子を実測・可視化してみます。
（※下記方法ではmAオーダの電流値は可視化できますが、uAオーダのそれは難しいので、そのオーダを計測するにはより高性能な計測器を用意してください）

## 実測環境

- テクトロニクス TBS1052B
    - テクトロの格安オシロ。テクトロ品質レベルで5万円代は他にありません。今回の計測ではノイズ面でやや頼りなさを感じますが普段使いには十分な性能です。
![image](https://qiita-image-store.s3.amazonaws.com/0/11626/da11c32b-e6a8-8b8c-bb85-c642efffaa71.png)

- NYA-01-200 : http://nyamfg.com/nya-01/
    - 電流電圧変換モジュール。1mA を 10mV に変換してくれます。オシロで電流計測ができるようになります。
    - https://www.switch-science.com/catalog/2088/
![image](https://qiita-image-store.s3.amazonaws.com/0/11626/569d44ab-7276-685b-6675-48fea31566af.png)

- nRF51822 rev.3 SoftDevice 8.0.0



# アドバタイズのTxPowerを変化させてみる

以下のようにアドバタイジングインターバルは100msec固定で電波強度を変えてみます。

| 項目 | 値 |
|:-----------|---|
| アドバタイジングインターバル | 100 msec |
| 電波強度 | +4, 0, -4, -20 dBm |

横軸タイムスケールを100msecつまり画面の端から端まで1secです。
アドバタイズインターバルは100msecにしているので約10本のアドバタイズが立っています。
例によって100mV ⇔ 10mA で換算しています。

TxPower:**+4dBm**, Adv. Interval:**100msec**のときの波形 電流値 **16mA**
![TEK0008.JPG](https://qiita-image-store.s3.amazonaws.com/0/11626/5588911c-edad-0300-1e1d-8e2db51a1ce1.jpeg)


TxPower:**+0dBm**, Adv. Interval:**100msec**のときの波形 電流値 **10.4mA**
![TEK0009.JPG](https://qiita-image-store.s3.amazonaws.com/0/11626/99277b54-ca4d-7040-5523-49ada334cee6.jpeg)

TxPower:**-4dBm**, Adv. Interval:**100msec**のときの波形 電流値 **8.2mA**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11626/c7838563-c16f-46be-0bc7-44fd31c18c79.png)

TxPower:**-20dBm**, Adv. Interval:**100msec**のときの波形 電流値 **6.0mA**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11626/216b98c0-1dfb-fb0e-5edc-fdf552f55513.png)

| 電波強度(dBm) | ピーク電流(mA) |
|:-----------|---|
| +4 | 16 |
| 0 | 10.4 |
| -4 | 8.2 |
| -20 | 6.0 |


# 実測値からどれくらいの電池持ちになるかを見積もる
ではこの実測値から、どれくらいの電池持ちになるかを見積もっていきます。
TxPoer:+4dBm Adv. Interval:100msecのときの電池持ち時間を計算してみます。
先の結果から予測して1.1ヶ月ほどになるはずです。

1mAhは1mAを1時間流し続けることができる電池容量のことを指しますから
アドバタイズによって1時間に何mA流れたかを計算できれば良いわけです。

アドバタイズ1回分の消費電流
16(mA) * 0.002(sec) / 60(minuteに変換) / 60(hourに変換) = 0.00000888888(mAh/times)

1時間のアドバタイズ回数
10(times/sec) * 60(minuteに変換) * 60(hourに変換) = 36000(times/hour)

つまり1時間分の電流量は
0.00000888888 * 36000 = 0.32(mAh/hour)

一応、スリープ時の電流は0.8uA程度なので0.8uAhを加算
0.32 + 0.0008 = 0.3208(mAh/hour)

CR2032の電池容量が240mAhだとすると
240 (mAh) / 0.3208(mAh/hour) = 748 (hours) = **31 (days)**

おおよそ見積もり1ヶ月となりました。
先の電池寿命表で1.1ヶ月でしたから、おおよそ合っていることがわかります。

# データシートからどれくらいの電池持ちになるかを見積もる

より正確に消費電力を見積もるにはデータシートと照らし合わせるのがよいでしょう。

S110 nRF51 SoftDevice Specification v2.0 の
14.2 Advertising Event にあるFigure 17とTable 34を引用すると

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11626/23bc8043-afe8-5bf2-e90c-dc09f5dc445d.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11626/dc9a43b6-f40b-de91-9488-8884d53c3197.png)

参照：http://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.110.sds.v1.0.0%2Fs110.html&resultof=%22S110%22%20%22s110%22%20

これらの値を積分していけば消費電力を計算できることになります。

nRF51822 Product Specification v3.1の8 Electrical specificationsから読み進めるとその電流量が出てきます。

https://www.nordicsemi.com/eng/nordic/Products/nRF51822/nRF51822-PS/20339

例えば、上記 I(CPU,Flash) はTable 34にその値が出ています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11626/4049392c-1ade-237b-a63e-83dd454082f7.png)

# まとめ
さまざまなレイヤーからBLE/iBeaconの消費電力についてみてきました。



## おまけハック１：アドバタイズ 1回分の波形を拡大してみる
オシロのタイムスケールを100ms→1msの100倍に拡大してアドバタイズ1回分の波形を見てみましょう。すると面白い波形が見えてきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11626/653cbb23-1565-e336-53cf-fd6617d9a29a.png)
アドバタイズの1回分に1個の波形が出ていると思いきや、拡大すると約2msecの間に3つの山が出ています。

なぜ３つの山があるのか？

実はBLEのアドバタイズはWifiなどの電波干渉を防ぐためにCh.37,38,39の3チャネルの電波を飛ばしています。
その3チャネル分が約2msec間に送出されているというわけです。


# おまけハック２： その他Tips
以下Tips集です

- BLEデバイス間でアドバタイズが干渉し合わないよう、アドバタイズインターバルは意図的に0〜10 msecのランダムなズレを生じさせている(図中 Delay部分)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11626/8154da2c-0fc2-f302-f610-fdc3475e7aa0.png)
参考：http://www.ti.com/lit/an/swra475/swra475.pdf

- nRF51ではアドバタイズチャネルのON/OFFができる。例えばch.37だけOFFするとch.38, 39の2波だけが出力される

```c
// アドバタイジングチャネルのON/OFF
// OFFしたい場合 1
#define CH_37_OFF                   (1)
#define CH_38_OFF                   (0)
#define CH_39_OFF                   (0)
...
    m_adv_params.channel_mask.ch_37_off = CH_37_OFF;
    m_adv_params.channel_mask.ch_38_off = CH_38_OFF;
    m_adv_params.channel_mask.ch_39_off = CH_39_OFF;
...
    sd_ble_gap_adv_start(&m_adv_params);

```
ただしチャネルを停波させることによってiPhoneからは非常に見つかりにくくなるという不都合が生じるので、ここまでやるチューニングは現実的ではない。

- nRF51では書込をしたあとWinコマンドラインで"nrfjprog --pinreset"しないとDebugModeの高い消費電力のまま起動してしまうので注意

# 最後に
この消費電力ハックのノウハウは株式会社PhotosynthのAkerunで培われた情報をまとめました（計測器はより良い物を使っていますが・・・）
https://akerun.com/
今後も Photosynth Akerun をよろしくお願いします。