2015年7月9日木曜日

BluetoothSMARTデバイスをmbed で開発する(8)


はじめに

mbed nRF51822 に新機能が追加されました。今回は 2015年5月に追加された新機能についてAPI仕様や使用方法について紹介いたします。



関連記事
BluetoothSMARTデバイスをmbed で開発する(1)
BluetoothSMARTデバイスをmbed で開発する(2)
BluetoothSMARTデバイスをmbed で開発する(3)
BluetoothSMARTデバイスをmbed で開発する(4)
BluetoothSMARTデバイスをmbed で開発する(5)
BluetoothSMARTデバイスをmbed で開発する(6)
BluetoothSMARTデバイスをmbed で開発する(7)

ARMは、ARM Limited(またはその子会社)のEUまたはその他の国における登録商標です。mbedは、ARM Limited(またはその子会社)のEUまたはその他の国における商標です。All rights reserved.

注意事項 - 本記事に掲載されているソースコードについて

2015年の後半に次世代 mbed である mbed OS がリリースされるというアナウンスが出ています。 mbed OSでは新たに Bluetooth スタックのサポートが追加され API が大幅に変更されることが予測されます。 mbed OS上では本記事の内容が利用できなくなる可能性がありますので予めご了承ください。


お知らせ - またAPI変更が行われました

今回の記事にも関連しますが、mbed nRF51822において新しい機能を追加するにあたり既存のAPI にも変更が行われています。

mbed BLE定義
インクルードファイルとクラス名が変更となっています
/* old API */
#include "BLEDevice.h"
BLEDevice ble;

/* new API */
#include "BLE.h"
BLE ble;

接続コールバック関数
引数がGap::ConnectionParams_t構造体に集約されました
/* old API */
void ConnectionCallback(Gap::Handle_t handle, Gap::addr_type_t type, const Gap::address_t addr,Gap::addr_type_t addr_type_townAddrType, const Gap::address_t ownAddr, const Gap::ConnectionParams_t *params)

/* new API */
void ConnectionCallback(const Gap::ConnectionCallbackParams_t *params)

接続タイムアウトコールバック関数
引数にGap::TimeoutSource_t構造体が追加されました
/* old API */
void ConnectTimeoutCallback(void)

/* new API */
void ConnectTimeoutCallback(Gap::TimeoutSource_t source)

当ブログに掲載されていた記事についても逐次改定を行っていく予定です。



新しい Softdevice 「S130」

nRF51 Softdeviceには次のような種別があり mbed nRF51822 はデビュー当初から S110というBluetooth ペリフェラル専用のSoftdeviceが使われ続けていました。ところが 2015年5月の更新から Bluetoothセントラル対応の Softdevice S130 が導入されています。S130自体は今年発表されたばかりなので、mbed としてはホットな機能追加ということになります。

nRF51 シリーズのSoftdevice
S110 - ペリフェラル専用
S120 - セントラル専用(8台までのペリフェラルが接続可)
S130 - セントラル/ペリフェラル両用 (ホスト1台、ペリフェラル3台まで接続可)
S210(注) - ANT+
S310(注) - ANT Slave & BLE Peripheral
※ nRF51422 のみ対応

お手持ちの環境で SoftdeviceがS130にアップグレードされているかどうかは mbedのワークスペースから次のフォルダ内容を表示することにより確認することができます。Softdeviceのバイナリはmbedライブラリ内に内包されているため直接見ることが出来ませんが、依存関連ファイルを見ることにより確認が可能です。softdeviceフォルダ内にs110フォルダがあれば古いSoftdevice 、同フォルダに s130というフォルダがあれば新しい Softdeivce が使用されています。

左側の図では s110 が使用されるようになっていますが nRF51822フォルダ部分に更新を促すマークが出ています。
マークに従ってnRF51822フォルダに更新を掛けることにより s130 へ移行されます。
なお nRF51822フォルダを更新した場合は上位ライブラリとの互換性が失われますので、同時にBLE_API とmbed フォルダについても更新を行うようにしてください。



追加されたBLE関連API

5月のアップデートにて前途の S130 Softdeviceが導入されたことに合わせて mbed nRF51822にも Bluetooth セントラルを利用するためのAPIが追加されています。

