誰でもすぐにBLE通信機器が作れるnRF52用サンプルプログラム

# 記事の概要

BLE通信機器の開発に使える以下のサンプルの使用方法について解説します。
https://github.com/matsuikosuke/nRF52_Central_and_Peripheral

BLE通信モジュールにはNordicのnRF52シリーズを使用します。
サンプルはnRF52832を対象にしていますが、メモリや端子設定が少し異なるだけで他のnRF52シリーズにも使用できます。

BLE通信についての知識はあるものとみなして解説します。
BLE通信について知りたい方は、以下の本などをご参照ください。

[Bluetooth Low Energyをはじめよう](https://www.amazon.co.jp/Bluetooth-Low-Energy%E3%82%92%E3%81%AF%E3%81%98%E3%82%81%E3%82%88%E3%81%86-Make-PROJECTS/dp/4873117135/ref=sr_1_2?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&dchild=1&keywords=BLE&qid=1631890281&s=books&sr=1-2)

# （2022年5月4日追記）注意事項
本サンプルでCentral機能を有効にするとDFU機能が無効になることが分かりました。
原因はDFU用のUUIDをCentral用のUUIDが上書きしてしまうためです。
Peripheralだけを使用する場合、PeripheralとCentralのSCAN機能のみ使用する場合は、DFU機能が使用できます。



# 準備

## 開発環境の構築

開発環境は無料で用意できます。
開発環境の構築方法については以下の記事をご参照ください。

[Nordic社製BLEの開発環境構築と動作確認](https://qiita.com/Kosuke_Matsui/items/5d61ce77e928b9f117cc)

## nRF52モジュールの購入

個人での電子工作では開発ボードを使用するのが便利です。
[NRF52-DK](https://www.digikey.jp/products/ja?keywords=NRF52-DK)のようなNoridicが提供する各種ボードは日本の技適を取得していないので使用が難しいです。
ですが、技適取得済みの開発ボードとして、以下があります。

- [nRF52832 MDBT42Q 評価ボード](https://www.switch-science.com/catalog/5526/)
- [EBSKBNZWB](https://www.digikey.jp/products/ja?keywords=EBSKBNZWB)
- [Adafruit Feather nRF52840 Express](https://www.switch-science.com/catalog/5400/)
- [SparkFun Pro nRF52840 Mini](https://www.switch-science.com/catalog/5508/)

他にも多くの開発ボードがあります。
配線が少し面倒ですが小型モジュールを使う手もあります。

- [EYSHCNZWZ(nRF52832)｜無線モジュール｜製品情報｜太陽誘電株式会社](https://www.digikey.jp/product-detail/ja/taiyo-yuden/EYSHCNZWZ/587-5979-1-ND/7918039)
- [EYSKBNZWB(nRF52840)｜無線モジュール｜製品情報｜太陽誘電株式会社](https://www.digikey.jp/product-detail/ja/taiyo-yuden/EYSKBNZWB/587-6258-1-ND/9825399
)

これらはDigi-keyなどで1個1,500円前後で購入できます。
使用方法については以下を参照ください。

[表面実装部品の太陽誘電BLEモジュールを強引に電子工作で利用する方法](https://qiita.com/Kosuke_Matsui/items/8132bee58323126a0cd7)

## サンプルプロジェクト

### ダウンロード
今回用意したサンプルはオリジナルのBLEサービスです。
以下からダウンロードしてください。

https://github.com/matsuikosuke/nRF52_Central_and_Peripheral

このサンプルは**SDK 17.0.2**とソフトデバイス**s132_nrf52_7.2.0**を使用しています。
SDKとソフトデバイスのダウンロードと使用方法については、先ほどに紹介した[Nordic社製BLEの開発環境構築と動作確認：SDKとソフトデバイス](https://qiita.com/Kosuke_Matsui/items/5d61ce77e928b9f117cc#sdk%E3%81%A8%E3%82%BD%E3%83%95%E3%83%88%E3%83%87%E3%83%90%E3%82%A4%E3%82%B9)をご参照ください。

現在の最新のSDKは17.1.0ですが、そちらでも問題なく使用できると思われます。
今後もSDKやソフトデバイスが更新されるにつれて、サンプルはそのままでは使用できなくなる可能性があります。

ダウンロードしたファイルは適当な名前をつけたフォルダ、例えばtest_projectに入れて、SDKの以下の階層に置いてください。
別の階層に置く場合は、ライブラリなどへのリンクを見失ってしまうので、自分の環境に合わせてリンク先を修正してください。

```
~nRF5_SDK_17.0.2_d674dde\examples\ble_central_and_peripheral\test_project
```

開発環境にはSEGGER Embedded Studioを使用しています。
以下の階層にあるtest_s132.emProjectを開いて、修正、ビルド、デバックをしてください。

```
~\nRF5_SDK_17.0.2_d674dde\examples\ble_central_and_peripheral\test_project\pca10040\s132\ses\test_s132.emProject
```

### 機能
サンプルのBLEサービスは、CentralとPeripheralの両方の機能を持ちます。
サービス名はorangeとしています。
自分用のサービスに作り替える時は、orangeという単語を自分のサービス名に置き換えてください。

使用するのがCentral機能かPeripheral機能のどちらか１つでいい場合は、関係ない部分を削除するか、Central機能だけを使用したい場合はアドバタイジング発信を停止し、Peripheral機能だけを使用したい場合はスキャンをしないようにしてください。
各種関数の設定方法やどれがCentral機能やPeripheral機能に関する部分なのかは以下を参照ください。

- [BLEモジュールnRF52シリーズにおけるCentral機能とPeripheral機能の両方を実装する仕組み](https://qiita.com/Kosuke_Matsui/items/13da1b5df710b4b0a3ab)
- [BLEモジュールnRF52シリーズにおけるCentralサービスを実装する仕組み](https://qiita.com/Kosuke_Matsui/items/f0ae02aa1fdc5494c332)
- [土日で出来るBLEリモコン](https://qiita.com/matsui_685/items/af563f8f2a64e2f8e35d)
    - Peripheralサービスの実装はこの記事中で解説しています。

また、サンプルはDFU機能を持っています。
DFUとは、JTAGツールなどを使用せずに、BLE通信によりファームウェア更新する機能のことです。
詳細は以下を参照ください。

- [nRF52のDFU試験1](https://qiita.com/Kosuke_Matsui/items/7ab5235b4cfa61a398ba)
- [nRF52のDFU試験2](https://qiita.com/Kosuke_Matsui/items/ea9309ffaf75925b671e)

## ビルド済ファイル
自分でBLEサービスを作成するにはプロジェクトを開いて修正した上で、ビルドやデバッグをしていただく必要があります。

ですが動作確認だけしたいという場合は既にビルド済みのファイルを書き込んで使用ください。
書き込み方法は[Nordic社製BLEの開発環境構築と動作確認：サンプルプログラムのビルドと書込み](https://qiita.com/Kosuke_Matsui/items/5d61ce77e928b9f117cc#%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E3%81%AE%E3%83%93%E3%83%AB%E3%83%89%E3%81%A8%E6%9B%B8%E8%BE%BC%E3%81%BF)を参照ください。

```
~\nRF5_SDK_17.0.2_d674dde\examples\ble_central_and_peripheral\test_project\Output\all.hex
```

このビルドファイルはDFU機能を持っているので、このファイルを書き込んだ機器はnRF ToolBoxアプリなどによりファームウェア更新ができます。


# サンプルプロジェクトの動作

## Peripheral機能の確認
Nordicが無償で配布しているアプリnRF Connectを使用してPeripheral機能を確認します。

ファームウェアを書き込んだnRF52に電源を供給するとアドバタイジングパケット発信を開始します。
SCANでORANGE_DEVICEを探してください。
<img width="30%" alt="SCAN.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/dac07753-9bdf-8355-3ca4-7756208f5f16.png">

CONNECTを選択するとサービス名とCharacteristicが確認できます。
Notifyの横のアイコンをクリックして受信可能に設定してください。
<img width="30%" alt="BLE接続.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/9a2fcaf4-1214-30f3-9e93-66d077f4874d.png">

### NotifyとWrite
サンプルは`peripheral_write_notification_test`関数により、Writeで受信したデータをNotifyでそのまま送り返します。

スマホからwriteデータを送信します。
writeの横のアイコンをクリックしてデータ入力画面を開き、適当な送信データを入力してSENDを押してください。
<img width="30%" alt="write.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/7a3b41d1-7962-24c0-db0c-52d5fdde3c57.png">

送信したのと同じデータがNotifyに返ってきているのが分かります。
<img width="30%" alt="write_notify.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/756b1f71-0f6e-2ca3-f84f-2c62a00eb1e2.png">

### Indicate
IndicateはNotifyと同様の方法で確認できます。
サンプルは`peripheral_write_indication_test`関数により、Writeで受信したデータをIndicateでそのまま送り返します。

Notifyとの動作の違いはIndicate送信後にACK応答が返ってくることです。
ACK応答は`BLE_GATTS_EVT_HVC`イベントにより受信できます。

### Read
ReadはCentaral側からの要求に対してPeripheral側がデータを返します。
Readの横のアイコンをクリックすることでRead要求を実行します。
するとReadデータが返ってくることが分かります。
<img width="30%" alt="read.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/27baac5a-a331-4002-fa4a-fdd994d82407.png">

## Central機能の確認
デバッガを使用してCentral機能を確認します。
DFU機能が有効ですとデバックできないのでdefine.hの`#define WITHOUT_DFU`を有効化してください。

この試験をするにはnRF52の開発ボードが2台必要になります。
両方ともにサンプルを書き込みます。
1台をデバッガと接続してCentral機能を確認します。
もう1台がCentral側にならないように、そちらに書き込むファームウェアは、define.hの`#define WITHOUT_SCAN`を有効化してPeripheral機能のみ有効化した方が便利です。

### アドバタイジングパケットのスキャン
Central側はアドバタイジングパケットとスキャンパケットをスキャンしています。

アドバタイジングパケットにはUUIDの77bfabc0-b245-d7d5-baaf-7cb4aec8129cが含まれていることが分かります。
![アドバタイジングパケット.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/8a5b3d2d-367d-852b-5a94-9dbf908a3161.png)

スキャンパケットにはDevice名のORANGE_DEVICEが含まれていることが分かります。
![スキャンパケット.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/96a42651-0074-7462-2f20-0dda7edd3de2.png)

BEACONの検知を行う場合はBLE接続は行わずに、このアドバタイジングパケットだけを取得します。

### NotifyとWrite
サンプルの`central_write_notification_test`関数は10秒周期でWriteデータを送信します。
Peripheral側はとWrite
サンプルは`peripheral_write_notification_test`関数によりWrite受信したデータをNotifyで送信します。

デバッガを確認すると送信したデータと同じデータがNotify受信していることが分かります。
![centaral_notify.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/ee38e495-dec4-abb7-edeb-4e9b54c9665d.png)

### Indicate
IndicateはNotifyと同様の方法で確認できます。
サンプルは`peripheral_write_indication_test`関数によりWrite受信したデータをIndicateで送信します。

### Read
サンプルの`central_read_test`関数は10秒周期でread要求します。

デバッガを確認するとread要求後にreadデータを受信していることが分かります。
![centaral_read.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/82ab4f16-8ace-cd59-2b04-e67491476455.png)


## DFU機能の確認
Nordicが無償で配布しているアプリnRF ToolBoxを使用してDFU機能を確認します。

まず以下のzipファイルをスマホに保存してください。
私はいつもスマホにメールで添付送信して、スマホのフォルダにダウンロードしています。

```
~\nRF5_SDK_17.0.2_d674dde\examples\ble_central_and_peripheral\test_project\Output\test_app.zip
```

このzipファイルの生成方法については[nRF52のDFU試験1](https://qiita.com/Kosuke_Matsui/items/7ab5235b4cfa61a398ba)を参照してください。
実例として私の環境で実行しているコマンドを以下に記載します。
set命令を用いて、よく使うフォルダ名や定数を定義した方がいいのでしょうが、Dドライブに入れたフォルダをset命令で定義するとエラーになってしまうので諦めました。

```
nrfutil settings generate --family NRF52 --application D:\BLE\nRF5_SDK_17.0.2_d674dde\examples\ble_central_and_peripheral\test_project\pca10040\s132\ses\Output\Release\Exe\test_s132.hex --application-version 1 --bootloader-version 1 --bl-settings-version 1 D:\BLE\nRF5_SDK_17.0.2_d674dde\examples\ble_central_and_peripheral\test_project\Output\settings.hex 

mergehex --merge D:\BLE\nRF5_SDK_17.0.2_d674dde\examples\ble_central_and_peripheral\test_project\softdevice\s132_nrf52_7.2.0_softdevice.hex D:\BLE\nRF5_SDK_17.0.2_d674dde\examples\ble_central_and_peripheral\test_project\secure_bootloader\pca10040_s132_ble\ses\Output\Release\Exe\secure_bootloader_ble_s132_pca10040.hex --output D:\BLE\nRF5_SDK_17.0.2_d674dde\examples\ble_central_and_peripheral\test_project\Output\SD_BL.hex

mergehex --merge D:\BLE\nRF5_SDK_17.0.2_d674dde\examples\ble_central_and_peripheral\test_project\Output\SD_BL.hex D:\BLE\nRF5_SDK_17.0.2_d674dde\examples\ble_central_and_peripheral\test_project\pca10040\s132\ses\Output\Release\Exe\test_s132.hex --output D:\BLE\nRF5_SDK_17.0.2_d674dde\examples\ble_central_and_peripheral\test_project\Output\SD_BL_APP.hex

mergehex --merge D:\BLE\nRF5_SDK_17.0.2_d674dde\examples\ble_central_and_peripheral\test_project\Output\SD_BL_APP.hex D:\BLE\nRF5_SDK_17.0.2_d674dde\examples\ble_central_and_peripheral\test_project\Output\settings.hex --output D:\BLE\nRF5_SDK_17.0.2_d674dde\examples\ble_central_and_peripheral\test_project\Output\all.hex

del D:\BLE\nRF5_SDK_17.0.2_d674dde\examples\ble_central_and_peripheral\test_project\Output\SD_BL.hex
del D:\BLE\nRF5_SDK_17.0.2_d674dde\examples\ble_central_and_peripheral\test_project\Outputut\SD_BL_APP.hex
del D:\BLE\nRF5_SDK_17.0.2_d674dde\examples\ble_central_and_peripheral\test_project\Output\settings.hex

REM make image
nrfutil pkg generate --hw-version 52 --application-version 1 --application D:\BLE\nRF5_SDK_17.0.2_d674dde\examples\ble_central_and_peripheral\test_project\pca10040\s132\ses\Output\Release\Exe\test_s132.hex --sd-req 0x0101 --key-file D:\BLE\nRF5_SDK_17.0.2_d674dde\examples\ble_central_and_peripheral\test_project\private.key D:\BLE\nRF5_SDK_17.0.2_d674dde\examples\ble_central_and_peripheral\test_project\Output\test_app.zip
```

DFUおよびzipファイル生成方法については以下の記事を参照しています。

- [nrf52でOTAする(Secure Bootloader+DFU)](https://qiita.com/chabose/items/dab0b12f460f85918c8d)
- [nRF52でBLEデバイスを開発する（２）OTAアップデート Buttonless DFUとSecure DFU](https://qiita.com/jiro-aqua/items/97c8ec6910d584281b7a)

ここでDFU機能を持つhexファイルが既にnRF52832に書き込まれているとします。
nRF ToolBoxからOrangeDeviceにBLE接続し、zipファイルを選択してDFU実行します。
成功画面で終了するのが確認できるはずです。

なお、皆様が私のサンプルを元にしてファームウェアを作成した際は、private keyとpublic keyを再生成して、secure_bootloaderの以下のプロジェクトを開き、再ビルドするのを忘れないようにご注意ください。

```
~\nRF5_SDK_17.0.2_d674dde\examples\ble_central_and_peripheral\project\secure_bootloader\pca10040_s132_ble\ses\secure_bootloader_ble_s132_pca10040.emProject
```

もしこの変更をしなければ、GitHubに公開鍵も秘密鍵も置いてあるので、世界中の誰でも皆様の作成したファームウェアを自由に上書きできてしまいます。


# 消費電力の測定
アドバタイジングパケットを発信しているだけの時とアドバタイジングパケット発信とスキャンの両方をしている時の消費電力を比較します。

消費電力はPower Profiler Kitで測定しました。測定方法は以下を参照ください。
[Power Profiler KitでBLEの消費電力を測定する](https://qiita.com/Kosuke_Matsui/items/2860ef2c565bd9d72665)

## スキャン機能無効時
アドバタイジングパケットを発信しているだけの時は平均して4mAを消費しています。

![SmartLock_Central機能あり_SCAN無効時消費電力2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/1fae7d69-0433-dba5-9973-c22b95540f1d.png)


## スキャン機能有効時
アドバタイジングパケット発信と同時にスキャンも実行している時には平均して6.5mAを消費しています。

![SmartLock_Central機能あり_SCAN有効時消費電力.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150620/24738a74-7e6f-65cf-55a7-61f37fd87a9c.png)

BLE通信は消費電力の大きな処理をCentral側に任せることでPeripheral機器の消費電力を低く抑えています。
Central機能をBLE機器に持たせる場合はスキャンを常時行っていると、BLE通信の利点である低消費電力を損なうことにご注意ください。

# その他
サンプルにはAuthority Writeの機能を実装しているものの、まだ実際に動作を確認していません。
また、Central側が複数のPeripheral機器とBLE接続した場合、それらを識別する機能も実装していません。

今後、これらの機能の確認と実装をする予定です。