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:
todotani
Date:
Fri Sep 05 14:26:54 2014 +0000
Revision:
2:daf2344afc28
Parent:
0:5e4210d108ac
Child:
5:ab8889077be9
BLE_Health_Thermometer for mbed HRM1017 with BLE library 0.1.0

Who changed what in which revision?

UserRevisionLine numberNew contents of line
todotani 0:5e4210d108ac 1 #include "mbed.h"
todotani 0:5e4210d108ac 2 #include "TMP102.h"
todotani 0:5e4210d108ac 3 #include "BLEDevice.h"
todotani 0:5e4210d108ac 4 #include "ble_hts.h"
todotani 0:5e4210d108ac 5
todotani 0:5e4210d108ac 6 #define NEED_CONSOLE_OUTPUT 1 /* Set this if you need debug messages on the console;
todotani 0:5e4210d108ac 7 * it will have an impact on code-size and power consumption. */
todotani 0:5e4210d108ac 8
todotani 0:5e4210d108ac 9 #if NEED_CONSOLE_OUTPUT
todotani 0:5e4210d108ac 10 Serial pc(USBTX, USBRX);
todotani 0:5e4210d108ac 11 #define DEBUG(...) { pc.printf(__VA_ARGS__); }
todotani 0:5e4210d108ac 12 #else
todotani 0:5e4210d108ac 13 #define DEBUG(...) /* nothing */
todotani 0:5e4210d108ac 14 #endif /* #if NEED_CONSOLE_OUTPUT */
todotani 0:5e4210d108ac 15
todotani 0:5e4210d108ac 16 const static char DEVICE_NAME[] = "HRM1017_HTM";
todotani 2:daf2344afc28 17 static volatile bool triggerSensorPolling = false;
todotani 0:5e4210d108ac 18
todotani 0:5e4210d108ac 19 BLEDevice ble;
todotani 0:5e4210d108ac 20 TMP102 healthThemometer(p22, p20, 0x90); /* The TMP102 connected to our board */
todotani 0:5e4210d108ac 21
todotani 0:5e4210d108ac 22 /* LEDs for indication: */
todotani 0:5e4210d108ac 23 DigitalOut oneSecondLed(LED1); /* LED1 is toggled every second. */
todotani 0:5e4210d108ac 24 DigitalOut advertisingStateLed(LED2); /* LED2 is on when we are advertising, otherwise off. */
todotani 0:5e4210d108ac 25
todotani 0:5e4210d108ac 26
todotani 0:5e4210d108ac 27 /* Health Thermometer Service */
todotani 0:5e4210d108ac 28 uint8_t thermTempPayload[5] = { 0, 0, 0, 0, 0 };
todotani 0:5e4210d108ac 29
todotani 0:5e4210d108ac 30 GattCharacteristic tempChar (GattCharacteristic::UUID_TEMPERATURE_MEASUREMENT_CHAR,
todotani 0:5e4210d108ac 31 thermTempPayload, 5, 5,
todotani 0:5e4210d108ac 32 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE);
todotani 0:5e4210d108ac 33 /* Battery Level Service */
todotani 0:5e4210d108ac 34 uint8_t batt = 100; /* Battery level */
todotani 0:5e4210d108ac 35 uint8_t read_batt = 0; /* Variable to hold battery level reads */
todotani 0:5e4210d108ac 36 GattCharacteristic battLevel ( GattCharacteristic::UUID_BATTERY_LEVEL_CHAR,
todotani 0:5e4210d108ac 37 (uint8_t *)batt, 1, 1,
todotani 0:5e4210d108ac 38 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);
todotani 0:5e4210d108ac 39 GattCharacteristic *htmChars[] = {&tempChar, };
todotani 0:5e4210d108ac 40 GattCharacteristic *battChars[] = {&battLevel, };
todotani 0:5e4210d108ac 41 GattService htmService(GattService::UUID_HEALTH_THERMOMETER_SERVICE, htmChars,
todotani 0:5e4210d108ac 42 sizeof(htmChars) / sizeof(GattCharacteristic *));
todotani 0:5e4210d108ac 43 GattService battService(GattService::UUID_BATTERY_SERVICE, battChars,
todotani 0:5e4210d108ac 44 sizeof(battChars) / sizeof(GattCharacteristic *));
todotani 0:5e4210d108ac 45
todotani 0:5e4210d108ac 46 uint16_t uuid16_list[] = {GattService::UUID_HEALTH_THERMOMETER_SERVICE,
todotani 0:5e4210d108ac 47 GattService::UUID_BATTERY_SERVICE};
todotani 0:5e4210d108ac 48
todotani 0:5e4210d108ac 49 uint32_t quick_ieee11073_from_float(float temperature);
todotani 0:5e4210d108ac 50 void updateServiceValues(void);
todotani 0:5e4210d108ac 51
todotani 0:5e4210d108ac 52 static Gap::ConnectionParams_t connectionParams;
todotani 0:5e4210d108ac 53
todotani 2:daf2344afc28 54 void disconnectionCallback(Gap::Handle_t handle, Gap::DisconnectionReason_t reason) // Mod
todotani 0:5e4210d108ac 55 {
todotani 0:5e4210d108ac 56 advertisingStateLed = 1;
todotani 0:5e4210d108ac 57
todotani 0:5e4210d108ac 58 DEBUG("Disconnected handle %u!\n\r", handle);
todotani 0:5e4210d108ac 59 DEBUG("Restarting the advertising process\n\r");
todotani 0:5e4210d108ac 60 ble.startAdvertising();
todotani 0:5e4210d108ac 61 }
todotani 0:5e4210d108ac 62
todotani 2:daf2344afc28 63 void onConnectionCallback(Gap::Handle_t handle, const Gap::ConnectionParams_t *params) //Mod
todotani 0:5e4210d108ac 64 {
todotani 0:5e4210d108ac 65 advertisingStateLed = 0;
todotani 0:5e4210d108ac 66
todotani 0:5e4210d108ac 67 DEBUG("connected. Got handle %u\r\n", handle);
todotani 0:5e4210d108ac 68
todotani 0:5e4210d108ac 69 connectionParams.slaveLatency = 1;
todotani 0:5e4210d108ac 70 if (ble.updateConnectionParams(handle, &connectionParams) != BLE_ERROR_NONE) {
todotani 0:5e4210d108ac 71 DEBUG("failed to update connection paramter\r\n");
todotani 0:5e4210d108ac 72 }
todotani 0:5e4210d108ac 73 }
todotani 0:5e4210d108ac 74
todotani 2:daf2344afc28 75 void periodicCallback(void)
todotani 2:daf2344afc28 76 {
todotani 2:daf2344afc28 77 oneSecondLed = !oneSecondLed; /* Do blinky on LED1 while we're waiting for BLE events */
todotani 2:daf2344afc28 78
todotani 2:daf2344afc28 79 /* Note that the periodicCallback() executes in interrupt context, so it is safer to do
todotani 2:daf2344afc28 80 * heavy-weight sensor polling from the main thread. */
todotani 2:daf2344afc28 81 triggerSensorPolling = true;
todotani 2:daf2344afc28 82 }
todotani 2:daf2344afc28 83
todotani 0:5e4210d108ac 84 /**************************************************************************/
todotani 0:5e4210d108ac 85 /*!
todotani 0:5e4210d108ac 86 @brief Program entry point
todotani 0:5e4210d108ac 87 */
todotani 0:5e4210d108ac 88 /**************************************************************************/
todotani 0:5e4210d108ac 89 int main(void)
todotani 0:5e4210d108ac 90 {
todotani 0:5e4210d108ac 91
todotani 0:5e4210d108ac 92 /* Setup blinky led */
todotani 0:5e4210d108ac 93 oneSecondLed = 1;
todotani 2:daf2344afc28 94 Ticker ticker;
todotani 2:daf2344afc28 95 ticker.attach(periodicCallback, 1);
todotani 2:daf2344afc28 96
todotani 2:daf2344afc28 97 DEBUG("Initialising the nRF51822\n");
todotani 0:5e4210d108ac 98 ble.init();
todotani 2:daf2344afc28 99 DEBUG("Init done\n");
todotani 0:5e4210d108ac 100 ble.onDisconnection(disconnectionCallback);
todotani 0:5e4210d108ac 101 ble.onConnection(onConnectionCallback);
todotani 0:5e4210d108ac 102
todotani 0:5e4210d108ac 103 ble.getPreferredConnectionParams(&connectionParams);
todotani 0:5e4210d108ac 104
todotani 0:5e4210d108ac 105 /* setup advertising */
todotani 0:5e4210d108ac 106 ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
todotani 0:5e4210d108ac 107 ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t*)uuid16_list, sizeof(uuid16_list));
todotani 0:5e4210d108ac 108 ble.accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_THERMOMETER);
todotani 0:5e4210d108ac 109 ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
todotani 0:5e4210d108ac 110 ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
todotani 0:5e4210d108ac 111 ble.setAdvertisingInterval(160); /* 100ms; in multiples of 0.625ms. */
todotani 0:5e4210d108ac 112 ble.startAdvertising();
todotani 0:5e4210d108ac 113 advertisingStateLed = 1;
todotani 2:daf2344afc28 114 DEBUG("Start Advertising\n");
todotani 0:5e4210d108ac 115
todotani 0:5e4210d108ac 116 ble.addService(htmService);
todotani 0:5e4210d108ac 117 ble.addService(battService);
todotani 2:daf2344afc28 118 DEBUG("Add Service\n");
todotani 0:5e4210d108ac 119
todotani 2:daf2344afc28 120 while (true) {
todotani 2:daf2344afc28 121 if (triggerSensorPolling) {
todotani 2:daf2344afc28 122 triggerSensorPolling = false;
todotani 2:daf2344afc28 123 updateServiceValues();
todotani 2:daf2344afc28 124 } else {
todotani 2:daf2344afc28 125 ble.waitForEvent();
todotani 2:daf2344afc28 126 }
todotani 0:5e4210d108ac 127 }
todotani 0:5e4210d108ac 128 }
todotani 0:5e4210d108ac 129
todotani 0:5e4210d108ac 130 /**************************************************************************/
todotani 0:5e4210d108ac 131 /*!
todotani 0:5e4210d108ac 132 @brief Ticker callback to switch advertisingStateLed state
todotani 0:5e4210d108ac 133 */
todotani 0:5e4210d108ac 134 /**************************************************************************/
todotani 0:5e4210d108ac 135 void updateServiceValues(void)
todotani 0:5e4210d108ac 136 {
todotani 0:5e4210d108ac 137 /* Decrement the battery level. */
todotani 0:5e4210d108ac 138 batt <=50 ? batt=100 : batt--;
todotani 0:5e4210d108ac 139
todotani 0:5e4210d108ac 140 /* Update the temperature. Note that we need to convert to an ieee11073 format float. */
todotani 0:5e4210d108ac 141 float temperature = healthThemometer.read();
todotani 0:5e4210d108ac 142 DEBUG("temp:%f\n", temperature);
todotani 0:5e4210d108ac 143 uint32_t temp_ieee11073 = quick_ieee11073_from_float(temperature);
todotani 0:5e4210d108ac 144 memcpy(thermTempPayload+1, &temp_ieee11073, 4);
todotani 2:daf2344afc28 145 ble.updateCharacteristicValue(tempChar.getValueAttribute().getHandle(), thermTempPayload, sizeof(thermTempPayload)); //Mod
todotani 2:daf2344afc28 146 ble.updateCharacteristicValue(battLevel.getValueAttribute().getHandle(), (uint8_t *)&batt, sizeof(batt)); //Mod
todotani 0:5e4210d108ac 147 }
todotani 0:5e4210d108ac 148
todotani 0:5e4210d108ac 149 /**
todotani 0:5e4210d108ac 150 * @brief A very quick conversion between a float temperature and 11073-20601 FLOAT-Type.
todotani 0:5e4210d108ac 151 * @param temperature The temperature as a float.
todotani 0:5e4210d108ac 152 * @return The temperature in 11073-20601 FLOAT-Type format.
todotani 0:5e4210d108ac 153 */
todotani 0:5e4210d108ac 154 uint32_t quick_ieee11073_from_float(float temperature)
todotani 0:5e4210d108ac 155 {
todotani 0:5e4210d108ac 156 uint8_t exponent = 0xFF; //exponent is -1
todotani 0:5e4210d108ac 157 uint32_t mantissa = (uint32_t)(temperature*10);
todotani 0:5e4210d108ac 158
todotani 0:5e4210d108ac 159 return ( ((uint32_t)exponent) << 24) | mantissa;
todotani 0:5e4210d108ac 160 }
todotani 0:5e4210d108ac 161