https://developer.mbed.org/teams/Bluetooth-Low-Energy/code/BLE_API/rev/3201f029c2eb
5/11頃からソースコードのコミットが始まり、数回API仕様の変更を経て次のようなインターフェイスに落ち着きました



追加された機能は BLEデバイスの Advertisingパケットをスキャンする関数がメインです。
Android 4.4(API 19)でいうところの startLeScan()にあたる機能になります。
またスキャン停止 stopScan()、動作パラメータ設定 setScanParams() が追加されています。
なお5月のアップデートでは GATT接続に必要なAPIは実装されておらず、6月以降のアップデートにて順次機能追加が行われているところです。

・スキャン開始

ble_error_t startScan(Gap::AdvertisementReportCallback_t callback);
BLE Advertising スキャンを開始します 引数にはスキャン検出時に呼ばれるコールバック関数を設定します。


・スキャン停止

ble_error_t stopScan( void );
BLE Advertising スキャンを停止します。

・パラメータ設定

ble_error_t setScanParams(

    uint16_t interval = GapScanningParams::SCAN_INTERVAL_MAX,
    uint16_t window   = GapScanningParams::SCAN_WINDOW_MAX,
    uint16_t timeout  = 0,
    bool     activeScanning = false);
ble_error_t setScanInterval(uint16_t interval);
ble_error_t setScanWindow  (uint16_t window);
ble_error_t setScanTimeout (uint16_t timeout);
スキャン時のパラメータを設定します。
interval
 スキャン周期を 625us単位で指定します
 最小値  SCAN_INTERVAL_MIN (0x0004 : 2.5 ms)
 最大値 SCAN_INTERVAL_MAX (0x4000 : 10.24 s) -- デフォルト値

window
 スキャン時間を 625us単位で指定します
 最小値 SCAN_WINDOW_MIN (0x0004 : 2.5 ms)
 最大値 SCAN_WINDOW_MAX (0x4000 : 10.24 s) -- デフォルト値

timeout
 スキャンを終了するまでの時間を秒単位で指定します
 最小値 SCAN_TIMEOUT_MIN (0x0001)
 最大値 SCAN_TIMEOUT_MAX (0xFFFF)
 0x0000 はスキャン終了せずにエンドレス動作となります -- デフォルト値


・コールバック関数

void onScanCallback(const Gap::AdvertisementCallbackParams_t *params)
関数名はstartScan() の引数として設定すればよいので自由に決めても問題ありません
引数 params よりスキャン成功時の情報が取得できます。

<Gap.h>
struct AdvertisementCallbackParams_t {
  Address_t      peerAddr;
  int8_t         rssi;
  bool           isScanResponse;
  AdvertisementType_t type;
  uint8_t        advertisingDataLen;
  const uint8_t  *advertisingData;
};


新しいAPIを使った実例

今回紹介しましたBLE-API を用いる最適なアプリケーションとして BLE Beacon受信があります。
ちょうど 2015年6月に UriBeacon のAPI 更新も行われたところなので UriBeaconで送信したビーコンを、今回紹介しましたAPIを用いて受信するデバイスを作成してみました。

・受信側

ハードウェアは次のようになっています。


受信した Advertising パケットの内容をUSBシリアルポート経由で出力できるようにしました。USBシリアル変換は秋葉原で購入したものをそのまま使っています。mbedからは9600bpsでデバッグ出力が行われますので、ターミナル設定を9600bps,non-pariry,1-stopbit として接続を行ってください。ボードの電源についてはUSBシリアル変換に3.3V出力がありましたので、そこから電源供給するようにしています。
また受信強度を3段階で表示するLEDも載せています。


ファームウェアはAdvertising パケット受信のためのBLEスキャンを行うための初期化コードと Advertising パケット受信時に呼ばれるコールバック関数の2つになります。

BLEスキャン部の抜粋コード -- 全体ソースコードはこちら

ble.init();
...
ble.setScanParams(
  GapScanningParams::SCAN_INTERVAL_MAX,
  GapScanningParams::SCAN_WINDOW_MAX,
  0);
