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:
ytsuboi
Date:
Mon Sep 08 16:59:22 2014 +0000
Revision:
6:c3d9dbadd654
Parent:
5:ab8889077be9
Child:
8:f753b4b022a8
BLE_Health_Thermometer; based on todotani-san's modify. libraries updated.

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