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

Files at this revision

API Documentation at this revision

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

Changed in this revision

TMP102.lib Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
--- a/TMP102.lib	Fri Nov 27 12:31:49 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-http://mbed.org/users/chris/code/TMP102/#694792b93731
--- a/main.cpp	Fri Nov 27 12:31:49 2015 +0000
+++ b/main.cpp	Mon Aug 22 06:12:27 2016 +0000
@@ -1,60 +1,72 @@
 #include "mbed.h"
-#include "TMP102.h"
 #include "BLE.h"
+#include <math.h>
 
-#define NEED_CONSOLE_OUTPUT 1 /* Set this if you need debug messages on the console;
-                               * it will have an impact on code-size and power consumption. */
 
-#if NEED_CONSOLE_OUTPUT
-Serial  pc(USBTX, USBRX);
-#define DEBUG(...) { pc.printf(__VA_ARGS__); }
+#define NEED_DEBUG 1 
+#if NEED_DEBUG
+#define DEBUG(...) { printf(__VA_ARGS__); }
 #else
 #define DEBUG(...) /* nothing */
-#endif /* #if NEED_CONSOLE_OUTPUT */
+#endif 
+
 
-const static char  DEVICE_NAME[] = "HRM1017_HTM";
+const static char  DEVICE_NAME[] = "mbed HRM1017";
 static volatile bool  triggerSensorPolling = false;
 
+
 BLEDevice  ble;
-TMP102      healthThemometer(I2C_SDA0, I2C_SCL0, 0x90);  /* The TMP102 connected to our board */
-//TMP102      healthThemometer(I2C_SDA1, I2C_SCL1, 0x90);  /* The TMP102 connected to our board */
+
 
-/* LEDs for indication: */
-DigitalOut  oneSecondLed(LED1);        /* LED1 is toggled every second. */
-DigitalOut  advertisingStateLed(LED2); /* LED2 is on when we are advertising, otherwise off. */
+/* 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 *));
 
 
-/* Health Thermometer Service */ 
-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);
 /* Battery Level Service */
-uint8_t            batt = 100;     /* Battery level */
-uint8_t            read_batt = 0;  /* Variable to hold battery level reads */
-GattCharacteristic battLevel ( GattCharacteristic::UUID_BATTERY_LEVEL_CHAR, 
-                                 (uint8_t *)batt, 1, 1,
-                                 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);
-GattCharacteristic *htmChars[] = {&tempChar, };
-GattCharacteristic *battChars[] = {&battLevel, };
-GattService        htmService(GattService::UUID_HEALTH_THERMOMETER_SERVICE, htmChars, 
-                                sizeof(htmChars) / sizeof(GattCharacteristic *));
-GattService        battService(GattService::UUID_BATTERY_SERVICE, battChars,
-                                sizeof(battChars) / sizeof(GattCharacteristic *));
+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 *));
+
+
 
-uint16_t             uuid16_list[] = {GattService::UUID_HEALTH_THERMOMETER_SERVICE,
-                                      GattService::UUID_BATTERY_SERVICE};
+/* 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 *));
 
-uint32_t quick_ieee11073_from_float(float temperature);
+
+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)    // Mod
+void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
 {
-    advertisingStateLed = 1;
-    
     DEBUG("Disconnected handle %u, reason %u\r\n", params->handle, params->reason);
     DEBUG("Restarting the advertising process\r\n");
     ble.gap().startAdvertising();
@@ -62,8 +74,6 @@
 
 void onConnectionCallback(const Gap::ConnectionCallbackParams_t *params)   //Mod
 {
-    advertisingStateLed = 0;
-
     DEBUG("connected. Got handle %u\r\n", params->handle);
 
     connectionParams.slaveLatency = 1;
@@ -74,23 +84,11 @@
 
 void periodicCallback(void)
 {
-    oneSecondLed = !oneSecondLed; /* Do blinky on LED1 while we're waiting for BLE events */
-
-    /* Note that the periodicCallback() executes in interrupt context, so it is safer to do
-     * heavy-weight sensor polling from the main thread. */
     triggerSensorPolling = true;
 }
 
-/**************************************************************************/
-/*!
-    @brief  Program entry point
-*/
-/**************************************************************************/
 int main(void)
-{
-    
-    /* Setup blinky led */
-    oneSecondLed = 1;
+{    
     Ticker ticker;
     ticker.attach(periodicCallback, 1);
        
@@ -105,16 +103,16 @@
     /* 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_THERMOMETER);
+    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();
-    advertisingStateLed = 1;
     DEBUG("Start Advertising\r\n");
 
-    ble.gattServer().addService(htmService);
+    ble.gattServer().addService(hrmService);
     ble.gattServer().addService(battService);
+    ble.gattServer().addService(deviceInformationService);
     DEBUG("Add Service\r\n");
 
     while (true) {
@@ -127,34 +125,14 @@
     }
 }
 
-/**************************************************************************/
-/*!
-    @brief  Ticker callback to switch advertisingStateLed state
-*/
-/**************************************************************************/
 void updateServiceValues(void)
 {
-      /* Decrement the battery level. */
-      batt <=50 ? batt=100 : batt--;
-      
-      /* Update the temperature. Note that we need to convert to an ieee11073 format float. */
-      float temperature = healthThemometer.read();
-      DEBUG("temp:%f\r\n", temperature);
-      uint32_t temp_ieee11073 = quick_ieee11073_from_float(temperature);
-      memcpy(thermTempPayload+1, &temp_ieee11073, 4);
-      ble.gattServer().write(tempChar.getValueAttribute().getHandle(), thermTempPayload, sizeof(thermTempPayload));  //Mod
-      ble.gattServer().write(battLevel.getValueAttribute().getHandle(), (uint8_t *)&batt, sizeof(batt));             //Mod
-}
+    /* Decrement the battery level. */
+    batt <= 50 ? batt = 100 : batt--;
+    ble.gattServer().write(battLevel.getValueAttribute().getHandle(), (uint8_t *)&batt, sizeof(batt));
 
-/**
- * @brief A very quick conversion between a float temperature and 11073-20601 FLOAT-Type.
- * @param temperature The temperature as a float.
- * @return The temperature in 11073-20601 FLOAT-Type format.
- */
-uint32_t quick_ieee11073_from_float(float temperature)
-{
-    uint8_t  exponent = 0xFF; //exponent is -1
-    uint32_t mantissa = (uint32_t)(temperature*10);
-    
-    return ( ((uint32_t)exponent) << 24) | mantissa;
+    /* Randomize the heart rate. */
+    hrmCounter = (rand() % 150) + 30;
+    bpm[1] = hrmCounter;
+    ble.gattServer().write(hrmChar.getValueAttribute().getHandle(), bpm, sizeof(bpm));
 }