BLE Heart Rate Sample Program for HRM1017 which is using Nordic nRF51822 confirmed the connection of nRFToolbox on Android.

Dependencies:   BLE_API mbed nRF51822 color_pixels

Fork of BLE_HTM_HRM1017 by Switch Science

Committer:
YoshinoTaro
Date:
Mon Aug 22 06:12:27 2016 +0000
Revision:
10:8a67578c3ef0
Parent:
9:554af3c63d0c
Child:
11:d32f4f43161d
BLE Heart Rate Sample Program for HRM1017 which is using Nordic nRF51822 confirmed the connection of nRFToolbox on Android.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
todotani 0:5e4210d108ac 1 #include "mbed.h"
ytsuboi 8:f753b4b022a8 2 #include "BLE.h"
YoshinoTaro 10:8a67578c3ef0 3 #include <math.h>
todotani 0:5e4210d108ac 4
todotani 0:5e4210d108ac 5
YoshinoTaro 10:8a67578c3ef0 6 #define NEED_DEBUG 1
YoshinoTaro 10:8a67578c3ef0 7 #if NEED_DEBUG
YoshinoTaro 10:8a67578c3ef0 8 #define DEBUG(...) { printf(__VA_ARGS__); }
todotani 0:5e4210d108ac 9 #else
todotani 0:5e4210d108ac 10 #define DEBUG(...) /* nothing */
YoshinoTaro 10:8a67578c3ef0 11 #endif
YoshinoTaro 10:8a67578c3ef0 12
todotani 0:5e4210d108ac 13
YoshinoTaro 10:8a67578c3ef0 14 const static char DEVICE_NAME[] = "mbed HRM1017";
todotani 2:daf2344afc28 15 static volatile bool triggerSensorPolling = false;
todotani 0:5e4210d108ac 16
YoshinoTaro 10:8a67578c3ef0 17
todotani 0:5e4210d108ac 18 BLEDevice ble;
YoshinoTaro 10:8a67578c3ef0 19
todotani 0:5e4210d108ac 20
YoshinoTaro 10:8a67578c3ef0 21 /* Heart Rate Service */
YoshinoTaro 10:8a67578c3ef0 22 static uint8_t hrmCounter = 100;
YoshinoTaro 10:8a67578c3ef0 23 static uint8_t bpm[2] = {0x00, hrmCounter};
YoshinoTaro 10:8a67578c3ef0 24 GattCharacteristic hrmChar(GattCharacteristic::UUID_HEART_RATE_MEASUREMENT_CHAR
YoshinoTaro 10:8a67578c3ef0 25 ,bpm, sizeof(bpm) ,sizeof(bpm)
YoshinoTaro 10:8a67578c3ef0 26 ,GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);
YoshinoTaro 10:8a67578c3ef0 27 static uint8_t location = 0x05; /* Ear Lobe */
YoshinoTaro 10:8a67578c3ef0 28 GattCharacteristic hrmLocation(GattCharacteristic::UUID_BODY_SENSOR_LOCATION_CHAR
YoshinoTaro 10:8a67578c3ef0 29 ,(uint8_t *)&location ,sizeof(location) ,sizeof(location)
YoshinoTaro 10:8a67578c3ef0 30 ,GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ);
YoshinoTaro 10:8a67578c3ef0 31 GattCharacteristic *hrmChars[] = {&hrmChar, &hrmLocation,};
YoshinoTaro 10:8a67578c3ef0 32 GattService hrmService(GattService::UUID_HEART_RATE_SERVICE
YoshinoTaro 10:8a67578c3ef0 33 ,hrmChars ,sizeof(hrmChars)/sizeof(GattCharacteristic *));
todotani 0:5e4210d108ac 34
todotani 0:5e4210d108ac 35
todotani 0:5e4210d108ac 36
todotani 0:5e4210d108ac 37 /* Battery Level Service */
YoshinoTaro 10:8a67578c3ef0 38 static uint8_t batt = 100;
YoshinoTaro 10:8a67578c3ef0 39 GattCharacteristic battLevel(GattCharacteristic::UUID_BATTERY_LEVEL_CHAR
YoshinoTaro 10:8a67578c3ef0 40 ,(uint8_t *)&batt ,sizeof(batt) ,sizeof(batt)
YoshinoTaro 10:8a67578c3ef0 41 ,GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);
YoshinoTaro 10:8a67578c3ef0 42 GattCharacteristic *battChars[] = {&battLevel,};
YoshinoTaro 10:8a67578c3ef0 43 GattService battService(GattService::UUID_BATTERY_SERVICE
YoshinoTaro 10:8a67578c3ef0 44 ,battChars ,sizeof(battChars)/sizeof(GattCharacteristic *));
YoshinoTaro 10:8a67578c3ef0 45
YoshinoTaro 10:8a67578c3ef0 46
todotani 0:5e4210d108ac 47
YoshinoTaro 10:8a67578c3ef0 48 /* Device Information service */
YoshinoTaro 10:8a67578c3ef0 49 static uint8_t deviceName[] = {'H', 'R', 'M', '1', '0', '1', '7'};
YoshinoTaro 10:8a67578c3ef0 50 GattCharacteristic deviceManufacturer(GattCharacteristic::UUID_MANUFACTURER_NAME_STRING_CHAR
YoshinoTaro 10:8a67578c3ef0 51 ,(uint8_t *)deviceName ,sizeof(deviceName) ,sizeof(deviceName)
YoshinoTaro 10:8a67578c3ef0 52 ,GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ);
YoshinoTaro 10:8a67578c3ef0 53 GattCharacteristic *devInfoChars[] = {&deviceManufacturer,};
YoshinoTaro 10:8a67578c3ef0 54 GattService deviceInformationService(GattService::UUID_DEVICE_INFORMATION_SERVICE
YoshinoTaro 10:8a67578c3ef0 55 ,devInfoChars ,sizeof(devInfoChars)/sizeof(GattCharacteristic *));
todotani 0:5e4210d108ac 56
YoshinoTaro 10:8a67578c3ef0 57
YoshinoTaro 10:8a67578c3ef0 58 static uint16_t uuid16_list[] = {
YoshinoTaro 10:8a67578c3ef0 59 GattService::UUID_HEART_RATE_SERVICE
YoshinoTaro 10:8a67578c3ef0 60 ,GattService::UUID_BATTERY_SERVICE
YoshinoTaro 10:8a67578c3ef0 61 ,GattService::UUID_DEVICE_INFORMATION_SERVICE
YoshinoTaro 10:8a67578c3ef0 62 };
YoshinoTaro 10:8a67578c3ef0 63
YoshinoTaro 10:8a67578c3ef0 64
todotani 0:5e4210d108ac 65 void updateServiceValues(void);
todotani 0:5e4210d108ac 66 static Gap::ConnectionParams_t connectionParams;
todotani 0:5e4210d108ac 67
YoshinoTaro 10:8a67578c3ef0 68 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
todotani 0:5e4210d108ac 69 {
mbed_tw_hoehoe 9:554af3c63d0c 70 DEBUG("Disconnected handle %u, reason %u\r\n", params->handle, params->reason);
ytsuboi 8:f753b4b022a8 71 DEBUG("Restarting the advertising process\r\n");
ytsuboi 8:f753b4b022a8 72 ble.gap().startAdvertising();
todotani 0:5e4210d108ac 73 }
todotani 0:5e4210d108ac 74
ytsuboi 8:f753b4b022a8 75 void onConnectionCallback(const Gap::ConnectionCallbackParams_t *params) //Mod
todotani 0:5e4210d108ac 76 {
ytsuboi 8:f753b4b022a8 77 DEBUG("connected. Got handle %u\r\n", params->handle);
todotani 0:5e4210d108ac 78
todotani 0:5e4210d108ac 79 connectionParams.slaveLatency = 1;
ytsuboi 8:f753b4b022a8 80 if (ble.gap().updateConnectionParams(params->handle, &connectionParams) != BLE_ERROR_NONE) {
todotani 0:5e4210d108ac 81 DEBUG("failed to update connection paramter\r\n");
todotani 0:5e4210d108ac 82 }
todotani 0:5e4210d108ac 83 }
todotani 0:5e4210d108ac 84
todotani 2:daf2344afc28 85 void periodicCallback(void)
todotani 2:daf2344afc28 86 {
todotani 2:daf2344afc28 87 triggerSensorPolling = true;
todotani 2:daf2344afc28 88 }
todotani 2:daf2344afc28 89
todotani 0:5e4210d108ac 90 int main(void)
YoshinoTaro 10:8a67578c3ef0 91 {
todotani 2:daf2344afc28 92 Ticker ticker;
todotani 2:daf2344afc28 93 ticker.attach(periodicCallback, 1);
todotani 2:daf2344afc28 94
ytsuboi 8:f753b4b022a8 95 DEBUG("Initialising the nRF51822\r\n");
todotani 0:5e4210d108ac 96 ble.init();
ytsuboi 8:f753b4b022a8 97 DEBUG("Init done\r\n");
ytsuboi 8:f753b4b022a8 98 ble.gap().onDisconnection(disconnectionCallback);
ytsuboi 8:f753b4b022a8 99 ble.gap().onConnection(onConnectionCallback);
todotani 0:5e4210d108ac 100
ytsuboi 8:f753b4b022a8 101 ble.gap().getPreferredConnectionParams(&connectionParams);
todotani 0:5e4210d108ac 102
todotani 0:5e4210d108ac 103 /* setup advertising */
ytsuboi 8:f753b4b022a8 104 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
ytsuboi 8:f753b4b022a8 105 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t*)uuid16_list, sizeof(uuid16_list));
YoshinoTaro 10:8a67578c3ef0 106 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_HEART_RATE_SENSOR);
ytsuboi 8:f753b4b022a8 107 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
ytsuboi 8:f753b4b022a8 108 ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
ytsuboi 8:f753b4b022a8 109 ble.gap().setAdvertisingInterval(160); /* 100ms; in multiples of 0.625ms. */
ytsuboi 8:f753b4b022a8 110 ble.gap().startAdvertising();
ytsuboi 8:f753b4b022a8 111 DEBUG("Start Advertising\r\n");
todotani 0:5e4210d108ac 112
YoshinoTaro 10:8a67578c3ef0 113 ble.gattServer().addService(hrmService);
ytsuboi 8:f753b4b022a8 114 ble.gattServer().addService(battService);
YoshinoTaro 10:8a67578c3ef0 115 ble.gattServer().addService(deviceInformationService);
ytsuboi 8:f753b4b022a8 116 DEBUG("Add Service\r\n");
todotani 0:5e4210d108ac 117
todotani 2:daf2344afc28 118 while (true) {
todotani 2:daf2344afc28 119 if (triggerSensorPolling) {
todotani 2:daf2344afc28 120 triggerSensorPolling = false;
todotani 2:daf2344afc28 121 updateServiceValues();
todotani 2:daf2344afc28 122 } else {
todotani 2:daf2344afc28 123 ble.waitForEvent();
todotani 2:daf2344afc28 124 }
todotani 0:5e4210d108ac 125 }
todotani 0:5e4210d108ac 126 }
todotani 0:5e4210d108ac 127
todotani 0:5e4210d108ac 128 void updateServiceValues(void)
todotani 0:5e4210d108ac 129 {
YoshinoTaro 10:8a67578c3ef0 130 /* Decrement the battery level. */
YoshinoTaro 10:8a67578c3ef0 131 batt <= 50 ? batt = 100 : batt--;
YoshinoTaro 10:8a67578c3ef0 132 ble.gattServer().write(battLevel.getValueAttribute().getHandle(), (uint8_t *)&batt, sizeof(batt));
todotani 0:5e4210d108ac 133
YoshinoTaro 10:8a67578c3ef0 134 /* Randomize the heart rate. */
YoshinoTaro 10:8a67578c3ef0 135 hrmCounter = (rand() % 150) + 30;
YoshinoTaro 10:8a67578c3ef0 136 bpm[1] = hrmCounter;
YoshinoTaro 10:8a67578c3ef0 137 ble.gattServer().write(hrmChar.getValueAttribute().getHandle(), bpm, sizeof(bpm));
todotani 0:5e4210d108ac 138 }