mbed HRM1017 で Heart Rate Profile をサポートしてみる(6) [mbed]
mbed HRM1017 で心拍を視覚的に表現するために、Pixel Led (WS2812b) を接続してみました。
心拍センサー は5ピンに、LED は6ピンに接続をしています。
プログラムは下記のサイトを参照してください。mbed にアカウントがあれば、インポートして使えると思います。
https://developer.mbed.org/users/YoshinoTaro/code/BLE_HeartRate/
実際の動きがこちら。思ったよりもつまらくてガッカリです。
うーん、なんか面白い視覚効果が出せないかなぁ。
ε=(ー。-)
心拍センサー は5ピンに、LED は6ピンに接続をしています。
プログラムは下記のサイトを参照してください。mbed にアカウントがあれば、インポートして使えると思います。
https://developer.mbed.org/users/YoshinoTaro/code/BLE_HeartRate/
実際の動きがこちら。思ったよりもつまらくてガッカリです。
うーん、なんか面白い視覚効果が出せないかなぁ。
ε=(ー。-)
mbed HRM1017 でカラーLED(WS2812B)を光らせてみた [mbed]
先日、カラーLEDアレイ WS2812B を買いました。しばらく放っておいたのですが、mbed HRM1017 で光らせてみることにしました。
mbed nRF51822 用の WS2812B 用のライブラリはこちらにあります。ライブラリとしてのインポートになるので、新しいプロジェクトを作って、”Import into Compiler” でワークスペースに取り込んでください。
https://developer.mbed.org/teams/Seeed/code/color_pixels/
WS2812B のシグナル用のピンはp6 ピンに接続しました。
簡単なテストプログラムで動きを確認してみました。
プログラムをコンパイルしダウンロードして書き込むと、あっけなく動きました!すげぇ。
動画はこちら!
mbed で出来ることも少しずつ増えてきました。さて、これで何を作ろうかなぁ!
(^_^)/~
mbed nRF51822 用の WS2812B 用のライブラリはこちらにあります。ライブラリとしてのインポートになるので、新しいプロジェクトを作って、”Import into Compiler” でワークスペースに取り込んでください。
https://developer.mbed.org/teams/Seeed/code/color_pixels/
WS2812B のシグナル用のピンはp6 ピンに接続しました。
簡単なテストプログラムで動きを確認してみました。
#include "mbed.h" #include "color_pixels.h" // ColorPixels(signal_pin, number_of_LED) ColorPixels pixels(6, 8); int main() { while (true) { pixels.rainbow(rand()/256, rand()/256, rand()/256); wait(1); } }
プログラムをコンパイルしダウンロードして書き込むと、あっけなく動きました!すげぇ。
動画はこちら!
mbed で出来ることも少しずつ増えてきました。さて、これで何を作ろうかなぁ!
(^_^)/~
mbed HRM1017 で Heart Rate Profile をサポートしてみる(5) [mbed]
mbed HRM1017 をいよいよ Heart Rate Monitor にして、スマホとBLEで接続できるようにしてみたいと思います。心拍センサーの出力は前回の実験から10kΩを挟んで計測しています。
Heart Rate 計測のアルゴリズムは PulseSensor.com の内容をmbedに移植しました。
PULSE SENSOR AMPED
http://pulsesensor.com/pages/pulse-sensor-amped-arduino-v1dot1
ときどき値が飛ぶのでまだバグがあるようですが、参考までにソースコードを公開しておきます。
メインのプログラムは下記のように変更を加えました。BLEのライブラリはこちらのサンプルで使われているライブラリをアップデートせずに使っています。
Nordic のスマホ向けテストアプリ nRFToolBox で動きを確かめてみました。心拍数が時々あがっているところは軽くスクワットをしているところです。
ちょっと値がおかしいところもありますが、ほぼ想定通りに動いているようです。実験しながらアルゴリズムを調整していきたいと思います。
(^_^)/~
Heart Rate 計測のアルゴリズムは PulseSensor.com の内容をmbedに移植しました。
PULSE SENSOR AMPED
http://pulsesensor.com/pages/pulse-sensor-amped-arduino-v1dot1
ときどき値が飛ぶのでまだバグがあるようですが、参考までにソースコードを公開しておきます。
#include "mbed.h" #include <limits.h> #ifdef __cplusplus extern "C" { #endif // __cplusplus #define NEED_DEBUG #ifdef NEED_DEBUG #define DEBUG(...) { printf(__VA_ARGS__); } #else #define DEBUG(...) /* nothing */ #endif #define N 10 #define DEFAULT_THRESHOLD 500 #define DEFAULT_AMP 100 volatile int BPM = 60; volatile int IBI = 600; volatile bool Pulse = false; volatile bool QS = false; volatile int Rate[N]; volatile int CurrentBeatTime = 0; volatile int LastBeatTime = 0; volatile uint16_t Signal; volatile uint16_t P = DEFAULT_THRESHOLD; volatile uint16_t T = DEFAULT_THRESHOLD; volatile uint16_t Threshold = DEFAULT_THRESHOLD; volatile int Amplifier = DEFAULT_AMP; Timer timer; AnalogIn ain(p6); void initPulseSensor(void) { for (int i = 0; i < N; ++i) { Rate[i] = 0; } timer.start(); LastBeatTime = timer.read_ms(); } int getBPM(void) { return BPM; } bool isQS(void) { bool qs = QS; QS = false; return qs; } void reset() { Threshold = DEFAULT_THRESHOLD; Amplifier = DEFAULT_AMP; P = T = DEFAULT_THRESHOLD; } void calcHeartRate(void) { Signal = ain.read_u16(); CurrentBeatTime = timer.read_ms(); // printf("%d\t%d\r\n", CurrentBeatTime, Signal); int interval = 0; if (CurrentBeatTime < LastBeatTime) { interval = INT_MAX - CurrentBeatTime + LastBeatTime; } else { interval = CurrentBeatTime - LastBeatTime; } if ((Signal < Threshold) && (interval > IBI * 3/5)) { if (Signal < T) { T = Signal; // hold bottom } } else if ((Signal > Threshold) && (Signal > P)) { P = Signal; // hold peak } if (interval > 250 && interval < 2500) { // msec if ((Signal > Threshold) && !Pulse && (interval > IBI * 3/5)) { Pulse = true; IBI = interval; if (Rate[0] < 0) { // first time Rate[0] = 0; LastBeatTime = timer.read_ms(); return; } else if (Rate[0] == 0) { // second time for (int i = 0; i < N; ++i) { Rate[i] = IBI; } } int running_total = 0; for (int i = 0; i < N-1; ++i) { Rate[i] = Rate[i+1]; running_total += Rate[i]; } Rate[N-1] = IBI; running_total += IBI; running_total /= N; BPM = 60000 / running_total; QS = true; LastBeatTime = timer.read_ms(); DEBUG("P:%d T:%d AMP:%d THR:%d BPM:%d\r\n" ,P ,T ,Amplifier ,Threshold ,BPM); } } if (Pulse) { Pulse = false; if (P >= T) { Amplifier = P - T; Threshold = Amplifier/2 + T; // update Threshold P = T = Threshold; DEBUG("Update Threshold:%d\r\n", Threshold); } else { DEBUG("Error: T(%d) over P(%d)\r\n", T, P); reset(); } } // check if no Signal is over 2.5 sec if (interval >= 2500) { DEBUG("No Signal over 2.5sec\r\n"); reset(); LastBeatTime = timer.read_ms(); for (int i = 0; i < N; ++i) { Rate[i] = -1; } } } #ifdef __cplusplus } #endif
メインのプログラムは下記のように変更を加えました。BLEのライブラリはこちらのサンプルで使われているライブラリをアップデートせずに使っています。
#include "mbed.h" #include "BLE.h" #include <math.h> #include "PulseSensor.h" #define NEED_DEBUG #ifdef NEED_DEBUG #define DEBUG(...) { printf(__VA_ARGS__); } #else #define DEBUG(...) /* nothing */ #endif const static char DEVICE_NAME[] = "mbed HRM1017"; static volatile bool triggerSensorPolling = false; BLEDevice ble; /* Heart Rate Service */ static uint8_t hrmCounter = 100; static uint8_t bpm[2] = {0x00, hrmCounter}; GattCharacteristic hrmChar( GattCharacteristic::UUID_HEART_RATE_MEASUREMENT_CHAR ,bpm, sizeof(bpm) ,sizeof(bpm) ,GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY); static uint8_t location = 0x05; /* Ear Lobe */ GattCharacteristic hrmLocation( GattCharacteristic::UUID_BODY_SENSOR_LOCATION_CHAR ,(uint8_t *)&location ,sizeof(location) ,sizeof(location) ,GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ); GattCharacteristic *hrmChars[] = {&hrmChar, &hrmLocation,}; GattService hrmService(GattService::UUID_HEART_RATE_SERVICE ,hrmChars ,sizeof(hrmChars)/sizeof(GattCharacteristic *)); /* Battery Level Service */ static uint8_t batt = 100; GattCharacteristic battLevel( GattCharacteristic::UUID_BATTERY_LEVEL_CHAR ,(uint8_t *)&batt ,sizeof(batt) ,sizeof(batt) ,GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY); GattCharacteristic *battChars[] = {&battLevel,}; GattService battService( GattService::UUID_BATTERY_SERVICE ,battChars ,sizeof(battChars)/sizeof(GattCharacteristic *)); /* Device Information service */ static uint8_t deviceName[] = {'H', 'R', 'M', '1', '0', '1', '7'}; GattCharacteristic deviceManufacturer( GattCharacteristic::UUID_MANUFACTURER_NAME_STRING_CHAR ,(uint8_t *)deviceName ,sizeof(deviceName) ,sizeof(deviceName) ,GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ); GattCharacteristic *devInfoChars[] = {&deviceManufacturer,}; GattService deviceInformationService( GattService::UUID_DEVICE_INFORMATION_SERVICE ,devInfoChars ,sizeof(devInfoChars)/sizeof(GattCharacteristic *)); static uint16_t uuid16_list[] = { GattService::UUID_HEART_RATE_SERVICE ,GattService::UUID_BATTERY_SERVICE ,GattService::UUID_DEVICE_INFORMATION_SERVICE }; void updateServiceValues(void); static Gap::ConnectionParams_t connectionParams; void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params) { DEBUG("Disconnected handle %u, reason %u\r\n", params->handle, params->reason); DEBUG("Restarting the advertising process\r\n"); ble.gap().startAdvertising(); } void onConnectionCallback(const Gap::ConnectionCallbackParams_t *params) { DEBUG("connected. Got handle %u\r\n", params->handle); connectionParams.slaveLatency = 1; if (ble.gap().updateConnectionParams(params->handle, &connectionParams) != BLE_ERROR_NONE) { DEBUG("failed to update connection paramter\r\n"); } } void periodicCallback(void) { triggerSensorPolling = true; } int main(void) { Ticker ticker; ticker.attach(periodicCallback, 1); DEBUG("Initialising the nRF51822\r\n"); ble.init(); DEBUG("Init done\r\n"); ble.gap().onDisconnection(disconnectionCallback); ble.gap().onConnection(onConnectionCallback); ble.gap().getPreferredConnectionParams(&connectionParams); /* setup advertising */ ble.gap().accumulateAdvertisingPayload( GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); ble.gap().accumulateAdvertisingPayload( GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS ,(uint8_t*)uuid16_list, sizeof(uuid16_list)); ble.gap().accumulateAdvertisingPayload( GapAdvertisingData::GENERIC_HEART_RATE_SENSOR); ble.gap().accumulateAdvertisingPayload( GapAdvertisingData::COMPLETE_LOCAL_NAME ,(uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME)); ble.gap().setAdvertisingType( GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); ble.gap().setAdvertisingInterval(160); /* 100ms; in multiples of 0.625ms. */ ble.gap().startAdvertising(); DEBUG("Start Advertising\r\n"); ble.gattServer().addService(hrmService); ble.gattServer().addService(battService); ble.gattServer().addService(deviceInformationService); DEBUG("Add Service\r\n"); initPulseSensor(); Ticker hrm_ticker; hrm_ticker.attach(calcHeartRate, 0.02); while (true) { if (triggerSensorPolling) { triggerSensorPolling = false; updateServiceValues(); } else { ble.waitForEvent(); } } } void updateServiceValues(void) { /* Decrement the battery level. */ batt <= 50 ? batt = 100 : batt--; ble.gattServer().write( battLevel.getValueAttribute().getHandle() ,(uint8_t*)&batt, sizeof(batt)); /* Randomize the heart rate. */ if (isQS()) { hrmCounter = getBPM(); DEBUG("BPM: %d\r\n", hrmCounter); } bpm[1] = hrmCounter; ble.gattServer().write(hrmChar.getValueAttribute().getHandle() ,bpm, sizeof(bpm)); }
Nordic のスマホ向けテストアプリ nRFToolBox で動きを確かめてみました。心拍数が時々あがっているところは軽くスクワットをしているところです。
ちょっと値がおかしいところもありますが、ほぼ想定通りに動いているようです。実験しながらアルゴリズムを調整していきたいと思います。
(^_^)/~
mbed HRM1017 で Heart Rate Profile をサポートしてみる(4) [mbed]
前回まで心拍データにランダム値を使っていましたが、それではつまらないので、mbed HRM1017 に HeartRateSensor を接続してみました。
センサーの値がAnalogIn端子から読み取れるか試してみます。ピン配は下記のようにしてみました。
HeartRateSensor の値を読みだすプログラムを作ってみました。非常にシンプルなので分かりやすい!
読み取った値をグラフにしてみました。
心拍はとれているようですが、値がサチってしまっています。抵抗を間に入れたほうがよさそうです。10kΩを間に入れてみました。
10kΩを挟んでみたデータをグラフにしてみました。ピークが少し小さいですが、なかなか良い値がとれているようです。
センサーからデータが取れるようになったので、心拍計算用のアルゴリズムを導入してBLE心拍センサーに仕上げてみたいと思います!
(^_^)/~
センサーの値がAnalogIn端子から読み取れるか試してみます。ピン配は下記のようにしてみました。
HeartRateSensor の値を読みだすプログラムを作ってみました。非常にシンプルなので分かりやすい!
#include "mbed.h" AnalogIn ain(p6); Timer timer; void getHeartRateValue(void) { uint16_t signal = ain.read_u16(); int cur_time = timer.read_ms(); printf("%d\t%d\r\n", cur_time, signal); } int main() { timer.start(); Ticker hrm_ticker; hrm_ticker.attach(getHeartRateValue, 0.02); // 20msec while(true); }
読み取った値をグラフにしてみました。
心拍はとれているようですが、値がサチってしまっています。抵抗を間に入れたほうがよさそうです。10kΩを間に入れてみました。
10kΩを挟んでみたデータをグラフにしてみました。ピークが少し小さいですが、なかなか良い値がとれているようです。
センサーからデータが取れるようになったので、心拍計算用のアルゴリズムを導入してBLE心拍センサーに仕上げてみたいと思います!
(^_^)/~
mbed HRM1017 の Nordic BLE ライブラリにはまる [mbed]
mbed を使っていると、BLEライブラリをアップデートしたら?という案内が出てきます。下の緑にリサイクルマークのような奴がそうです。しかし、この誘いにやすやすと乗るのはよしましょう。
迂闊にアップデートをすると、自分の書いたソースコードを一行も変更していないのに Nordic のBLEライブラリの中でエラーが出てしまいます。さすがにライブラリの中でエラーが出ると手出しができません。
mbed の BLEライブラリは更新頻度が高くてついていくのが大変だという話はよく聞きますが、ここまでとは。おかげで小一時間無駄にしてしまいました。mbed がいまいち盛り上がりに欠けるのはこういうところもあるのかなぁ。
ε=(-A -#)
迂闊にアップデートをすると、自分の書いたソースコードを一行も変更していないのに Nordic のBLEライブラリの中でエラーが出てしまいます。さすがにライブラリの中でエラーが出ると手出しができません。
mbed の BLEライブラリは更新頻度が高くてついていくのが大変だという話はよく聞きますが、ここまでとは。おかげで小一時間無駄にしてしまいました。mbed がいまいち盛り上がりに欠けるのはこういうところもあるのかなぁ。
ε=(-A -#)
mbed HRM1017 で Heart Rate Profile をサポートしてみる(3) [mbed]
いよいよ、今回から mbed HRM1017 で Heart Rate Profile をサポートしてみたいと思います。前回の検討で、Heart Rate Profile は、Heart Rate Service と Device Information Service をサポートする必要があることが分かりました。
Heart Rate Service では、Heart Rate Measurement Characteristic とBody Sensor Location Characteristic の2つをサポートします。 mbed での宣言部は下記のようになります。
Device Information Service では、Device Information Service Characteristic をサポートします。
NORDIC の nRFToolbox では、Battery Level も表示するようになっていますので参考までに設定を載せておきます。(mbed HRM1017 のサンプルプログラムでも記載されています)
だいたいパターンはわかったと思います。次にサポートするサービスを Advertising パケットに組み込みます。Advertising とは Collector と接続するための仕組みで、Advertising パケットの中に自分がどのようなサービスを提供しているか記述する必要があります。
Advertising パケットの詳細については、こちらを参照ください。非常に参考になります。
BluetoothSMARTデバイスをmbed で開発する(4)
http://bril-tech.blogspot.jp/2014/06/bluetoothsmartmbed-4.html
今回作成した全コードは下記リポジトリにありますので参照ください。今回は心拍センサーは接続せずにランダム値を心拍データとして扱っています。
BLE_HeartRate
https://developer.mbed.org/users/YoshinoTaro/code/BLE_HeartRate/
それでは、nRFToolbox の Heart Rate Monitor でどう見えるか見てみましょう。
おお、それらしく見えてますね!Device Information も Body Location も認識しているようです。
スマホと接続できると値を記録できるので、心拍計としての応用範囲がぐっと広がりますね。次はいよいよ心拍センサーを接続してみたいと思います!
(^_^)/~
Heart Rate Service では、Heart Rate Measurement Characteristic とBody Sensor Location Characteristic の2つをサポートします。 mbed での宣言部は下記のようになります。
// Heart Rate Measurement Characteristic Setting static uint8_t hrmCounter = 100; // default value static uint8_t bpm[2] = {0x00, hrmCounter}; GattCharacteristic hrmChar(GattCharacteristic::UUID_HEART_RATE_MEASUREMENT_CHAR ,bpm, sizeof(bpm) ,sizeof(bpm) ,GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY); // Body Sensor Location Characteristic Setting static uint8_t location = 0x05; /* Ear Lobe */ GattCharacteristic hrmLocation(GattCharacteristic::UUID_BODY_SENSOR_LOCATION_CHAR ,(uint8_t *)&location ,sizeof(location) ,sizeof(location) ,GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ); // Heart Rate Service Service GattCharacteristic *hrmChars[] = {&hrmChar, &hrmLocation,}; GattService hrmService(GattService::UUID_HEART_RATE_SERVICE ,hrmChars ,sizeof(hrmChars)/sizeof(GattCharacteristic *));
Device Information Service では、Device Information Service Characteristic をサポートします。
// Device Information Service Characteristic Setting static uint8_t deviceName[] = {'H', 'R', 'M', '1', '0', '1', '7'}; GattCharacteristic deviceManufacturer(GattCharacteristic::UUID_MANUFACTURER_NAME_STRING_CHAR ,(uint8_t *)deviceName ,sizeof(deviceName) ,sizeof(deviceName) ,GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ); // Device Information Service GattCharacteristic *devInfoChars[] = {&deviceManufacturer,}; GattService deviceInformationService(GattService::UUID_DEVICE_INFORMATION_SERVICE ,devInfoChars ,sizeof(devInfoChars)/sizeof(GattCharacteristic *));
NORDIC の nRFToolbox では、Battery Level も表示するようになっていますので参考までに設定を載せておきます。(mbed HRM1017 のサンプルプログラムでも記載されています)
// Battery Level Characteristic Setting static uint8_t batt = 100; GattCharacteristic battLevel(GattCharacteristic::UUID_BATTERY_LEVEL_CHAR ,(uint8_t *)&batt ,sizeof(batt) ,sizeof(batt) ,GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY); // Battery Level Service GattCharacteristic *battChars[] = {&battLevel,}; GattService battService(GattService::UUID_BATTERY_SERVICE ,battChars ,sizeof(battChars)/sizeof(GattCharacteristic *));
だいたいパターンはわかったと思います。次にサポートするサービスを Advertising パケットに組み込みます。Advertising とは Collector と接続するための仕組みで、Advertising パケットの中に自分がどのようなサービスを提供しているか記述する必要があります。
// service list static uint16_t uuid16_list[] = { GattService::UUID_HEART_RATE_SERVICE ,GattService::UUID_BATTERY_SERVICE ,GattService::UUID_DEVICE_INFORMATION_SERVICE }; BLEDevice ble; // only BLE support, not support the classic bluetooth ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); // registering the supported services ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS , (uint8_t*)uuid16_list, sizeof(uuid16_list)); // the appearance is a heart rate sensor ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_HEART_RATE_SENSOR); // registering the device name ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME , (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME)); // setting as a connectable device to a collector ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); // advertising interval is 100msec ble.gap().setAdvertisingInterval(160); ble.gap().startAdvertising();
Advertising パケットの詳細については、こちらを参照ください。非常に参考になります。
BluetoothSMARTデバイスをmbed で開発する(4)
http://bril-tech.blogspot.jp/2014/06/bluetoothsmartmbed-4.html
今回作成した全コードは下記リポジトリにありますので参照ください。今回は心拍センサーは接続せずにランダム値を心拍データとして扱っています。
BLE_HeartRate
https://developer.mbed.org/users/YoshinoTaro/code/BLE_HeartRate/
それでは、nRFToolbox の Heart Rate Monitor でどう見えるか見てみましょう。
おお、それらしく見えてますね!Device Information も Body Location も認識しているようです。
スマホと接続できると値を記録できるので、心拍計としての応用範囲がぐっと広がりますね。次はいよいよ心拍センサーを接続してみたいと思います!
(^_^)/~
mbed HRM1017 で Heart Rate Profile をサポートしてみる(2) [mbed]
前回から少し間が空きましたが mbed HRM1017 で Heart Rate Profile をサポートする検討の続きです。 Heart Rate Profile の仕様書は下記サイトでダウンロードできます。
仕様書へのリンクは少し分かりにくいところにありますので注意してください。
https://developer.bluetooth.org/TechnologyOverview/Pages/HRP.aspx
Heart Rate Sensor は二つのサービスをサポートすることが必須となります。Heart Rate Service と、Device Information Service です。心拍情報を提供と製品情報の提供ですね。
こちらは、仕様書から抜き出した Heart Rate Service と Device Information Service がサポートすべきCharacteristics の抜粋です。
まずは Heart Rate Service がサポートすべき Characteristics から、
Heart Rate Measurement Characteristic は、心拍数データを表します。Heart Rate Sensor から Collector へ通知するデータです。
Body Sensor Location Characteristic は、身体のどの位置につけるセンサーかを示すデータです。Other(0x00)、Chest(0x01)、Wrist(0x02)、Finger(0x03)、Hand(0x04)、Ear Lobe(0x05)、Foot(0x06)等が定義されています。
Heart Rate Control Point Characteristic は、何なのか一番悩みました。Energy Expended がよく分からなかったのですが、文字通り”エネルギー消費量”、活動量計ってことですね。活動量を提示する機能があるデバイスなら、Collector からゼロリセット出来るようにしておけということらしいです。
Device Information Service の Characteristics については詳細が記述されていませんが、ここには製品情報(メーカー名や製品名)を格納します。
だいたい様子は分かりました。今回は活動量計をつけるつもりはないので、Heart Rate Control Point はサポートしなくてもよいかな。
σ( ̄_ ̄)
仕様書へのリンクは少し分かりにくいところにありますので注意してください。
https://developer.bluetooth.org/TechnologyOverview/Pages/HRP.aspx
Heart Rate Sensor は二つのサービスをサポートすることが必須となります。Heart Rate Service と、Device Information Service です。心拍情報を提供と製品情報の提供ですね。
こちらは、仕様書から抜き出した Heart Rate Service と Device Information Service がサポートすべきCharacteristics の抜粋です。
まずは Heart Rate Service がサポートすべき Characteristics から、
Device Information Service の Characteristics については詳細が記述されていませんが、ここには製品情報(メーカー名や製品名)を格納します。
だいたい様子は分かりました。今回は活動量計をつけるつもりはないので、Heart Rate Control Point はサポートしなくてもよいかな。
σ( ̄_ ̄)
Bluetooth Low Energyをはじめよう (Make:PROJECTS)
- 作者: Kevin Townsend
- 出版社/メーカー: オライリージャパン
- 発売日: 2015/02/25
- メディア: 単行本(ソフトカバー)
mbed HRM1017 で Heart Rate Profile をサポートしてみる(1) [mbed]
mbed HRM1017 のサンプルプログラムはHealth Thermometer Profile (HTM) をサポートしています。
今回はサンプルプログラムを改造して Health Thermometer Profile の代わりに Heart Rate Profile をサポートしてみたいと思います。
その前に、BLEの基本プロトコルであるGATTプロファイルの構造について調べてみました。GATTプロファイルは大きく3つの情報から構成されています。
・デバイスが提供するサービス (Service)
・デバイスの持つ属性値 (Characteristic)
・デバイスの持つ属性 (Characteristic) への付加情報 (Descriptor)
出典: http://yegang.hatenablog.com/entry/2014/08/09/195246
GATTは、サービスとプロファイルが混在しており分かりにくいですが、どうも機器固有機能はプロファイルとサービスが定義され、機器によらない一般的な情報はサービスのみとなっているようです。
https://www.bluetooth.com/specifications/adopted-specifications
参考までに、GATTでサポートしているプロファイルの一覧を列挙しておきます。
出典:https://developer.bluetooth.org/gatt/profiles/Pages/ProfilesHome.aspx
BLEではホスト機能を持つ機器を "Central" と呼びデバイス機能を持つ機器を "Peripheral" と呼びます。(参考: http://yegang.hatenablog.com/entry/2014/07/19/224754 ) これらのプロファイル は Peripheral が持つ機能に相当します。
サンプルプログラムではどのように mbed HRM1017 へ Health Thermometer Profile を設定しているか抜粋し整理してみました。
Advertising は Central (スマホ)が Peripheral を見つけるためのプロトコルです。詳細について知りたい方はこちらのサイトが参考になると思います。
まぁ中身は詳しく分からなくとも、この流儀に従えば Heart Rate Profile の追加ができそうですね。
(^_^)/~
今回はサンプルプログラムを改造して Health Thermometer Profile の代わりに Heart Rate Profile をサポートしてみたいと思います。
その前に、BLEの基本プロトコルであるGATTプロファイルの構造について調べてみました。GATTプロファイルは大きく3つの情報から構成されています。
・デバイスが提供するサービス (Service)
・デバイスの持つ属性値 (Characteristic)
・デバイスの持つ属性 (Characteristic) への付加情報 (Descriptor)
出典: http://yegang.hatenablog.com/entry/2014/08/09/195246
GATTは、サービスとプロファイルが混在しており分かりにくいですが、どうも機器固有機能はプロファイルとサービスが定義され、機器によらない一般的な情報はサービスのみとなっているようです。
https://www.bluetooth.com/specifications/adopted-specifications
参考までに、GATTでサポートしているプロファイルの一覧を列挙しておきます。
Alert Notification | This profile enables a client device to receive different types of alerts and event information, as well as information on the count of new alerts and unread items, which exist in the server device. |
Blood Pressure | This profile enables a device to connect and interact with a Blood Pressure Sensor device for use in consumer and professional health care applications. |
Cycling Power | This profile enables a Collector device to connect and interact with a Cycling Power Sensor for use in sports and fitness applications. |
Cycling Speed and Cadence | This profile enables a Collector device to connect and interact with a Cycling Speed and Cadence Sensor for use in sports and fitness applications. |
Find Me | The Find Me profile defines the behavior when a button is pressed on one device to cause an alerting signal on a peer device. |
Glucose | This profile enables a device to connect and interact with a glucose sensor for use in consumer and professional healthcare applications. |
Health Thermometer | This profile enables a Collector device to connect and interact with a Thermometer sensor for use in healthcare applications. |
Heart Rate | This profile enables a Collector device to connect and interact with a Heart Rate Sensor for use in fitness applications. |
HID OVER GATT | This profile defines how a device with Bluetooth low energy wireless communications can support HID services over the Bluetooth low energy protocol stack using the Generic Attribute Profile. |
Location and Navigation | This profile enables a Collector device to connect and interact with a Location and Navigation Sensor for use in outdoor activity applications. |
Phone Alert Status | This profile enables a PUID device to alert its user about the alert status of a phone connected to the PUID device. |
Proximity | The Proximity profile enables proximity monitoring between two devices. |
Running Speed and Cadence | This profile enables a Collector device to connect and interact with a Runners Speed and Cadence Sensor for use in sports and fitness applications. |
Scan Parameters | This profile defines how a Scan Client device with Bluetooth low energy wireless communications can write its scanning behavior to a Scan Server, and how a Scan Server can request updates of a Scan Client scanning behavior. |
Time | The Time profile enables the device to get the date, time, time zone, and DST information and control the functions related the time. |
出典:https://developer.bluetooth.org/gatt/profiles/Pages/ProfilesHome.aspx
BLEではホスト機能を持つ機器を "Central" と呼びデバイス機能を持つ機器を "Peripheral" と呼びます。(参考: http://yegang.hatenablog.com/entry/2014/07/19/224754 ) これらのプロファイル は Peripheral が持つ機能に相当します。
サンプルプログラムではどのように mbed HRM1017 へ Health Thermometer Profile を設定しているか抜粋し整理してみました。
// Health Thermometer の Characteristics の定義 uint8_t thermTempPayload[5] = { 0, 0, 0, 0, 0 }; GattCharacteristic tempChar (GattCharacteristic::UUID_TEMPERATURE_MEASUREMENT_CHAR, thermTempPayload, 5, 5, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE); GattCharacteristic *htmChars[] = {&tempChar, }; ... // Health Thermometer の Service の定義 GattService htmService(GattService::UUID_HEALTH_THERMOMETER_SERVICE, htmChars, sizeof(htmChars) / sizeof(GattCharacteristic *)); ... // サポートするサービス一覧 uint16_t uuid16_list[] = {GattService::UUID_HEALTH_THERMOMETER_SERVICE, GattService::UUID_BATTERY_SERVICE}; ... // Advertising (サービスディスカバリー)のための設定 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE); ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t*)uuid16_list, sizeof(uuid16_list)); ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_THERMOMETER); ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME)); ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED); ble.gap().setAdvertisingInterval(160); /* 100ms; in multiples of 0.625ms. */ ble.gap().startAdvertising(); ... // サービスの登録 ble.gattServer().addService(htmService); ... //デバイス情報の Central (例えばスマホ)へ通知 ble.gattServer().write(tempChar.getValueAttribute().getHandle(), thermTempPayload, sizeof(thermTempPayload));
Advertising は Central (スマホ)が Peripheral を見つけるためのプロトコルです。詳細について知りたい方はこちらのサイトが参考になると思います。
まぁ中身は詳しく分からなくとも、この流儀に従えば Heart Rate Profile の追加ができそうですね。
(^_^)/~
mbed HRM1017 で "Hello World" してみた [mbed]
mbed HRM1017 でLチカするのは、GPIO が 0.5mA しかドライブできないのでちょっとやっかいです。ということで、手軽にデバッグするためにシリアル出力を試してみました。
シリアル出力をするには、ドライバをインストールする必要があります。Switch Science さん提供の mbed HRM1017 のページから辿れます。
mbed-HRM1017をはじめよう
ドライバをインストールする時は、mbed HRM1017 をUSBで接続しておく必要があります。接続していないと、「The driver could not be installed」と出て失敗してしまいます。
ドライバのインストールが成功すると、mbed用のCOMポートが見えます。baud rate はデフォルトで 9600 bps ですので注意してください。
それでは、プログラムを書いて試してみましょう。メニューの新規を選択して、「mbed_blinky」をテンプレートに選択します。
LEDはついてないのでコメントアウトをして、おなじみの "Hello World" を書き加えます。
ターミナルを立ち上げて、ダウンロードしたイメージの mbed HRM1017 への書き込みをします。書き込みが完了すると”Hello World”が表示されるはずです。
無事に”Hello World”が表示されました!これでデバッグが捗りそうです。
(^_^)/~
シリアル出力をするには、ドライバをインストールする必要があります。Switch Science さん提供の mbed HRM1017 のページから辿れます。
mbed-HRM1017をはじめよう
ドライバをインストールする時は、mbed HRM1017 をUSBで接続しておく必要があります。接続していないと、「The driver could not be installed」と出て失敗してしまいます。
ドライバのインストールが成功すると、mbed用のCOMポートが見えます。baud rate はデフォルトで 9600 bps ですので注意してください。
それでは、プログラムを書いて試してみましょう。メニューの新規を選択して、「mbed_blinky」をテンプレートに選択します。
LEDはついてないのでコメントアウトをして、おなじみの "Hello World" を書き加えます。
ターミナルを立ち上げて、ダウンロードしたイメージの mbed HRM1017 への書き込みをします。書き込みが完了すると”Hello World”が表示されるはずです。
無事に”Hello World”が表示されました!これでデバッグが捗りそうです。
(^_^)/~
mbed で HRM1017 を動かしてみた! [mbed]
前回、mbed でのプログラムのコンパイルまで終わりましたので、いよいよダウンロードしたイメージを書き込み、HRM1017を動かしてみたいと思います。
mbed にイメージを書き込むのは、すごく簡単です。 HRM1017 をUSBで接続すると、mbed というドライブが追加されます。そこにダウンロードしてきたイメージをコピーするだけです。
書き込み中はLEDが点滅します。LEDの点滅が終わったら書き込み完了です。
書き込んだプログラムが動作しているか確認するために、Android アプリをインストールする必要があります。Nordic が提供している nRF TOOLBOX というアプリをインストールします。※使用しているスマートフォンがBLE (Bluetooth 4.0以上)に対応しているか確認してください。
インストールが終わったら nRF TOOLBOX を起動します。メニューが出てきますので、そこで「HTM」を選択します。
「CONNECT」を選択します。
接続機器リストが表示されますので、その中から「HRM1017_HTM」を選択します。
ボタンが”CONNECT”から”DISCONNECT”に変わりますので、接続されたことが分かります。肝心の温度はセンサーを接続していないので”0.00”から変化しませんが、バッテリーの数値が変わりますので、そこからも動作しているのが分かります。
mbed での開発のスタイルはだいたい分かりました。次はこのプログラムを Heart Rate Monitor に対応させてみようかな。
(^_^)/~
mbed にイメージを書き込むのは、すごく簡単です。 HRM1017 をUSBで接続すると、mbed というドライブが追加されます。そこにダウンロードしてきたイメージをコピーするだけです。
書き込み中はLEDが点滅します。LEDの点滅が終わったら書き込み完了です。
書き込んだプログラムが動作しているか確認するために、Android アプリをインストールする必要があります。Nordic が提供している nRF TOOLBOX というアプリをインストールします。※使用しているスマートフォンがBLE (Bluetooth 4.0以上)に対応しているか確認してください。
インストールが終わったら nRF TOOLBOX を起動します。メニューが出てきますので、そこで「HTM」を選択します。
「CONNECT」を選択します。
接続機器リストが表示されますので、その中から「HRM1017_HTM」を選択します。
ボタンが”CONNECT”から”DISCONNECT”に変わりますので、接続されたことが分かります。肝心の温度はセンサーを接続していないので”0.00”から変化しませんが、バッテリーの数値が変わりますので、そこからも動作しているのが分かります。
mbed での開発のスタイルはだいたい分かりました。次はこのプログラムを Heart Rate Monitor に対応させてみようかな。
(^_^)/~