Add HeartRateMonitor

Dependencies:   BLE_API_Native_TBO TMP102 mbed

Fork of BLE_Health_Thermometer_IRC by Yoshihiro TSUBOI

Committer:
ghz2000
Date:
Mon Jun 16 15:13:32 2014 +0000
Revision:
5:0b26ee423037
Parent:
2:f11df1469db2
Add HeartRateMonitor

Who changed what in which revision?

UserRevisionLine numberNew contents of line
donalm 0:701da26ee5cb 1 /* mbed Microcontroller Library
donalm 0:701da26ee5cb 2 * Copyright (c) 2006-2014 ARM Limited
donalm 0:701da26ee5cb 3 *
donalm 0:701da26ee5cb 4 * Licensed under the Apache License, Version 2.0 (the "License");
donalm 0:701da26ee5cb 5 * you may not use this file except in compliance with the License.
donalm 0:701da26ee5cb 6 * You may obtain a copy of the License at
donalm 0:701da26ee5cb 7 *
donalm 0:701da26ee5cb 8 * http://www.apache.org/licenses/LICENSE-2.0
donalm 0:701da26ee5cb 9 *
donalm 0:701da26ee5cb 10 * Unless required by applicable law or agreed to in writing, software
donalm 0:701da26ee5cb 11 * distributed under the License is distributed on an "AS IS" BASIS,
donalm 0:701da26ee5cb 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
donalm 0:701da26ee5cb 13 * See the License for the specific language governing permissions and
donalm 0:701da26ee5cb 14 * limitations under the License.
donalm 0:701da26ee5cb 15 */
donalm 0:701da26ee5cb 16
donalm 0:701da26ee5cb 17 #include "mbed.h"
donalm 0:701da26ee5cb 18 #include "TMP102.h"
donalm 0:701da26ee5cb 19 #include "nRF51822n.h"
donalm 0:701da26ee5cb 20
donalm 0:701da26ee5cb 21 nRF51822n nrf; /* BLE radio driver */
donalm 0:701da26ee5cb 22 TMP102 healthThemometer(p22, p20, 0x90); /* The TMP102 connected to our board */
donalm 0:701da26ee5cb 23
donalm 2:f11df1469db2 24 /* LEDs for indication: */
donalm 2:f11df1469db2 25 DigitalOut oneSecondLed(LED1); /* LED1 is toggled every second. */
donalm 2:f11df1469db2 26 DigitalOut advertisingStateLed(LED2); /* LED2 is on when we are advertising, otherwise off. */
donalm 0:701da26ee5cb 27
donalm 0:701da26ee5cb 28
donalm 0:701da26ee5cb 29 /* Health Thermometer Service */
donalm 0:701da26ee5cb 30 uint8_t thermTempPayload[5] = { 0, 0, 0, 0, 0 };
donalm 0:701da26ee5cb 31 GattService thermService (GattService::UUID_HEALTH_THERMOMETER_SERVICE);
donalm 0:701da26ee5cb 32 GattCharacteristic thermTemp (GattCharacteristic::UUID_TEMPERATURE_MEASUREMENT_CHAR,
donalm 0:701da26ee5cb 33 5, 5, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE);
donalm 0:701da26ee5cb 34
ghz2000 5:0b26ee423037 35 /* Heart Rate Servece */
ghz2000 5:0b26ee423037 36 uint8_t heartRate = 100;
ghz2000 5:0b26ee423037 37 uint8_t heartRatePayload[8] = { 0,0,0,0,0,0,0,0};
ghz2000 5:0b26ee423037 38 GattService heartRateService (GattService::UUID_HEART_RATE_SERVICE);
ghz2000 5:0b26ee423037 39 GattCharacteristic heartRateChar (GattCharacteristic::UUID_HEART_RATE_MEASUREMENT_CHAR,
ghz2000 5:0b26ee423037 40 8,8, GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY);
ghz2000 5:0b26ee423037 41
ghz2000 5:0b26ee423037 42
donalm 0:701da26ee5cb 43 /* Battery Level Service */
donalm 0:701da26ee5cb 44 uint8_t batt = 100; /* Battery level */
donalm 0:701da26ee5cb 45 uint8_t read_batt = 0; /* Variable to hold battery level reads */
donalm 0:701da26ee5cb 46 GattService battService ( GattService::UUID_BATTERY_SERVICE );
donalm 0:701da26ee5cb 47 GattCharacteristic battLevel ( GattCharacteristic::UUID_BATTERY_LEVEL_CHAR, 1, 1,
donalm 0:701da26ee5cb 48 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY |
donalm 0:701da26ee5cb 49 GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ);
donalm 0:701da26ee5cb 50
donalm 0:701da26ee5cb 51
ghz2000 5:0b26ee423037 52
donalm 0:701da26ee5cb 53 /* Advertising data and parameters */
donalm 0:701da26ee5cb 54 GapAdvertisingData advData;
donalm 0:701da26ee5cb 55 GapAdvertisingData scanResponse;
donalm 0:701da26ee5cb 56 GapAdvertisingParams advParams ( GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED );
donalm 2:f11df1469db2 57
donalm 0:701da26ee5cb 58 uint16_t uuid16_list[] = {GattService::UUID_HEALTH_THERMOMETER_SERVICE,
ghz2000 5:0b26ee423037 59 GattService::UUID_BATTERY_SERVICE,
ghz2000 5:0b26ee423037 60 GattService::UUID_HEART_RATE_SERVICE};
donalm 0:701da26ee5cb 61
donalm 0:701da26ee5cb 62 uint32_t quick_ieee11073_from_float(float temperature);
donalm 0:701da26ee5cb 63 void updateServiceValues(void);
donalm 0:701da26ee5cb 64
donalm 0:701da26ee5cb 65 /**************************************************************************/
donalm 0:701da26ee5cb 66 /*!
donalm 0:701da26ee5cb 67 @brief This custom class can be used to override any GapEvents
donalm 0:701da26ee5cb 68 that you are interested in handling on an application level.
donalm 0:701da26ee5cb 69 */
donalm 0:701da26ee5cb 70 /**************************************************************************/
donalm 0:701da26ee5cb 71 class GapEventHandler : public GapEvents
donalm 0:701da26ee5cb 72 {
donalm 2:f11df1469db2 73 //virtual void onTimeout(void) {}
donalm 2:f11df1469db2 74
donalm 0:701da26ee5cb 75 virtual void onConnected(void)
donalm 0:701da26ee5cb 76 {
donalm 2:f11df1469db2 77 advertisingStateLed = 0;
donalm 0:701da26ee5cb 78 }
donalm 0:701da26ee5cb 79
donalm 2:f11df1469db2 80 /* When a client device disconnects we need to start advertising again. */
donalm 0:701da26ee5cb 81 virtual void onDisconnected(void)
donalm 0:701da26ee5cb 82 {
donalm 0:701da26ee5cb 83 nrf.getGap().startAdvertising(advParams);
donalm 2:f11df1469db2 84 advertisingStateLed = 1;
donalm 0:701da26ee5cb 85 }
donalm 0:701da26ee5cb 86 };
donalm 0:701da26ee5cb 87
donalm 0:701da26ee5cb 88 /**************************************************************************/
donalm 0:701da26ee5cb 89 /*!
donalm 0:701da26ee5cb 90 @brief Program entry point
donalm 0:701da26ee5cb 91 */
donalm 0:701da26ee5cb 92 /**************************************************************************/
donalm 0:701da26ee5cb 93 int main(void)
donalm 0:701da26ee5cb 94 {
donalm 2:f11df1469db2 95
donalm 2:f11df1469db2 96 /* Setup blinky led */
donalm 2:f11df1469db2 97 oneSecondLed=1;
donalm 0:701da26ee5cb 98
donalm 2:f11df1469db2 99 /* Setup an event handler for GAP events i.e. Client/Server connection events. */
donalm 0:701da26ee5cb 100 nrf.getGap().setEventHandler(new GapEventHandler());
donalm 2:f11df1469db2 101
donalm 0:701da26ee5cb 102 /* Initialise the nRF51822 */
donalm 0:701da26ee5cb 103 nrf.init();
donalm 0:701da26ee5cb 104
donalm 0:701da26ee5cb 105 /* Make sure we get a clean start */
donalm 0:701da26ee5cb 106 nrf.reset();
donalm 0:701da26ee5cb 107
donalm 0:701da26ee5cb 108 /* Add BLE-Only flag and complete service list to the advertising data */
donalm 0:701da26ee5cb 109 advData.addFlags(GapAdvertisingData::BREDR_NOT_SUPPORTED);
donalm 0:701da26ee5cb 110 advData.addData(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS,
donalm 0:701da26ee5cb 111 (uint8_t*)uuid16_list, sizeof(uuid16_list));
donalm 0:701da26ee5cb 112 advData.addAppearance(GapAdvertisingData::GENERIC_THERMOMETER);
donalm 0:701da26ee5cb 113 nrf.getGap().setAdvertisingData(advData, scanResponse);
donalm 0:701da26ee5cb 114
donalm 0:701da26ee5cb 115 /* Health Thermometer Service */
donalm 0:701da26ee5cb 116 thermService.addCharacteristic(thermTemp);
donalm 0:701da26ee5cb 117 nrf.getGattServer().addService(thermService);
donalm 0:701da26ee5cb 118
ghz2000 5:0b26ee423037 119 /* Heart Rate Service */
ghz2000 5:0b26ee423037 120 heartRateService.addCharacteristic(heartRateChar);
ghz2000 5:0b26ee423037 121 nrf.getGattServer().addService(heartRateService);
ghz2000 5:0b26ee423037 122
donalm 0:701da26ee5cb 123 /* Add the Battery Level service */
donalm 0:701da26ee5cb 124 battService.addCharacteristic(battLevel);
donalm 0:701da26ee5cb 125 nrf.getGattServer().addService(battService);
donalm 0:701da26ee5cb 126
donalm 0:701da26ee5cb 127 /* Start advertising (make sure you've added all your data first) */
donalm 0:701da26ee5cb 128 nrf.getGap().startAdvertising(advParams);
donalm 2:f11df1469db2 129 advertisingStateLed = 1;
donalm 0:701da26ee5cb 130
donalm 0:701da26ee5cb 131 for (;;)
donalm 0:701da26ee5cb 132 {
donalm 2:f11df1469db2 133 /* Now that we're live, update the battery level & temperature characteristics */
donalm 2:f11df1469db2 134 updateServiceValues();
donalm 0:701da26ee5cb 135 wait(1);
donalm 0:701da26ee5cb 136 }
donalm 0:701da26ee5cb 137 }
donalm 0:701da26ee5cb 138
donalm 0:701da26ee5cb 139 /**************************************************************************/
donalm 0:701da26ee5cb 140 /*!
donalm 2:f11df1469db2 141 @brief Ticker callback to switch advertisingStateLed state
donalm 0:701da26ee5cb 142 */
donalm 0:701da26ee5cb 143 /**************************************************************************/
ghz2000 5:0b26ee423037 144
ghz2000 5:0b26ee423037 145 int sec = 0;
ghz2000 5:0b26ee423037 146
donalm 0:701da26ee5cb 147 void updateServiceValues(void)
donalm 0:701da26ee5cb 148 {
donalm 2:f11df1469db2 149 /* Toggle the one second LEDs */
donalm 2:f11df1469db2 150 oneSecondLed = !oneSecondLed;
donalm 0:701da26ee5cb 151
donalm 0:701da26ee5cb 152 /* Update battery level */
donalm 0:701da26ee5cb 153 nrf.getGattServer().updateValue(battLevel.handle, (uint8_t*)&batt, sizeof(batt));
donalm 2:f11df1469db2 154 /* Decrement the battery level. */
donalm 2:f11df1469db2 155 batt <=50 ? batt=100 : batt--;;
donalm 0:701da26ee5cb 156
donalm 2:f11df1469db2 157 /* Update the temperature. Note that we need to convert to an ieee11073 format float. */
donalm 0:701da26ee5cb 158 float temperature = healthThemometer.read();
donalm 0:701da26ee5cb 159 uint32_t temp_ieee11073 = quick_ieee11073_from_float(temperature);
donalm 0:701da26ee5cb 160 memcpy(thermTempPayload+1, &temp_ieee11073, 4);
donalm 0:701da26ee5cb 161 nrf.getGattServer().updateValue(thermTemp.handle, thermTempPayload, sizeof(thermTempPayload));
ghz2000 5:0b26ee423037 162
ghz2000 5:0b26ee423037 163 /* Update the HeartRate */
ghz2000 5:0b26ee423037 164 if(sec ==3){
ghz2000 5:0b26ee423037 165 if(heartRate < 200)heartRate++;
ghz2000 5:0b26ee423037 166 else heartRate = 0;
ghz2000 5:0b26ee423037 167 sec = 0;
ghz2000 5:0b26ee423037 168 }else{
ghz2000 5:0b26ee423037 169 sec++;
ghz2000 5:0b26ee423037 170 }
ghz2000 5:0b26ee423037 171 uint8_t heartRateFlags = 0x00;
ghz2000 5:0b26ee423037 172 heartRatePayload[0] = heartRateFlags;
ghz2000 5:0b26ee423037 173 heartRatePayload[1] = heartRate;
ghz2000 5:0b26ee423037 174 nrf.getGattServer().updateValue(heartRateChar.handle, heartRatePayload , sizeof(heartRatePayload));
donalm 0:701da26ee5cb 175 }
donalm 0:701da26ee5cb 176
donalm 0:701da26ee5cb 177 /**
donalm 0:701da26ee5cb 178 * @brief A very quick conversion between a float temperature and 11073-20601 FLOAT-Type.
donalm 0:701da26ee5cb 179 * @param temperature The temperature as a float.
donalm 0:701da26ee5cb 180 * @return The temperature in 11073-20601 FLOAT-Type format.
donalm 0:701da26ee5cb 181 */
donalm 0:701da26ee5cb 182 uint32_t quick_ieee11073_from_float(float temperature)
donalm 0:701da26ee5cb 183 {
donalm 0:701da26ee5cb 184 uint8_t exponent = 0xFF; //exponent is -1
donalm 0:701da26ee5cb 185 uint32_t mantissa = (uint32_t)(temperature*10);
donalm 0:701da26ee5cb 186
donalm 0:701da26ee5cb 187 return ( ((uint32_t)exponent) << 24) | mantissa;
donalm 2:f11df1469db2 188 }
donalm 2:f11df1469db2 189