![](/media/cache/group/default_image.jpg.50x50_q85.jpg)
mbed code for UberVest health monitoring
Dependencies: BLE_API mbed nRF51822
main.cpp@6:808cfc0b9480, 2015-11-23 (annotated)
- 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?
User | Revision | Line number | New 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 | } |