ble.startScan(&onScanCallback);
void onScanCallback(const Gap::AdvertisementCallbackParams_t *params)
{
  DEBUG("onScan() ");
  DEBUG("RSSI:%d ",params->rssi);
  DEBUG("Addr:%d ",params->peerAddr);
  DEBUG("Len:%d ",params->advertisingDataLen);
  DEBUG("Data:");
  for (int i=0; i< params->advertisingDataLen; i++){
    DEBUG("%02x,",params->advertisingData[i]);
  }
}


・送信側

ビーコンを送信するだけなのでハードウェアはとてもシンプルです。
nRF51 ブランクモジュールを搭載した BreakoutボードとCR2032ボタン電池、そして状態表示用としてLEDを2個をブレッドボードに載せています。


UriBeacon を送信するファームウェアのソースコードは UriBeacon本家にあります。
https://github.com/google/uribeacon/tree/master/beacons/mbed

しかし今回のAPI変更にはまだ対応していませんでした。
そこでAPI変更に対応したコードをここで公開いたします -- ソースコードはこちら


・実際に動作させてみましょう!

送信側はボタン電池を取り付けたあと10秒後にビーコン送信が始まります。
受信側はUSBシリアル変換モジュールにあるUSBコネクタをPCに接続するとスキャンが始まります。近くに Advertisingパケットを出す機器があると、USBシリアル経由で RSSI値とADフィールドのダンプが表示されます。

onScan() RSSI:-40 Len:24 Data:02,01,06,03,03,d8,fe,10,16,d8,fe,00,fc,02,75,72,69,62,65,61,63,6f,6e,08,


また3つのLEDにより、ビーコンとの距離が「存在する」「近づいた」「タッチできるぐらい」という感覚で判るようになっています




BLEスキャン中の消費電力について

前回と同じ方法を用いAdvertisingパケットをスキャンしているときの消費電力を測定してみました。

測定にあたり波形確認しやすいようファームウェアを変更しています -- ソースコードはこちら
・10秒間隔で1秒間の BLEスキャンを行う
・Advertisingパケットを受信したらスキャン停止

スキャン中の波形は次のとおりです


BLEスキャン中は連続して10mAの電流が流れ続けており、他の処理に比べて圧倒的に電力消費が多くなっています。
このことからBLEセントラルの動作にはボタン電池を使わず外部電源で行うのが現実的であると思われます。またBLEモジュール内部では電力消費分の発熱も起きていますので、熱による内部回路への影響も考慮して連続的なスキャン動作は避けるべきでしょう。

今後期待したい BLE-API 追加と安定化

6月以降のアップデートにてGATTクライアント関連のコードが順次追加されています。まだ実装が安定しておらず頻繁にビルド不能に陥ることから実際に使うのには難しいところですが、今後の機能追加に期待したいところです。

まとめ

今回は特別編として、新しく追加されたBLE-APIの使い方を紹介させていただきました。まだビーコンしか扱うことができませんが面白いアイデアが沸いてくるかと思っています。
次回は新たに追加されるGATTクライアントAPIについて掲載していく予定です。

140 180 Bluetooth , GAP , GATT , mbed , Nordic , nRF51822 , UriBeacon , ツール作成

記載されている会社名、および商品名等は、各社の商標または登録商標です。

1 コメント:

  1. mbed BLE APIを修正して、Readまで出来ました。

    修正箇所は DiscoveredCharacteristic.h で、connHandleが抜けているのでソイツを追加してやればOKです。

    詳しいことは、RedBearのGitHubにある
    https://github.com/RedBearLab/nRF51822-Arduino/tree/S130/arduino-1.6.x/hardware/RBL/RBL_nRF51822/cores/RBL_nRF51822
    内のコードと、付属しているBLE_CentralTest.inoが参考になると思います。
    https://github.com/RedBearLab/nRF51822-Arduino/tree/S130/arduino-1.6.x/hardware/RBL/RBL_nRF51822/libraries/BLE_Examples/examples/BLE_CentralTest

    Arduinoが開発環境となっているようですが、ほぼほぼ丸っとmbed BLE APIを内包していて、修正も入っているようですよ。

    返信削除

Related Posts Plugin for WordPress, Blogger...