Bluetooth評価ボード「Target Board for RX23W」によるBLE Peripheralデバイスの作成

こんにちは。
この記事は、[グロースエクスパートナーズ Advent Calendar 2021](https://qiita.com/advent-calendar/2021/gxp) 13日目の記事です。
冬はイベント盛りだくさんで、なお且つ美味しいものに溢れる季節ですね。
余計なことを気にせず食事を楽しみたいものです。

#はじめに
最近、BLEでデバイスと通信するスマホアプリの開発に関わるようになりました。
このような他の機器と通信を行うソフトウェア開発においては、
検証・試験・問題切り分け等のために、自由に制御出来る対向装置は必要不可になります。

今回は、BLE通信でスマホアプリに体重を送信する疑似体重計を作ってみます。

# デバイス選定

まず、体重計を騙る通信を実現するデバイスの選定をします。
調べてみるといろいろ選択肢があり、Qiita内にも沢山記事が存在します。
私はRenesas社様製 Target Board for RX23Wを選定しました。

選定理由は、メ〇カリで売っていたのを衝動買いしたためになります。
こういうモノも売ってたりするのは驚きですね。

![2021-12-10_12h52_18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2318306/f4c21725-2f5b-e9e8-dca5-8e294e900c9c.png)



# メリット・デメリット
てきとーな選定理由ですが、明確なメリットも存在します

+ 技適マーク付き(**重要!**)
+ USBケーブルでPCに繋ぐだけで開発できる(別途デバッグツールやROMライターが不要)
+ Bluetoothチップの評価ボードであるため、深く細かい動作も実装可能
+ BLE機能を実装するためのサンプルコードや、ライブラリが存在する
    + SIG標準プロファイルは組み込むだけで実現できたりする
+ 公式ドキュメントが日本語で提供されており難易度が低い
+ スマートフォンやPCを対向装置とするより安く数が揃えやすい
  (実売 単価 6000～7000円台)


逆にデメリットも存在します。

+ 公式ドキュメント以外の情報が少ない
+ コンパイラ(CC-RX)が有償で、60日を過ぎると制限により生成ROMサイズに上限が発生する。
    + 無償のコンパイラとしてGCCも選択可能ですが、後述の"QE for BLE"がGCC未対応となっております
    + ~~ただし検証で使うレベルにでは恐らく問題なさそう~~ BLE関連モジュールを組み込むと、生成ROMサイズが制限の128kを超える
+ 他にもっと単価の安い評価ボードがある(それらはメリットで挙げた点が満たせなかったりで、一筋縄にはいかない・・・)

# 事前準備

+ Bluetooth評価ボード Target Board for RX23W
+ USB Micro B-TypeA コネクタ ケーブル
+ スマートフォン(Pixel 3a, Android 11)
    + nRF Connect(BLE通信検証アプリ)
+ PC(Windows 10)


![2021-12-10_11h36_24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2318306/6930f8b6-14e2-61b9-feef-d246c33397cf.png)


# 参考ドキュメント
ドキュメント集めにRenesas社様WEBサイトから、RX23W 製品のページを漁ってみます。

[RX23W](https://www.renesas.com/jp/ja/products/microcontrollers-microprocessors/rx-32-bit-performance-efficiency-mcus/rx23w-32-bit-microcontrollers-and-module-bluetooth-5-iot-endpoint-devices-system-control-and-wireless)
[Target Board for RX23W](https://www.renesas.com/jp/ja/products/microcontrollers-microprocessors/rx-32-bit-performance-efficiency-mcus/rtk5rx23w0c00000bj-target-board-rx23w)

今回の記事を書くにあたり、以下のドキュメントを参考にしました。

+ RX23Wグループ Target Board for RX23W クイックスタートガイド
+ RX23W グループ Bluetooth Low Energy アプリケーション開発者ガイド
+ RX23Wグループ BLE モジュールFirmware Integration Technology
+ RX23Wグループ Bluetooth Low Energyプロファイル開発者ガイド



#評価ボード動作確認
公式ドキュメント**RX23Wグループ Target Board for RX23W クイックスタートガイド**を参考に動作確認を実施します。

詳細は公式ドキュメントが手取り足取り教えてくれるので割愛しますが、
ざっくり以下のことが確認出来ます。

+ 配線, 電源投入～起動確認
+ BLE通信確認
+ PC-評価ボード間シリアル通信
+ ファームウェア書き込み
+ Bluetooth Test Tool Suite導入

ここで導入されたBluetooth Test Tool Suiteは、Bluetoothの各種動作検証できるテストツールになります。
ちょっとした実験でしたら、これを使用すれば事足りてしまいそうですね。



# ソフトウェア開発環境導入

WindowsPCに、以下のソフトウェアを導入します。

[e2 studio](https://www.renesas.com/jp/ja/software-tool/e-studio)
統合開発環境e2 studio 2021-10 Windows用インストーラ


[スマート・コンフィグレータ](https://www.renesas.com/jp/ja/software-tool/smart-configurator)
RXスマート・コンフィグレータV2.11.0

[QE for BLE](https://www.renesas.com/jp/ja/software-tool/qe-ble-development-assistance-tool-bluetooth-low-energy)
QE for BLE[RX]	V1.1.0
(e2 studioインストール時にオプションでも導入できます)



# ベースソフトウェア環境の作成

プロジェクト作成・各種コンポーネントの組み込み・ビルド設定等を行い、
ベースとなるソフトウェア環境を作成します。


公式ドキュメント**RX23Wグループ BLE モジュールFirmware Integration Technology**に従い、4.1 新規プロジェクトの作成 ～ 4.8デバッグ設定の手順を実施します。

ただし、今回試した手順は、以下の点に相違があります。

+ プロジェクト作成時
    + RTOSは"None"に設定
    + Target Boardに"TargetBoardRX23W"を選択する(最初選択肢に出ないため、Download additional boardsからダウンロードします)
    + Hardware Debug 構成を生成で、"E2 Lite(RX)"を選択
+ スマート・コンフィグレータ コンポーネント組み込み
    + バージョンアップが可能なコンポーネントのバージョンを上げる
    + IRQ7は利用しない(RTOSを使わないため)

Config_BLE_PROFILEにエラーマークが出ますが、とりあえず今の段階では問題ありません。
この状態で、ビルド→デバッグを実施することで、評価ボードが立ち上がります。



# Lチカ
このままでは外見上動いていることが確認できないので、LEDを点滅させてみます。

app_main.cに以下の制御を実装します。

+ ボード初期化関数コール
+ Lチカ制御関数 L_chika()に実装
+ L_chika()をハンドラ関数とする周期実行タイマー生成

<details><summary>修正内容詳細</summary><div>
関数プロトタイプ宣言

```c
/******************************************************************************
 User function prototype declarations
*******************************************************************************/
/* Start user code for function prototype declarations. Do not edit comment generated here */
void L_chika(void);
/* End user code. Do not edit comment generated here */
```

app_main()

```c
void app_main(void)
{
    /* Initialize BLE */
    R_BLE_Open();

    /* Initialize host stack and profiles */
    ble_init();

/* Hint: Input process that should be done before main loop such as calling initial function or variable definitions */
/* Start user code for process before main loop. Do not edit comment generated here */
    R_BLE_BOARD_Init();
    R_CMT_CreatePeriodic(1, L_chika, NULL);
/* End user code. Do not edit comment generated here */

    /* main loop */
    while (1)
```

Ｌチカ制御関数 L_chika()

```C
/******************************************************************************
 User function definitions
*******************************************************************************/
/* Start user code for function definitions. Do not edit comment generated here */
void L_chika(void)
{
	static bool LED1 = 1;
	static bool LED2 = 0;

	LED1 = !LED1;
	LED2 = !LED2;

	R_BLE_BOARD_SetLEDState(BLE_BOARD_LED1, LED1);
	R_BLE_BOARD_SetLEDState(BLE_BOARD_LED2, LED2);
}
/* End user code. Do not edit comment generated here */
```
</div></details>

追加コードは、"/* Start user code...." と　"/* End user code..."の間に記述します。
ここ以外に記述すると、再度ソースを自動生成したときに消えてしまうので注意が必要です。
もしうっかり消してしまった場合、trashフォルダに残っているので、そこから復旧します。



# BLE制御実験

## 作るもの

作成する疑似体重計の仕様は以下の通り。

+ 体重を送信するプロトコルとして、SIG標準 Weight Scale Serviceを実装する
+ 評価ボード上のスイッチを押すたび、Indicateで体重を送る
+ その際コッソリ100gほど体重を減らす
+ 体重初期値は面倒なのでハードコーディング

## BLE関連設定

公式ドキュメント **RX23Wグループ Bluetooth Low Energyプロファイル開発者ガイド**を参考に構築します。

スマートコンフィグレータ → コンポーネント → Config_BLE_PROFILE
で設定を行います。


### Weight Scale Serviceコンポーネント追加

Profileタブ
ボタン(追加) → サービスを追加 → Weight Scale Profile


### アドバタイズの設定

Peripheralタブ → Advertising Data

+ Local Name設定
  Local Nameにチェックを入れ、
  Local Nameを選択 → Complete local name に"TJK-1213"を入力
  ※ TJKは 体(T) 重(J) 計(K)の意味

+ Service Solicitation UUIDS設定
  Service Solicitation UUIDSにチェックを入れ、
  Service Solicitation UUIDS  →  Weight Scale Serviceにチェック

### コード生成
「コードの生成」を実行
これだけでBLE体重計の通信が可能になります。




## 体重送信(&減少)モジュール作成

独自制御部分を作成します。以下の機能を有します。

+ 評価ボード上スイッチ押下でIndicateを飛ばす
+ その際元の体重から100g減らす

新規ファイルLoseWeight.hとLoseWeight.cをプロジェクトに追加します。
smc_gen配下に作成すると、クリーン時に削除されますので他の場所に作成して下さい。

<details><summary>修正内容詳細</summary><div>

LoseWeight.h

```c
#ifndef LOSEWEIGHT_H_
#define LOSEWEIGHT_H_

#include <stdint.h>

void lw_init(uint16_t _conn_hdl);
void lw_indicate_lose_weight(void);

#endif /* LOSEWEIGHT_H_ */
```
LoseWeight.c

```c
#include "LoseWeight.h"
#include "board/r_ble_board.h"
#include "r_ble_wss.h"

static bool init = 0;
static uint32_t my_weight = 77600;
static uint16_t conn_hdl;

#define GRAM_TO_WSS_WEIGHT(g) ((g) / 5)


void lw_init(uint16_t _conn_hdl)
{
	init = 1;
	conn_hdl = _conn_hdl;
}

static void indicate_weight(uint32_t weight)
{
	if(!init){
		return;
	}

	st_ble_wss_weight_measurement_t value;
    value.is_bmi_height_present = 0;
    value.is_measurement_in_imperial_units = 0;
    value.is_timestamp_present = 0;
    value.is_user_id_present = 0;
    value.weight = GRAM_TO_WSS_WEIGHT(weight);

    R_BLE_WSS_IndicateWeightMeasurement(conn_hdl, &value) ;
}

void lw_indicate_lose_weight(void)
{
    my_weight -= 100;
    indicate_weight(my_weight);
}
```

</div></details>

## Weight Scale Serviceコールバック実装

Weight Scale Service(WSS)にアクセスがあると、app_main.c wss_cb()がコールされます。
引数として渡される情報から、必要情報を保持します。




<details><summary>修正内容詳細</summary><div>

indicateにp_data->conn_hdlが必要になるので保持します。
Typeによって制御を書く必要がありそうですが端折ります。

app_main.c 

```c
static void wss_cb(uint16_t type, ble_status_t result, st_ble_wss_evt_data_t *p_data)
{
/* Hint: Input common process of callback function such as variable definitions */
/* Start user code for Weight Scale Service Server callback function common process. Do not edit comment generated here */
    if(p_data != NULL){
        lw_init(p_data->conn_hdl);
    }
/* End user code. Do not edit comment generated here */

    switch(type)
    {

```

</div></details>

## 評価ボードスイッチ押下でIndicateの送信

スイッチ押下 割り込みハンドラに、Indicate送信制御を登録します。
割り込みハンドラで通信制御呼び出すのはダメかも？
と思わないでもないですが、
とりあえず動くところを見るために気が付かなかったことにします。

<details><summary>修正内容詳細</summary><div>

```c
void app_main(void)
{
    /* Initialize BLE */
    R_BLE_Open();

    /* Initialize host stack and profiles */
    ble_init();

/* Hint: Input process that should be done before main loop such as calling initial function or variable definitions */
/* Start user code for process before main loop. Do not edit comment generated here */
    R_BLE_BOARD_Init();
    R_CMT_CreatePeriodic(1, L_chika, NULL);
    R_BLE_BOARD_RegisterSwitchCb(BLE_BOARD_SW1, lw_indicate_lose_weight);
/* End user code. Do not edit comment generated here */

```
</div></details>







# 動作確認
スマートフォン nRF Connectで動作確認をします。

## アドバタイズ確認

Scanを実施しアドバタイズを確認。
設定したComplete Local Name "TJK-1213"と、
Weight Scale ServiceのUUID(0x181D)が見えています。

![2021-12-09_19h48_20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2318306/49229f7a-9f9b-7c71-8147-d36462cfbd7b.png)

  
## サービス確認

接続してサービスの確認。
しっかりWeight Scale Serviceが見えています。

![2021-12-09_19h49_00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2318306/f880d5fc-bfb3-d1c9-4682-f4fddb403c95.png)

## Indicate送信確認
評価ボードのスイッチ押下で、(100g減った)体重が送信されました。

![2021-12-09_19h50_37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2318306/e1ad01fe-ce29-da30-482f-a35924c5b9ca.png)

## 連打連打！

すごいいきおいでたいじゅうがへる！！！
やったぞ！てきせいたいじゅうだ！

![2021-12-09_19h51_21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2318306/e9ccd6e6-d18f-62a5-39f5-3009f4c1ef6f.png)


# おわりに

環境構築からLチカするまでは、それなりに時間がかかりましたが、
そこからBLE通信の実現はあっという間に実現できました。
特にSIG標準Serviceの実装は、非常に楽できると感じました。
一度立ち上げてベースを作ってしまえば、後々少ない作業量で様々な用途に使えそうです。

これで年末年始は気持ちよく暴飲暴食できます。