oled_sensor

Dependencies:   max32630fthr Adafruit_FeatherOLED_2020 USBDevice

Committer:
jonaangelica
Date:
Thu Feb 20 13:40:30 2020 +0000
Revision:
5:f18d3d0fe600
Parent:
4:727e58d27bf1
Child:
6:980318add386
font 3 oled display;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
jonaangelica 0:cc636f742803 1 /* mbed Microcontroller Library
jonaangelica 0:cc636f742803 2 * Copyright (c) 2006-2015 ARM Limited
jonaangelica 0:cc636f742803 3 *
jonaangelica 0:cc636f742803 4 * Licensed under the Apache License, Version 2.0 (the "License");
jonaangelica 0:cc636f742803 5 * you may not use this file except in compliance with the License.
jonaangelica 0:cc636f742803 6 * You may obtain a copy of the License at
jonaangelica 0:cc636f742803 7 *
jonaangelica 0:cc636f742803 8 * http://www.apache.org/licenses/LICENSE-2.0
jonaangelica 0:cc636f742803 9 *
jonaangelica 0:cc636f742803 10 * Unless required by applicable law or agreed to in writing, software
jonaangelica 0:cc636f742803 11 * distributed under the License is distributed on an "AS IS" BASIS,
jonaangelica 0:cc636f742803 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
jonaangelica 0:cc636f742803 13 * See the License for the specific language governing permissions and
jonaangelica 0:cc636f742803 14 * limitations under the License.
jonaangelica 0:cc636f742803 15 */
jonaangelica 0:cc636f742803 16
jonaangelica 0:cc636f742803 17 #include <events/mbed_events.h>
jonaangelica 0:cc636f742803 18 #include <mbed.h>
jonaangelica 4:727e58d27bf1 19 #include "max32630fthr.h"
jonaangelica 2:786c61e6532a 20 #include "Adafruit_SSD1306.h"//include the adafruit library for the oled display
jonaangelica 0:cc636f742803 21 #include "ble/BLE.h"
jonaangelica 0:cc636f742803 22 #include "ble/Gap.h"
jonaangelica 0:cc636f742803 23 #include "ble/services/HeartRateService.h"
jonaangelica 0:cc636f742803 24 #include "algorithm.h"
jonaangelica 0:cc636f742803 25 #include "MAX30102.h"
jonaangelica 0:cc636f742803 26
jonaangelica 0:cc636f742803 27 #define MAX_BRIGHTNESS 255
jonaangelica 0:cc636f742803 28
jonaangelica 0:cc636f742803 29
jonaangelica 0:cc636f742803 30
jonaangelica 0:cc636f742803 31 DigitalOut led2(LED2, 1);
jonaangelica 4:727e58d27bf1 32 MAX32630FTHR pegasus(MAX32630FTHR::VIO_3V3);
jonaangelica 0:cc636f742803 33
jonaangelica 0:cc636f742803 34 uint32_t aun_ir_buffer[500]; //IR LED sensor data
jonaangelica 0:cc636f742803 35 int32_t n_ir_buffer_length; //data length
jonaangelica 0:cc636f742803 36 uint32_t aun_red_buffer[500]; //Red LED sensor data
jonaangelica 0:cc636f742803 37 int32_t n_sp02; //SPO2 value
jonaangelica 0:cc636f742803 38 int8_t ch_spo2_valid; //indicator to show if the SP02 calculation is valid
jonaangelica 0:cc636f742803 39 int32_t n_heart_rate; //heart rate value
jonaangelica 0:cc636f742803 40 int8_t ch_hr_valid; //indicator to show if the heart rate calculation is valid
jonaangelica 0:cc636f742803 41 uint8_t uch_dummy;
jonaangelica 0:cc636f742803 42 uint32_t un_min, un_max, un_prev_data; //variables to calculate the on-board LED brightness that reflects the heartbeats
jonaangelica 0:cc636f742803 43 int i;
jonaangelica 0:cc636f742803 44 int32_t n_brightness;
jonaangelica 0:cc636f742803 45 float f_temp;
jonaangelica 0:cc636f742803 46 uint8_t hrmCounter;
jonaangelica 4:727e58d27bf1 47 I2C I2c(P3_4, P3_5); // SDA, SCL
jonaangelica 5:f18d3d0fe600 48
jonaangelica 4:727e58d27bf1 49 Adafruit_SSD1306_I2c oled(I2c);
jonaangelica 0:cc636f742803 50
jonaangelica 0:cc636f742803 51 #ifdef TARGET_MAX32630FTHR
jonaangelica 0:cc636f742803 52 PwmOut led1(LED_RED); //initializes the pwm output that connects to the on board LED
jonaangelica 0:cc636f742803 53 DigitalIn INT(P3_0); //pin P30 connects to the interrupt output pin of the MAX30102
jonaangelica 0:cc636f742803 54 #endif
jonaangelica 0:cc636f742803 55
jonaangelica 0:cc636f742803 56 const static char DEVICE_NAME[] = "HRM";
jonaangelica 0:cc636f742803 57 static const uint16_t uuid16_list[] = {GattService::UUID_HEART_RATE_SERVICE};
jonaangelica 0:cc636f742803 58
jonaangelica 3:bb52b351d6f5 59
jonaangelica 0:cc636f742803 60 static HeartRateService *hrServicePtr;
jonaangelica 0:cc636f742803 61
jonaangelica 0:cc636f742803 62 static EventQueue eventQueue(/* event count */ 16 * EVENTS_EVENT_SIZE);
jonaangelica 0:cc636f742803 63
jonaangelica 0:cc636f742803 64 void disconnectionCallback(const Gap::DisconnectionCallbackParams_t *params)
jonaangelica 0:cc636f742803 65 {
jonaangelica 0:cc636f742803 66 BLE::Instance().gap().startAdvertising(); // restart advertising
jonaangelica 0:cc636f742803 67 }
jonaangelica 0:cc636f742803 68
jonaangelica 0:cc636f742803 69 void checkHR(){
jonaangelica 0:cc636f742803 70
jonaangelica 0:cc636f742803 71 i=0;
jonaangelica 0:cc636f742803 72 un_min=0x3FFFF;
jonaangelica 0:cc636f742803 73 un_max=0;
jonaangelica 0:cc636f742803 74
jonaangelica 0:cc636f742803 75 //dumping the first 100 sets of samples in the memory and shift the last 400 sets of samples to the top
jonaangelica 0:cc636f742803 76 for(i=100;i<500;i++)
jonaangelica 0:cc636f742803 77 {
jonaangelica 0:cc636f742803 78 aun_red_buffer[i-100]=aun_red_buffer[i];
jonaangelica 0:cc636f742803 79 aun_ir_buffer[i-100]=aun_ir_buffer[i];
jonaangelica 0:cc636f742803 80
jonaangelica 0:cc636f742803 81 //update the signal min and max
jonaangelica 0:cc636f742803 82 if(un_min>aun_red_buffer[i])
jonaangelica 0:cc636f742803 83 un_min=aun_red_buffer[i];
jonaangelica 0:cc636f742803 84 if(un_max<aun_red_buffer[i])
jonaangelica 0:cc636f742803 85 un_max=aun_red_buffer[i];
jonaangelica 0:cc636f742803 86 }
jonaangelica 0:cc636f742803 87
jonaangelica 0:cc636f742803 88 //take 100 sets of samples before calculating the heart rate.
jonaangelica 0:cc636f742803 89 for(i=400;i<500;i++)
jonaangelica 0:cc636f742803 90 {
jonaangelica 0:cc636f742803 91 un_prev_data=aun_red_buffer[i-1];
jonaangelica 0:cc636f742803 92 while(INT.read()==1);
jonaangelica 0:cc636f742803 93 maxim_max30102_read_fifo((aun_red_buffer+i), (aun_ir_buffer+i));
jonaangelica 0:cc636f742803 94
jonaangelica 0:cc636f742803 95 if(aun_red_buffer[i]>un_prev_data)
jonaangelica 0:cc636f742803 96 {
jonaangelica 0:cc636f742803 97 f_temp=aun_red_buffer[i]-un_prev_data;
jonaangelica 0:cc636f742803 98 f_temp/=(un_max-un_min);
jonaangelica 0:cc636f742803 99 f_temp*=MAX_BRIGHTNESS;
jonaangelica 0:cc636f742803 100 n_brightness-=(int)f_temp;
jonaangelica 0:cc636f742803 101 if(n_brightness<0)
jonaangelica 0:cc636f742803 102 n_brightness=0;
jonaangelica 0:cc636f742803 103 }
jonaangelica 0:cc636f742803 104 else
jonaangelica 0:cc636f742803 105 {
jonaangelica 0:cc636f742803 106 f_temp=un_prev_data-aun_red_buffer[i];
jonaangelica 0:cc636f742803 107 f_temp/=(un_max-un_min);
jonaangelica 0:cc636f742803 108 f_temp*=MAX_BRIGHTNESS;
jonaangelica 0:cc636f742803 109 n_brightness+=(int)f_temp;
jonaangelica 0:cc636f742803 110 if(n_brightness>MAX_BRIGHTNESS)
jonaangelica 0:cc636f742803 111 n_brightness=MAX_BRIGHTNESS;
jonaangelica 0:cc636f742803 112 }
jonaangelica 0:cc636f742803 113 #if defined(TARGET_KL25Z) || defined(TARGET_MAX32630FTHR)
jonaangelica 0:cc636f742803 114 led1.write(1-(float)n_brightness/256);
jonaangelica 0:cc636f742803 115 #endif
jonaangelica 0:cc636f742803 116
jonaangelica 0:cc636f742803 117
jonaangelica 0:cc636f742803 118 }
jonaangelica 0:cc636f742803 119 maxim_heart_rate_and_oxygen_saturation(aun_ir_buffer, n_ir_buffer_length, aun_red_buffer, &n_sp02, &ch_spo2_valid, &n_heart_rate, &ch_hr_valid);
jonaangelica 0:cc636f742803 120 }
jonaangelica 0:cc636f742803 121
jonaangelica 0:cc636f742803 122 void updateSensorValue() {
jonaangelica 0:cc636f742803 123 // Do blocking calls or whatever is necessary for sensor polling.
jonaangelica 0:cc636f742803 124 // In our case, we simply update the HRM measurement.
jonaangelica 0:cc636f742803 125
jonaangelica 0:cc636f742803 126
jonaangelica 0:cc636f742803 127 checkHR();
jonaangelica 0:cc636f742803 128
jonaangelica 0:cc636f742803 129 hrmCounter = n_heart_rate;
jonaangelica 0:cc636f742803 130
jonaangelica 0:cc636f742803 131 hrServicePtr->updateHeartRate(hrmCounter);
jonaangelica 0:cc636f742803 132 }
jonaangelica 0:cc636f742803 133
jonaangelica 0:cc636f742803 134 void periodicCallback(void)
jonaangelica 0:cc636f742803 135 {
jonaangelica 0:cc636f742803 136
jonaangelica 0:cc636f742803 137 if (BLE::Instance().getGapState().connected) {
jonaangelica 0:cc636f742803 138 eventQueue.call(updateSensorValue);
jonaangelica 0:cc636f742803 139 }
jonaangelica 0:cc636f742803 140 }
jonaangelica 0:cc636f742803 141
jonaangelica 0:cc636f742803 142
jonaangelica 0:cc636f742803 143
jonaangelica 0:cc636f742803 144 void onBleInitError(BLE &ble, ble_error_t error)
jonaangelica 0:cc636f742803 145 {
jonaangelica 0:cc636f742803 146 (void)ble;
jonaangelica 0:cc636f742803 147 (void)error;
jonaangelica 0:cc636f742803 148 /* Initialization error handling should go here */
jonaangelica 0:cc636f742803 149 }
jonaangelica 0:cc636f742803 150
jonaangelica 0:cc636f742803 151 void printMacAddress()
jonaangelica 0:cc636f742803 152 {
jonaangelica 0:cc636f742803 153 /* Print out device MAC address to the console*/
jonaangelica 0:cc636f742803 154 Gap::AddressType_t addr_type;
jonaangelica 0:cc636f742803 155 Gap::Address_t address;
jonaangelica 0:cc636f742803 156 BLE::Instance().gap().getAddress(&addr_type, address);
jonaangelica 0:cc636f742803 157 printf("DEVICE MAC ADDRESS: ");
jonaangelica 0:cc636f742803 158 for (int i = 5; i >= 1; i--){
jonaangelica 0:cc636f742803 159 printf("%02x:", address[i]);
jonaangelica 0:cc636f742803 160 }
jonaangelica 0:cc636f742803 161 printf("%02x\r\n", address[0]);
jonaangelica 0:cc636f742803 162 }
jonaangelica 0:cc636f742803 163
jonaangelica 0:cc636f742803 164 void bleInitComplete(BLE::InitializationCompleteCallbackContext *params)
jonaangelica 0:cc636f742803 165 {
jonaangelica 0:cc636f742803 166 BLE& ble = params->ble;
jonaangelica 0:cc636f742803 167 ble_error_t error = params->error;
jonaangelica 0:cc636f742803 168
jonaangelica 0:cc636f742803 169 if (error != BLE_ERROR_NONE) {
jonaangelica 0:cc636f742803 170 onBleInitError(ble, error);
jonaangelica 0:cc636f742803 171 return;
jonaangelica 0:cc636f742803 172 }
jonaangelica 0:cc636f742803 173
jonaangelica 0:cc636f742803 174 if (ble.getInstanceID() != BLE::DEFAULT_INSTANCE) {
jonaangelica 0:cc636f742803 175 return;
jonaangelica 0:cc636f742803 176 }
jonaangelica 0:cc636f742803 177
jonaangelica 0:cc636f742803 178 ble.gap().onDisconnection(disconnectionCallback);
jonaangelica 0:cc636f742803 179
jonaangelica 0:cc636f742803 180 /* Setup primary service. */
jonaangelica 0:cc636f742803 181 hrServicePtr = new HeartRateService(ble, hrmCounter, HeartRateService::LOCATION_WRIST);//initially LOCATION_FINGER
jonaangelica 0:cc636f742803 182
jonaangelica 0:cc636f742803 183 /* Setup advertising. */
jonaangelica 0:cc636f742803 184 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::BREDR_NOT_SUPPORTED | GapAdvertisingData::LE_GENERAL_DISCOVERABLE);
jonaangelica 0:cc636f742803 185 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LIST_16BIT_SERVICE_IDS, (uint8_t *)uuid16_list, sizeof(uuid16_list));
jonaangelica 0:cc636f742803 186 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::GENERIC_HEART_RATE_SENSOR);
jonaangelica 0:cc636f742803 187 ble.gap().accumulateAdvertisingPayload(GapAdvertisingData::COMPLETE_LOCAL_NAME, (uint8_t *)DEVICE_NAME, sizeof(DEVICE_NAME));
jonaangelica 0:cc636f742803 188 ble.gap().setAdvertisingType(GapAdvertisingParams::ADV_CONNECTABLE_UNDIRECTED);
jonaangelica 0:cc636f742803 189 ble.gap().setAdvertisingInterval(1000); /* 1000ms */
jonaangelica 0:cc636f742803 190 ble.gap().startAdvertising();
jonaangelica 0:cc636f742803 191
jonaangelica 0:cc636f742803 192 printMacAddress();
jonaangelica 0:cc636f742803 193 }
jonaangelica 0:cc636f742803 194
jonaangelica 0:cc636f742803 195 void scheduleBleEventsProcessing(BLE::OnEventsToProcessCallbackContext* context) {
jonaangelica 0:cc636f742803 196 BLE &ble = BLE::Instance();
jonaangelica 0:cc636f742803 197 eventQueue.call(Callback<void()>(&ble, &BLE::processEvents));
jonaangelica 0:cc636f742803 198 }
jonaangelica 0:cc636f742803 199
jonaangelica 2:786c61e6532a 200
jonaangelica 2:786c61e6532a 201 void HRMSensorInitialise(){
jonaangelica 4:727e58d27bf1 202 maxim_max30102_reset(); //resets the MAX30102
jonaangelica 0:cc636f742803 203
jonaangelica 0:cc636f742803 204
jonaangelica 0:cc636f742803 205 //read and clear status register
jonaangelica 0:cc636f742803 206 maxim_max30102_read_reg(0,&uch_dummy);
jonaangelica 0:cc636f742803 207
jonaangelica 0:cc636f742803 208
jonaangelica 0:cc636f742803 209 maxim_max30102_init(); //initializes the MAX30102
jonaangelica 0:cc636f742803 210
jonaangelica 0:cc636f742803 211 n_brightness=0;
jonaangelica 0:cc636f742803 212 un_min=0x3FFFF;
jonaangelica 0:cc636f742803 213 un_max=0;
jonaangelica 0:cc636f742803 214
jonaangelica 0:cc636f742803 215 n_ir_buffer_length=500; //buffer length of 100 stores 5 seconds of samples running at 100sps
jonaangelica 0:cc636f742803 216
jonaangelica 0:cc636f742803 217 //read the first 500 samples, and determine the signal range
jonaangelica 0:cc636f742803 218 for(i=0;i<n_ir_buffer_length;i++)
jonaangelica 0:cc636f742803 219 {
jonaangelica 0:cc636f742803 220 while(INT.read()==1); //wait until the interrupt pin asserts
jonaangelica 0:cc636f742803 221
jonaangelica 0:cc636f742803 222 maxim_max30102_read_fifo((aun_red_buffer+i), (aun_ir_buffer+i)); //read from MAX30102 FIFO
jonaangelica 0:cc636f742803 223
jonaangelica 0:cc636f742803 224 if(un_min>aun_red_buffer[i])
jonaangelica 0:cc636f742803 225 un_min=aun_red_buffer[i]; //update signal min
jonaangelica 0:cc636f742803 226 if(un_max<aun_red_buffer[i])
jonaangelica 0:cc636f742803 227 un_max=aun_red_buffer[i]; //update signal max
jonaangelica 0:cc636f742803 228
jonaangelica 0:cc636f742803 229 }
jonaangelica 0:cc636f742803 230 un_prev_data=aun_red_buffer[i];
jonaangelica 0:cc636f742803 231
jonaangelica 0:cc636f742803 232 //calculate heart rate and SpO2 after first 500 samples (first 5 seconds of samples)
jonaangelica 0:cc636f742803 233 maxim_heart_rate_and_oxygen_saturation(aun_ir_buffer, n_ir_buffer_length, aun_red_buffer, &n_sp02, &ch_spo2_valid, &n_heart_rate, &ch_hr_valid);
jonaangelica 2:786c61e6532a 234 }
jonaangelica 2:786c61e6532a 235
jonaangelica 4:727e58d27bf1 236
jonaangelica 4:727e58d27bf1 237
jonaangelica 2:786c61e6532a 238 void HRMSensorTask(){
jonaangelica 0:cc636f742803 239 eventQueue.call_every(500, periodicCallback);
jonaangelica 0:cc636f742803 240
jonaangelica 0:cc636f742803 241 BLE &ble = BLE::Instance();
jonaangelica 0:cc636f742803 242 ble.onEventsToProcess(scheduleBleEventsProcessing);
jonaangelica 0:cc636f742803 243 ble.init(bleInitComplete);
jonaangelica 0:cc636f742803 244
jonaangelica 0:cc636f742803 245 eventQueue.dispatch_forever();
jonaangelica 2:786c61e6532a 246 }
jonaangelica 4:727e58d27bf1 247
jonaangelica 4:727e58d27bf1 248
jonaangelica 4:727e58d27bf1 249
jonaangelica 4:727e58d27bf1 250
jonaangelica 4:727e58d27bf1 251
jonaangelica 4:727e58d27bf1 252
jonaangelica 4:727e58d27bf1 253
jonaangelica 4:727e58d27bf1 254
jonaangelica 3:bb52b351d6f5 255 void OLEDInitialise(){
jonaangelica 4:727e58d27bf1 256 Thread::wait(50); // Give the supplies time to settle before initializing the display
jonaangelica 3:bb52b351d6f5 257 oled.clearDisplay();
jonaangelica 4:727e58d27bf1 258 oled.display();
jonaangelica 5:f18d3d0fe600 259 oled.setTextSize(3);
jonaangelica 4:727e58d27bf1 260 }
jonaangelica 4:727e58d27bf1 261
jonaangelica 4:727e58d27bf1 262 void OLEDTask(){
jonaangelica 4:727e58d27bf1 263 Thread::wait(500);
jonaangelica 4:727e58d27bf1 264 oled.clearDisplay();
jonaangelica 4:727e58d27bf1 265 oled.setTextCursor(0,0);
jonaangelica 5:f18d3d0fe600 266 oled.printf("BP:120");
jonaangelica 4:727e58d27bf1 267 oled.display();
jonaangelica 3:bb52b351d6f5 268 }
jonaangelica 2:786c61e6532a 269
jonaangelica 5:f18d3d0fe600 270 int ack;
jonaangelica 5:f18d3d0fe600 271 char regaddr[1];
jonaangelica 5:f18d3d0fe600 272 char readdata[8]; // room for length and 7 databytes
jonaangelica 5:f18d3d0fe600 273 char writedata[9]; // room for reg address, length and 7 databytes
jonaangelica 5:f18d3d0fe600 274 DigitalOut bLED(LED3);
jonaangelica 5:f18d3d0fe600 275 DigitalOut gLED(LED2);
jonaangelica 5:f18d3d0fe600 276 int address;
jonaangelica 5:f18d3d0fe600 277 int addresses[2];
jonaangelica 5:f18d3d0fe600 278 char *dataBuff;
jonaangelica 5:f18d3d0fe600 279
jonaangelica 5:f18d3d0fe600 280
jonaangelica 2:786c61e6532a 281 int main()
jonaangelica 2:786c61e6532a 282 {
jonaangelica 5:f18d3d0fe600 283
jonaangelica 2:786c61e6532a 284 HRMSensorInitialise();
jonaangelica 5:f18d3d0fe600 285 Thread::wait(5000);
jonaangelica 3:bb52b351d6f5 286 OLEDInitialise();
jonaangelica 5:f18d3d0fe600 287
jonaangelica 2:786c61e6532a 288
jonaangelica 2:786c61e6532a 289 while(1)
jonaangelica 2:786c61e6532a 290 {
jonaangelica 5:f18d3d0fe600 291
jonaangelica 5:f18d3d0fe600 292 bLED = LED_OFF;
jonaangelica 5:f18d3d0fe600 293 gLED = LED_ON;
jonaangelica 4:727e58d27bf1 294 OLEDTask();
jonaangelica 5:f18d3d0fe600 295 Thread::wait(5000);
jonaangelica 2:786c61e6532a 296 HRMSensorTask();
jonaangelica 5:f18d3d0fe600 297 Thread::wait(5000);
jonaangelica 5:f18d3d0fe600 298
jonaangelica 0:cc636f742803 299
jonaangelica 0:cc636f742803 300
jonaangelica 0:cc636f742803 301 }
jonaangelica 0:cc636f742803 302 }