heart rate monitor

Dependencies:   BLE_API GroveEarbudSensor mbed nRF51822

Fork of BLE_HeartRate by Bluetooth Low Energy

Committer:
Rohit Grover
Date:
Tue Jun 10 11:03:03 2014 +0100
Revision:
8:49d8ee0aac11
Parent:
7:daab8ba5139e
Child:
9:5d693381e883
remove ticker; consumes un-necessary power; also added a satic const

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ktownsend 0:87a7fc231fae 1 /* mbed Microcontroller Library
ktownsend 0:87a7fc231fae 2 * Copyright (c) 2006-2013 ARM Limited
ktownsend 0:87a7fc231fae 3 *
ktownsend 0:87a7fc231fae 4 * Licensed under the Apache License, Version 2.0 (the "License");
ktownsend 0:87a7fc231fae 5 * you may not use this file except in compliance with the License.
ktownsend 0:87a7fc231fae 6 * You may obtain a copy of the License at
ktownsend 0:87a7fc231fae 7 *
ktownsend 0:87a7fc231fae 8 * http://www.apache.org/licenses/LICENSE-2.0
ktownsend 0:87a7fc231fae 9 *
ktownsend 0:87a7fc231fae 10 * Unless required by applicable law or agreed to in writing, software
ktownsend 0:87a7fc231fae 11 * distributed under the License is distributed on an "AS IS" BASIS,
ktownsend 0:87a7fc231fae 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
ktownsend 0:87a7fc231fae 13 * See the License for the specific language governing permissions and
ktownsend 0:87a7fc231fae 14 * limitations under the License.
ktownsend 0:87a7fc231fae 15 */
ktownsend 0:87a7fc231fae 16
ktownsend 0:87a7fc231fae 17 #include "mbed.h"
rgrover1 7:daab8ba5139e 18 #include "BLEPeripheral.h"
ktownsend 0:87a7fc231fae 19
rgrover1 7:daab8ba5139e 20 BLEPeripheral ble; /* BLE radio driver */
ktownsend 0:87a7fc231fae 21
Rohit Grover 3:24e2b056d229 22 DigitalOut led1(LED1);
Rohit Grover 3:24e2b056d229 23 Serial pc(USBTX, USBRX);
ktownsend 0:87a7fc231fae 24
ktownsend 0:87a7fc231fae 25 /* Battery Level Service */
Rohit Grover 3:24e2b056d229 26 uint8_t batt = 72; /* Battery level */
rgrover1 7:daab8ba5139e 27 uint8_t read_batt = 0; /* Variable to hold battery level reads */
Rohit Grover 3:24e2b056d229 28 GattService battService (GattService::UUID_BATTERY_SERVICE);
Rohit Grover 3:24e2b056d229 29 GattCharacteristic battLevel (GattCharacteristic::UUID_BATTERY_LEVEL_CHAR,
rgrover1 7:daab8ba5139e 30 1, /* initialLen */
rgrover1 7:daab8ba5139e 31 1, /* maxLen */
rgrover1 7:daab8ba5139e 32 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ);
ktownsend 0:87a7fc231fae 33
ktownsend 0:87a7fc231fae 34 /* Heart Rate Service */
ktownsend 0:87a7fc231fae 35 /* Service: https://developer.bluetooth.org/gatt/services/Pages/ServiceViewer.aspx?u=org.bluetooth.service.heart_rate.xml */
ktownsend 0:87a7fc231fae 36 /* HRM Char: https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.heart_rate_measurement.xml */
ktownsend 0:87a7fc231fae 37 /* Location: https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.body_sensor_location.xml */
Rohit Grover 3:24e2b056d229 38 GattService hrmService (GattService::UUID_HEART_RATE_SERVICE);
rgrover1 7:daab8ba5139e 39 GattCharacteristic hrmRate (GattCharacteristic::UUID_HEART_RATE_MEASUREMENT_CHAR,
rgrover1 7:daab8ba5139e 40 2, /* initialLen */
rgrover1 7:daab8ba5139e 41 3, /* maxLen */
rgrover1 7:daab8ba5139e 42 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);
rgrover1 7:daab8ba5139e 43 GattCharacteristic hrmLocation (GattCharacteristic::UUID_BODY_SENSOR_LOCATION_CHAR,
rgrover1 7:daab8ba5139e 44 1, /* initialLen */
rgrover1 7:daab8ba5139e 45 1, /* maxLen */
rgrover1 7:daab8ba5139e 46 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ);
ktownsend 0:87a7fc231fae 47
ktownsend 0:87a7fc231fae 48 /* Device Information service */
Rohit Grover 8:49d8ee0aac11 49 static const uint8_t deviceName[] = {'m', 'b', 'e', 'd'};
rgrover1 7:daab8ba5139e 50 GattService deviceInformationService (GattService::UUID_DEVICE_INFORMATION_SERVICE);
Rohit Grover 3:24e2b056d229 51 GattCharacteristic deviceManufacturer (
Rohit Grover 3:24e2b056d229 52 GattCharacteristic::UUID_MANUFACTURER_NAME_STRING_CHAR,
rgrover1 7:daab8ba5139e 53 sizeof(deviceName), /* initialLen */
rgrover1 7:daab8ba5139e 54 sizeof(deviceName), /* maxLen */
Rohit Grover 3:24e2b056d229 55 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ);
ktownsend 0:87a7fc231fae 56
rgrover1 7:daab8ba5139e 57 static const uint16_t uuid16_list[] = {
rgrover1 7:daab8ba5139e 58 GattService::UUID_BATTERY_SERVICE,
rgrover1 7:daab8ba5139e 59 GattService::UUID_DEVICE_INFORMATION_SERVICE,
rgrover1 7:daab8ba5139e 60 GattService::UUID_HEART_RATE_SERVICE
rgrover1 7:daab8ba5139e 61 };
ktownsend 0:87a7fc231fae 62
rgrover1 7:daab8ba5139e 63 void timeoutCallback(void)
ktownsend 0:87a7fc231fae 64 {
rgrover1 7:daab8ba5139e 65 pc.printf("Advertising Timeout!\n\r");
rgrover1 7:daab8ba5139e 66 // Restart the advertising process with a much slower interval,
rgrover1 7:daab8ba5139e 67 // only start advertising again after a button press, etc.
rgrover1 7:daab8ba5139e 68 }
ktownsend 0:87a7fc231fae 69
rgrover1 7:daab8ba5139e 70 void connectionCallback(void)
rgrover1 7:daab8ba5139e 71 {
rgrover1 7:daab8ba5139e 72 pc.printf("Connected!\n\r");
rgrover1 7:daab8ba5139e 73 }
ktownsend 0:87a7fc231fae 74
rgrover1 7:daab8ba5139e 75 void disconnectionCallback(void)
ktownsend 0:87a7fc231fae 76 {
rgrover1 7:daab8ba5139e 77 pc.printf("Disconnected!\n\r");
rgrover1 7:daab8ba5139e 78 pc.printf("Restarting the advertising process\n\r");
rgrover1 7:daab8ba5139e 79 ble.startAdvertising();
rgrover1 7:daab8ba5139e 80 }
Rohit Grover 3:24e2b056d229 81
rgrover1 7:daab8ba5139e 82 void updatesEnabledCallback(uint16_t charHandle)
rgrover1 7:daab8ba5139e 83 {
rgrover1 7:daab8ba5139e 84 if (charHandle == hrmRate.getHandle()) {
rgrover1 7:daab8ba5139e 85 pc.printf("Heart rate notify enabled\n\r");
ktownsend 0:87a7fc231fae 86 }
rgrover1 7:daab8ba5139e 87 }
ktownsend 0:87a7fc231fae 88
rgrover1 7:daab8ba5139e 89 void updatesDisabledCallback(uint16_t charHandle)
rgrover1 7:daab8ba5139e 90 {
rgrover1 7:daab8ba5139e 91 if (charHandle == hrmRate.getHandle()) {
rgrover1 7:daab8ba5139e 92 pc.printf("Heart rate notify disabled\n\r");
ktownsend 0:87a7fc231fae 93 }
rgrover1 7:daab8ba5139e 94 }
ktownsend 0:87a7fc231fae 95
ktownsend 0:87a7fc231fae 96 /**************************************************************************/
ktownsend 0:87a7fc231fae 97 /*!
ktownsend 0:87a7fc231fae 98 @brief Program entry point
ktownsend 0:87a7fc231fae 99 */
ktownsend 0:87a7fc231fae 100 /**************************************************************************/
ktownsend 0:87a7fc231fae 101 int main(void)
ktownsend 0:87a7fc231fae 102 {
Rohit Grover 3:24e2b056d229 103 led1 = 1;
ktownsend 0:87a7fc231fae 104
ktownsend 0:87a7fc231fae 105 /* Setup the local GAP/GATT event handlers */
rgrover1 7:daab8ba5139e 106 ble.onTimeout(timeoutCallback);
rgrover1 7:daab8ba5139e 107 ble.onConnection(connectionCallback);
rgrover1 7:daab8ba5139e 108 ble.onDisconnection(disconnectionCallback);
rgrover1 7:daab8ba5139e 109 ble.onUpdatesEnabled(updatesEnabledCallback);
rgrover1 7:daab8ba5139e 110 ble.onUpdatesDisabled(updatesDisabledCallback);
ktownsend 0:87a7fc231fae 111
ktownsend 0:87a7fc231fae 112 /* Initialise the nRF51822 */
ktownsend 0:87a7fc231fae 113 pc.printf("Initialising the nRF51822\n\r");
rgrover1 7:daab8ba5139e 114 ble.init();
ktownsend 0:87a7fc231fae 115
ktownsend 0:87a7fc231fae 116 /* Add BLE-Only flag and complete service list to the advertising data */
rgrover1 7:daab8ba5139e 117 ble.accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED);
rgrover1 7:daab8ba5139e 118 ble.accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list));
rgrover1 7:daab8ba5139e 119 ble.accumulateAdvertisingPayload(GapAdvertisingData::HEART_RATE_SENSOR_HEART_RATE_BELT);
ktownsend 0:87a7fc231fae 120
ktownsend 0:87a7fc231fae 121 /* Add the Battery Level service */
ktownsend 0:87a7fc231fae 122 battService.addCharacteristic(battLevel);
rgrover1 7:daab8ba5139e 123 ble.addService(battService);
ktownsend 0:87a7fc231fae 124
ktownsend 0:87a7fc231fae 125 /* Add the Device Information service */
ktownsend 0:87a7fc231fae 126 deviceInformationService.addCharacteristic(deviceManufacturer);
rgrover1 7:daab8ba5139e 127 ble.addService(deviceInformationService);
Rohit Grover 3:24e2b056d229 128
ktownsend 0:87a7fc231fae 129 /* Add the Heart Rate service */
ktownsend 0:87a7fc231fae 130 hrmService.addCharacteristic(hrmRate);
ktownsend 0:87a7fc231fae 131 hrmService.addCharacteristic(hrmLocation);
rgrover1 7:daab8ba5139e 132 ble.addService(hrmService);
Rohit Grover 3:24e2b056d229 133
rgrover1 7:daab8ba5139e 134 ble.setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
rgrover1 7:daab8ba5139e 135 ble.setAdvertisingInterval(160); /* 100ms; in multiples of 0.625ms. */
rgrover1 7:daab8ba5139e 136 ble.startAdvertising();
Rohit Grover 3:24e2b056d229 137
Rohit Grover 3:24e2b056d229 138 /* Wait until we are connected to a central device before updating
Rohit Grover 3:24e2b056d229 139 * anything */
ktownsend 0:87a7fc231fae 140 pc.printf("Waiting for a connection ...");
rgrover1 7:daab8ba5139e 141 while (!ble.getGapState().connected) {
rgrover1 7:daab8ba5139e 142 ble.waitForEvent();
ktownsend 0:87a7fc231fae 143 }
ktownsend 0:87a7fc231fae 144 pc.printf("Connected!\n\r");
Rohit Grover 3:24e2b056d229 145
rgrover1 7:daab8ba5139e 146 /* Now that we're live, update the battery level characteristic, and
rgrover1 7:daab8ba5139e 147 * change the device manufacturer characteristic to 'mbed' */
rgrover1 7:daab8ba5139e 148 ble.updateCharacteristicValue(battLevel.getHandle(), (uint8_t *)&batt, sizeof(batt));
rgrover1 7:daab8ba5139e 149 ble.updateCharacteristicValue(deviceManufacturer.getHandle(), deviceName, sizeof(deviceName));
ktownsend 0:87a7fc231fae 150
ktownsend 0:87a7fc231fae 151 /* Set the heart rate monitor location (one time only) */
ktownsend 0:87a7fc231fae 152 /* See --> https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.body_sensor_location.xml */
rgrover1 7:daab8ba5139e 153 uint8_t location = 0x03; /* Finger */
ktownsend 0:87a7fc231fae 154 uint8_t hrmCounter = 100;
rgrover1 7:daab8ba5139e 155 ble.updateCharacteristicValue(hrmLocation.getHandle(), (uint8_t *)&location, sizeof(location));
ktownsend 0:87a7fc231fae 156
ktownsend 0:87a7fc231fae 157 /* Do blinky on LED1 while we're waiting for BLE events */
Rohit Grover 3:24e2b056d229 158 for (;; ) {
Rohit Grover 3:24e2b056d229 159 led1 = !led1;
Rohit Grover 3:24e2b056d229 160 wait(1);
Rohit Grover 3:24e2b056d229 161
Rohit Grover 3:24e2b056d229 162 /* Update battery level */
Rohit Grover 3:24e2b056d229 163 batt++;
Rohit Grover 3:24e2b056d229 164 if (batt > 100) {
Rohit Grover 3:24e2b056d229 165 batt = 72;
Rohit Grover 3:24e2b056d229 166 }
rgrover1 7:daab8ba5139e 167 ble.updateCharacteristicValue(battLevel.getHandle(), (uint8_t *)&batt, sizeof(batt));
ktownsend 0:87a7fc231fae 168
rgrover1 7:daab8ba5139e 169 /* Update the HRM measurement */
rgrover1 7:daab8ba5139e 170 /* First byte = 8-bit values, no extra info, Second byte = uint8_t HRM value */
rgrover1 7:daab8ba5139e 171 /* See --> https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.heart_rate_measurement.xml */
Rohit Grover 3:24e2b056d229 172 hrmCounter++;
Rohit Grover 3:24e2b056d229 173 if (hrmCounter == 175) {
Rohit Grover 3:24e2b056d229 174 hrmCounter = 100;
Rohit Grover 3:24e2b056d229 175 }
Rohit Grover 3:24e2b056d229 176 uint8_t bpm[2] = {0x00, hrmCounter};
rgrover1 7:daab8ba5139e 177 ble.updateCharacteristicValue(hrmRate.getHandle(), bpm, sizeof(bpm));
ktownsend 0:87a7fc231fae 178 }
ktownsend 0:87a7fc231fae 179 }