概要
nrf51822 に Central の機能を実装して BLE デバイスをスキャンしてみました
スキャンした際に対象デバイスの Mac アドレスと RSSI (受信信号強度) を取得してデバッグ出力してみます
環境
- Windows7 64bit
- nRF51822
- nRF51 DK
- nRF51 SDK 9.0.0
- SoftDevice S130
実装方法
今回は Peripheral ではなく Central の機能を実装するので SoftDevice のバージョンは s120 or s130 が必要になります
なので、あらかじめ上記の SoftDevice を書き込んでおいてください
実装方法は SDK に含まれる Central のサンプルコードベースで説明します
スキャンできるように初期化する
まずスキャンの方法を設定します
サンプルコードでは基本的に main メソッド内で初期化用のメソッドをコールすることで初期化を行っています
スキャンの初期化の流れは ble_stack_init
-> softdevice_ble_evt_handler_set
-> ble_evt_dispatch
-> on_ble_central_evt
になります
簡単に説明するとスキャンを実行した際に発生するイベントを on_ble_central_evt
メソッドでハンドリングする設定を行っています
このコールの流れは基本サンプルのままで OK です
これが設定されていればスキャンの基本の設定は完了です
次にハンドリングしたイベント内で実際に Macアドレスと RSSI を取得してみます
Macアドレスと RSSI を取得するロジックを追加
修正は on_ble_central_evt
メソッドだけになります
このメソッドは発生したイベント ID を取得して switch 文でイベントを分岐しています
static void on_ble_central_evt(ble_evt_t * p_ble_evt) {
uint32_t err_code;
const ble_gap_evt_t * p_gap_evt = &p_ble_evt->evt.gap_evt;
switch (p_ble_evt->header.evt_id) {
case BLE_GAP_EVT_ADV_REPORT: {
// ...
break;
}
case BLE_GAP_EVT_TIMEOUT:
// ...
break;
case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST:
// ...
break;
case BLE_GAP_EVT_DISCONNECTED:
// ...
break;
default:
break;
}
}
今回はこの中の BLE_GAP_EVT_ADV_REPORT
の switch 文を修正します
Mac アドレスと RSSI は引数として渡ってきた ble_evt_t
のポインタから取得します
取得方法は以下の通りです
ble_gap_addr_t pa = p_gap_evt->params.adv_report.peer_addr;
int8_t rssi = p_gap_evt->params.adv_report.rssi;
printf("Mac Address: %02x:%02x:%02x:%02x:%02x:%02x \r\n", pa.addr[5], pa.addr[4], pa.addr[3], pa.addr[2], pa.addr[1], pa.addr[0]);
printf("RSSI %d \r\n", rssi);
これをそのまま BLE_GAP_EVT_ADV_REPORT
の switch 文中に記載すれば OK です
Mac アドレスは LSB (下位ビットから格納する方式) になっているので、添字の大きい方から参照します
ドットや矢印でいろいろと参照していますが流れとしては
ble_evt_t
からevt.gap_evt
で GAP (General Access Profile) のイベントを取得- イベントの
params
フィールドからパラメータを参照 - パラメータの
adv_report
フィールドからアドバタイジング情報を参照 - アドバタイジング情報の
peer_addr
フィールドから Mac アドレス情報を参照 - アドレス情報の
addr[6]
フィールドが Macアドレスが格納されている配列になっている
という感じです
RSSI は adv_report から直接数値が参照できます
この辺りはリファレンスを参照すると、この構造体のこのフィールドを参照しているという流れがわかると思います
スキャンを開始する
これもサンプルをそのまま使っているのであれば特に変更する箇所はありません
main メソッド内 scan_start
というメソッドをコールしていれば Central のスキャンを開始することができます
int main(void) {
uint32_t err_code;
bool erase_bonds;
// Some Initialize ...
ble_stack_init();
// Some Initialize ...
// Some Initialize ...
scan_start();
// Some Initialize ...
for (;; ) {
power_manage();
}
}
scan_start
を辿ってみるとわかると思いますが結構いろいろな設定をしています
スキャンの間隔やホワイトリストを使って、信頼するデバイスだけスキャンするようにするとか、タイムアウトをどうするかなど設定できます
興味があれば、scan_start メソッドのサンプルとリファレンスを見ながらいろいろとパラメータチューニングしてみてください
コードが記載できたら Keil でビルドして nRFgo Studio でアプリケーションを焼きこんでみましょう
焼きこみが完了すれば自動的に nRF51 DK が BLE デバイスとなりスキャンを開始します
試す
アドバタイズしている BLE デバイスは結構街中に飛んでいるのでスキャンを開始すればデバイスが見つかるかもしれません
ない場合はスマホアプリで Peripheral になれるアプリがあるので、それを使ってみてください
自分は SensorTag CC2650 を使いました
デバッグは nRF51 DK を PC に USB で接続して TeraTerm でシリアルモニタをすればいいと思います
ボーレートは 38400 を設定してください
今回のサンプルは printf
しているだけなので、デバイスが見つかればそのまま出力されると思います
最後に
コンシューマ向けの BLE デバイスは基本は Peripheral のみが実装されており、iPhone とか Android などのスマホが Central になっています
nrf51822 は Central にもなることでできるのでちょっとおもしろい実装ができます
nrf51822 には pstorage という仕組みもあってデバイス上にデータも保存できるので、スキャンした情報を保存しておくこともできます
pstorage の話もどっかでできればなぁと思っています
あと、サラッと書いたデバッグの方法とかも書いたほうがいいかなと思っています
0 件のコメント:
コメントを投稿