mbed code for UberVest health monitoring

Dependencies:   BLE_API mbed nRF51822

Committer:
haydenball
Date:
Mon Nov 23 15:48:07 2015 +0000
Revision:
6:808cfc0b9480
Parent:
5:40fcfb34e48f
Child:
7:7e1a474ca416
Updated with temperature as well

Who changed what in which revision?

UserRevisionLine numberNew contents of line
haydenball 0:b6fae6eb2bfe 1 /* mbed Microcontroller Library
haydenball 0:b6fae6eb2bfe 2 * Copyright (c) 2006-2013 ARM Limited
haydenball 0:b6fae6eb2bfe 3 *
haydenball 0:b6fae6eb2bfe 4 * Licensed under the Apache License, Version 2.0 (the "License");
haydenball 0:b6fae6eb2bfe 5 * you may not use this file except in compliance with the License.
haydenball 0:b6fae6eb2bfe 6 * You may obtain a copy of the License at
haydenball 0:b6fae6eb2bfe 7 *
haydenball 0:b6fae6eb2bfe 8 * http://www.apache.org/licenses/LICENSE-2.0
haydenball 0:b6fae6eb2bfe 9 *
haydenball 0:b6fae6eb2bfe 10 * Unless required by applicable law or agreed to in writing, software
haydenball 0:b6fae6eb2bfe 11 * distributed under the License is distributed on an "AS IS" BASIS,
haydenball 0:b6fae6eb2bfe 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
haydenball 0:b6fae6eb2bfe 13 * See the License for the specific language governing permissions and
haydenball 0:b6fae6eb2bfe 14 * limitations under the License.
haydenball 0:b6fae6eb2bfe 15 */
haydenball 6:808cfc0b9480 16
haydenball 6:808cfc0b9480 17 #define TARGET_NRF_LFCLK_RC 1
haydenball 0:b6fae6eb2bfe 18
haydenball 0:b6fae6eb2bfe 19 #include "mbed.h"
haydenball 0:b6fae6eb2bfe 20 #include "BLE.h"
haydenball 0:b6fae6eb2bfe 21 #include "UberVestService.h"
haydenball 6:808cfc0b9480 22 #include <math.h>
haydenball 6:808cfc0b9480 23
haydenball 6:808cfc0b9480 24 // BEGIN IO
haydenball 6:808cfc0b9480 25 // Inputs and outputs need to be changed between the devkit and prospeckz
haydenball 0:b6fae6eb2bfe 26
haydenball 4:851d3f52c344 27 // Outputs
haydenball 4:851d3f52c344 28 DigitalOut connectionLed(LED1);
haydenball 4:851d3f52c344 29
haydenball 4:851d3f52c344 30 // Inputs
haydenball 6:808cfc0b9480 31 AnalogIn ecg(p6);
haydenball 6:808cfc0b9480 32 AnalogIn pulse(p1);
haydenball 6:808cfc0b9480 33 AnalogIn temp(p2);
haydenball 4:851d3f52c344 34
haydenball 6:808cfc0b9480 35 // N.B. The devkit and prospeckz are different - DK is active low, prospeckz is active high.
haydenball 6:808cfc0b9480 36 static const bool LED_ON = 1;
haydenball 6:808cfc0b9480 37 static const bool LED_OFF = 0;
haydenball 6:808cfc0b9480 38
haydenball 6:808cfc0b9480 39 // END IO
haydenball 6:808cfc0b9480 40
haydenball 6:808cfc0b9480 41 BLE ble;
haydenball 0:b6fae6eb2bfe 42
haydenball 0:b6fae6eb2bfe 43 const static char DEVICE_NAME[] = "UberVest";
haydenball 0:b6fae6eb2bfe 44 static const uint16_t uuid16_list[] = {UberVestService::UBER_VEST_SERVICE_UUID};
haydenball 0:b6fae6eb2bfe 45
haydenball 6:808cfc0b9480 46 static int8_t ecgValue;
haydenball 6:808cfc0b9480 47 static int8_t pulseValue;
haydenball 6:808cfc0b9480 48 static int8_t tempValue;
haydenball 4:851d3f52c344 49
haydenball 6:808cfc0b9480 50 static volatile bool sampleEcg = false;
haydenball 6:808cfc0b9480 51 static volatile bool samplePulse = false;
haydenball 6:808cfc0b9480 52 static volatile bool sampleTemp = false;
haydenball 0:b6fae6eb2bfe 53
haydenball 0:b6fae6eb2bfe 54 UberVestService *uberVestServicePtr;
haydenball 0:b6fae6eb2bfe 55
haydenball 6:808cfc0b9480 56 Serial pc(USBTX, USBRX);
haydenball 0:b6fae6eb2bfe 57
haydenball 2:9b977e86e2d5 58 void connectionCallback(const Gap::ConnectionCallbackParams_t *params)
haydenball 2:9b977e86e2d5 59 {
haydenball 6:808cfc0b9480 60 connectionLed = LED_OFF;
haydenball 2:9b977e86e2d5 61 }
haydenball 2:9b977e86e2d5 62
haydenball 0:b6fae6eb2bfe 63 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
haydenball 0:b6fae6eb2bfe 64 {
haydenball 0:b6fae6eb2bfe 65 ble.gap().startAdvertising();
haydenball 6:808cfc0b9480 66 connectionLed = LED_ON;
haydenball 6:808cfc0b9480 67 }
haydenball 6:808cfc0b9480 68
haydenball 6:808cfc0b9480 69 void sampleEcgCallback(void)
haydenball 6:808cfc0b9480 70 {
haydenball 6:808cfc0b9480 71 sampleEcg = true;
haydenball 6:808cfc0b9480 72 }
haydenball 6:808cfc0b9480 73
haydenball 6:808cfc0b9480 74 void samplePulseCallback(void)
haydenball 6:808cfc0b9480 75 {
haydenball 6:808cfc0b9480 76 //samplePulse = true;
haydenball 6:808cfc0b9480 77 }
haydenball 6:808cfc0b9480 78
haydenball 6:808cfc0b9480 79 void sampleTempCallback(void)
haydenball 6:808cfc0b9480 80 {
haydenball 6:808cfc0b9480 81 sampleTemp = true;
haydenball 6:808cfc0b9480 82 }
haydenball 6:808cfc0b9480 83
haydenball 6:808cfc0b9480 84 void flasherTimer(void)
haydenball 6:808cfc0b9480 85 {
haydenball 6:808cfc0b9480 86 if (!ble.getGapState().connected) {
haydenball 6:808cfc0b9480 87 connectionLed = !connectionLed;
haydenball 6:808cfc0b9480 88 }
haydenball 0:b6fae6eb2bfe 89 }
haydenball 0:b6fae6eb2bfe 90
haydenball 6:808cfc0b9480 91 float getTemp(void)
haydenball 4:851d3f52c344 92 {
haydenball 6:808cfc0b9480 93 const int TEMP_RESISTOR_VALUE = 10830;
haydenball 6:808cfc0b9480 94 float rawValue;
haydenball 6:808cfc0b9480 95 float r; // Thermistor resistance
haydenball 6:808cfc0b9480 96 double convertedTemp;
haydenball 6:808cfc0b9480 97
haydenball 6:808cfc0b9480 98 rawValue = temp.read();
haydenball 6:808cfc0b9480 99 // The thermistor is set up as a simple voltage divider. We can get the resistance as follows:
haydenball 6:808cfc0b9480 100 r = ((1 / rawValue) * TEMP_RESISTOR_VALUE) - TEMP_RESISTOR_VALUE;
haydenball 6:808cfc0b9480 101
haydenball 6:808cfc0b9480 102 // Now calculate the temperature from the resistance
haydenball 6:808cfc0b9480 103 // From the thermistor data sheet (http://www.farnell.com/datasheets/1784420.pdf):
haydenball 6:808cfc0b9480 104 const float R_REF = 10000;
haydenball 6:808cfc0b9480 105 const double A = 3.354016e-03;
haydenball 6:808cfc0b9480 106 const double B = 2.569850e-04;
haydenball 6:808cfc0b9480 107 const double C = 2.620131e-06;
haydenball 6:808cfc0b9480 108 const double D = 6.383091e-08;
haydenball 6:808cfc0b9480 109
haydenball 6:808cfc0b9480 110 convertedTemp = A + B * (log(r / R_REF)) + C * pow(log(r / R_REF), 2.0f) + D * pow(log(r / R_REF), 3.0f);
haydenball 6:808cfc0b9480 111 convertedTemp = 1 / convertedTemp;
haydenball 6:808cfc0b9480 112
haydenball 6:808cfc0b9480 113 // convert to degrees celsius:
haydenball 6:808cfc0b9480 114 convertedTemp = convertedTemp - 273;
haydenball 6:808cfc0b9480 115
haydenball 6:808cfc0b9480 116 pc.printf("Raw: %f, Resisance: %f, Temp: %f\r\n", rawValue, r, convertedTemp);
haydenball 6:808cfc0b9480 117
haydenball 6:808cfc0b9480 118 return (float) convertedTemp;
haydenball 4:851d3f52c344 119 }
haydenball 4:851d3f52c344 120
haydenball 0:b6fae6eb2bfe 121 int main(void)
haydenball 0:b6fae6eb2bfe 122 {
haydenball 0:b6fae6eb2bfe 123 ble.init();
haydenball 2:9b977e86e2d5 124 ble.gap().onConnection(connectionCallback);
haydenball 0:b6fae6eb2bfe 125 ble.gap().onDisconnection(disconnectionCallback);
haydenball 6:808cfc0b9480 126
haydenball 6:808cfc0b9480 127 ecgValue = 0;
haydenball 6:808cfc0b9480 128 tempValue = 0;
haydenball 0:b6fae6eb2bfe 129
haydenball 6:808cfc0b9480 130 UberVestService uberVestService(ble, ecgValue, tempValue);
haydenball 0:b6fae6eb2bfe 131 uberVestServicePtr = &uberVestService;
haydenball 4:851d3f52c344 132
haydenball 6:808cfc0b9480 133 Ticker ecgSampler;
haydenball 6:808cfc0b9480 134 ecgSampler.attach(sampleEcgCallback, 0.02);
haydenball 6:808cfc0b9480 135
haydenball 6:808cfc0b9480 136 //Ticker pulseSampler;
haydenball 6:808cfc0b9480 137 //pulseSampler.attach(samplePulseCallback, 0.1);
haydenball 6:808cfc0b9480 138
haydenball 6:808cfc0b9480 139 Ticker tempSampler;
haydenball 6:808cfc0b9480 140 tempSampler.attach(sampleTempCallback, 1);
haydenball 6:808cfc0b9480 141
haydenball 6:808cfc0b9480 142 Ticker flasher;
haydenball 6:808cfc0b9480 143 flasher.attach(flasherTimer, 0.5);
haydenball 0:b6fae6eb2bfe 144
haydenball 0:b6fae6eb2bfe 145 /* setup advertising */
haydenball 0:b6fae6eb2bfe 146 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
haydenball 0:b6fae6eb2bfe 147 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list));
haydenball 0:b6fae6eb2bfe 148 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
haydenball 0:b6fae6eb2bfe 149 ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
haydenball 0:b6fae6eb2bfe 150 ble.gap().setAdvertisingInterval(1000); /* 1000ms. */
haydenball 0:b6fae6eb2bfe 151 ble.gap().startAdvertising();
haydenball 0:b6fae6eb2bfe 152
haydenball 0:b6fae6eb2bfe 153 while (true) {
haydenball 6:808cfc0b9480 154 if (ble.getGapState().connected) {
haydenball 6:808cfc0b9480 155 if (sampleEcg) {
haydenball 6:808cfc0b9480 156 sampleEcg = false;
haydenball 6:808cfc0b9480 157
haydenball 6:808cfc0b9480 158 ecgValue = (ecg.read() * 1024);
haydenball 6:808cfc0b9480 159 uberVestServicePtr->updateEcg(ecgValue);
haydenball 6:808cfc0b9480 160 }
haydenball 6:808cfc0b9480 161
haydenball 6:808cfc0b9480 162 if (samplePulse) {
haydenball 6:808cfc0b9480 163 samplePulse = false;
haydenball 6:808cfc0b9480 164
haydenball 6:808cfc0b9480 165 pulseValue = (pulse.read() * 1024);
haydenball 6:808cfc0b9480 166 }
haydenball 6:808cfc0b9480 167
haydenball 6:808cfc0b9480 168
haydenball 6:808cfc0b9480 169 if (sampleTemp) {
haydenball 6:808cfc0b9480 170 sampleTemp = false;
haydenball 6:808cfc0b9480 171
haydenball 6:808cfc0b9480 172 tempValue = getTemp();
haydenball 6:808cfc0b9480 173 uberVestServicePtr->updateTemp(tempValue);
haydenball 6:808cfc0b9480 174 }
haydenball 4:851d3f52c344 175 } else {
haydenball 4:851d3f52c344 176 ble.waitForEvent();
haydenball 4:851d3f52c344 177 }
haydenball 0:b6fae6eb2bfe 178 }
haydenball 0:b6fae6eb2bfe 179 }