Chanel's edits

Dependencies:   max32630fthr USBDevice

Committer:
saleiferis
Date:
Tue Apr 07 04:57:22 2020 +0000
Revision:
19:f230229cb6f3
Parent:
17:65a8b29f6bac
HeartRateService

Who changed what in which revision?

UserRevisionLine numberNew contents of line
saleiferis 0:89ec48e52250 1 #include "mbed.h"
saleiferis 0:89ec48e52250 2 #include "math.h"
saleiferis 0:89ec48e52250 3 #include "max32630fthr.h"
saleiferis 0:89ec48e52250 4 #include "max86150.h"
saleiferis 0:89ec48e52250 5 #include "I2C.h"
saleiferis 0:89ec48e52250 6 #include "ble/BLE.h"
saleiferis 0:89ec48e52250 7 #include "ble/Gap.h"
saleiferis 17:65a8b29f6bac 8 #include "ble/services/HeartRateService.h"
saleiferis 7:4debec043316 9 #include "ECGService.h"
saleiferis 1:6e6f7e3cc1e1 10 #include <events/mbed_events.h>
saleiferis 1:6e6f7e3cc1e1 11 #include "bt32630.h"
saleiferis 16:f6bfa6b66e96 12 #include "panTompkins.h"
saleiferis 14:ee2175578993 13 //#include "filters.h"
saleiferis 0:89ec48e52250 14
saleiferis 0:89ec48e52250 15 //Register definitions
saleiferis 0:89ec48e52250 16 #define MAX86150_Addr 0xBC //updated per I2Cscanner, 8 bit version of 7 bit code 0x5E
saleiferis 0:89ec48e52250 17 #define maxi2cFreq 1000000
saleiferis 0:89ec48e52250 18 #define recommendedi2cFreq 400000
saleiferis 10:28b8729cf5dc 19
saleiferis 10:28b8729cf5dc 20 #define BaudRate 115200
saleiferis 0:89ec48e52250 21
saleiferis 13:a555fd1253e7 22 #define WINDOW_SIZE 25 // number of samples for moving winfow integration for HR algo preprocessing. Effective window_size is half of this value
saleiferis 14:ee2175578993 23 #define BUFF_SIZE 136 // TODO: decouple BUFF_SIZE and FIR_SIZE. now program crashes if != 136
saleiferis 14:ee2175578993 24 #define FIR_SIZE 136
saleiferis 0:89ec48e52250 25
saleiferis 10:28b8729cf5dc 26 Serial pc(USBTX,USBRX,NULL,BaudRate);
saleiferis 10:28b8729cf5dc 27 InterruptIn intPin(P5_5); // interrupts currently not used
saleiferis 0:89ec48e52250 28 I2C i2c(I2C2_SDA, I2C2_SCL);
saleiferis 8:2005014df05c 29 MAX86150 max86150Sensor;
saleiferis 0:89ec48e52250 30
saleiferis 19:f230229cb6f3 31 //ECGService *hrServicePtr;
saleiferis 19:f230229cb6f3 32 HeartRateService *hrServicePtr;
saleiferis 14:ee2175578993 33 int k; // loop iteration
saleiferis 14:ee2175578993 34 float signal[BUFF_SIZE]={0}; //store signal segment to be filtered
saleiferis 14:ee2175578993 35 float bp_signal[BUFF_SIZE]={0};
saleiferis 14:ee2175578993 36 float derivative[BUFF_SIZE]={0};
saleiferis 14:ee2175578993 37 float squared[BUFF_SIZE]={0};
saleiferis 14:ee2175578993 38 float integral[BUFF_SIZE] = {0};
saleiferis 16:f6bfa6b66e96 39 bool outputSignal[BUFF_SIZE]={0};
saleiferis 14:ee2175578993 40
saleiferis 14:ee2175578993 41 // Variables for preprocessing
saleiferis 14:ee2175578993 42 float y = 0.0; //filtered sample to be displayed
saleiferis 14:ee2175578993 43 float prev_y = 0.0; // keep track of previous output to calculate derivative
saleiferis 14:ee2175578993 44 float sq_y = 0.0;
saleiferis 14:ee2175578993 45 float movmean = 0.0; // result of moving window integration
saleiferis 14:ee2175578993 46
saleiferis 14:ee2175578993 47
saleiferis 14:ee2175578993 48 // Variables for peak-finding
saleiferis 14:ee2175578993 49 int rr1[8], rr2[8], rravg1, rravg2, rrlow = 0, rrhigh = 0, rrmiss = 0;
saleiferis 16:f6bfa6b66e96 50 long unsigned int i, j, sample = 0, current = 0, lastQRS = 0, lastSlope = 0, currentSlope = 0;
saleiferis 14:ee2175578993 51 float peak_i = 0, peak_f = 0, threshold_i1 = 0, threshold_i2 = 0, threshold_f1 = 0, threshold_f2 = 0, spk_i = 0, spk_f = 0, npk_i = 0, npk_f = 0;
saleiferis 14:ee2175578993 52 bool qrs, regular = true, prevRegular;
saleiferis 14:ee2175578993 53
saleiferis 9:171171516ebd 54
saleiferis 12:ad628acddbf7 55 //Timer timer;
saleiferis 9:171171516ebd 56
saleiferis 1:6e6f7e3cc1e1 57 static events::EventQueue event_queue(/* event count */ 16 * EVENTS_EVENT_SIZE);
saleiferis 1:6e6f7e3cc1e1 58
saleiferis 15:b15b4b6c6da8 59
saleiferis 9:171171516ebd 60
saleiferis 15:b15b4b6c6da8 61
saleiferis 10:28b8729cf5dc 62
saleiferis 0:89ec48e52250 63 //////////
saleiferis 10:28b8729cf5dc 64 int main(){
saleiferis 14:ee2175578993 65 /*
saleiferis 0:89ec48e52250 66 max86150Sensor.begin(i2c, recommendedi2cFreq, MAX86150_Addr);
saleiferis 0:89ec48e52250 67 wait_ms(300);
saleiferis 4:4233f5538abf 68
saleiferis 0:89ec48e52250 69 //unsigned char partID = max86150Sensor.readPartID();
saleiferis 0:89ec48e52250 70 unsigned char partID = max86150Sensor.readRegister8(MAX86150_Addr,0xFF);
saleiferis 0:89ec48e52250 71 pc.printf("Part ID is: %X\n",partID);
saleiferis 14:ee2175578993 72 while (partID != 0x1E) { } // Connection to sensor is not established
saleiferis 2:a96a53e6c6a3 73
saleiferis 2:a96a53e6c6a3 74
saleiferis 14:ee2175578993 75 // SETUP SENSOR
saleiferis 10:28b8729cf5dc 76 max86150Sensor.setup(); //Configure sensor
saleiferis 10:28b8729cf5dc 77 wait_ms(300);
saleiferis 10:28b8729cf5dc 78 pc.printf("SYSCONTOL REG: %x\n", max86150Sensor.readRegister8(MAX86150_Addr,0x0D));
saleiferis 10:28b8729cf5dc 79 pc.printf("FIFO CONFIG: %X\n",max86150Sensor.readRegister8(MAX86150_Addr,0x08));
saleiferis 10:28b8729cf5dc 80 pc.printf("INT_EN1: %X\n", max86150Sensor.readRegister8(MAX86150_Addr,0x02));
saleiferis 10:28b8729cf5dc 81 pc.printf("INT_EN2: %X\n", max86150Sensor.readRegister8(MAX86150_Addr,0x03));
saleiferis 10:28b8729cf5dc 82 pc.printf("INT STATUS1: %X\n",max86150Sensor.readRegister8(MAX86150_Addr,0x00));
saleiferis 10:28b8729cf5dc 83 pc.printf("INT STATUS2: %X\n",max86150Sensor.readRegister8(MAX86150_Addr,0x01));
saleiferis 10:28b8729cf5dc 84
saleiferis 14:ee2175578993 85 ////
saleiferis 10:28b8729cf5dc 86
saleiferis 10:28b8729cf5dc 87 max86150Sensor.clearFIFO();
saleiferis 10:28b8729cf5dc 88 max86150Sensor.writeRegister8(MAX86150_Addr,0x0D,0x04); //start FIFO
saleiferis 14:ee2175578993 89 */
saleiferis 10:28b8729cf5dc 90 //******* SETUP BLUETOOTH *********
saleiferis 10:28b8729cf5dc 91 eventQueue.call_every(1, periodicCallback); // poll sensor every 1ms. New samples come every 5ms, so polling freq can potentially be decreased
saleiferis 1:6e6f7e3cc1e1 92 BLE &ble = BLE::Instance();
saleiferis 10:28b8729cf5dc 93 ble.onEventsToProcess(scheduleBleEventsProcessing);
saleiferis 14:ee2175578993 94 ble.init(bleInitComplete);
saleiferis 14:ee2175578993 95 eventQueue.dispatch_forever();
saleiferis 14:ee2175578993 96
saleiferis 13:a555fd1253e7 97
saleiferis 14:ee2175578993 98 /*
saleiferis 14:ee2175578993 99 int16_t ecgsigned16;
saleiferis 13:a555fd1253e7 100 while(1){
saleiferis 13:a555fd1253e7 101 if(max86150Sensor.check()>0){
saleiferis 13:a555fd1253e7 102
saleiferis 13:a555fd1253e7 103 ecgsigned16 = (int16_t) (max86150Sensor.getFIFOECG()>>2);
saleiferis 13:a555fd1253e7 104 max86150Sensor.nextSample();
saleiferis 13:a555fd1253e7 105 ble.updateHeartRate(ecgsigned16);
saleiferis 14:ee2175578993 106 pc.printf("%f\n",(float)ecgsigned16);
saleiferis 14:ee2175578993 107 */
saleiferis 13:a555fd1253e7 108
saleiferis 4:4233f5538abf 109
saleiferis 10:28b8729cf5dc 110 // Below code is for testing interrupts and sensor polling without involving bluetooth API
saleiferis 14:ee2175578993 111 /* UNCOMMENT HERE
saleiferis 10:28b8729cf5dc 112 // max86150Sensor.clearFIFO();
saleiferis 10:28b8729cf5dc 113 //intPin.fall(&ISR_DATA_READY);
saleiferis 10:28b8729cf5dc 114 // max86150Sensor.writeRegister8(MAX86150_Addr,0x0D,0x04);
saleiferis 10:28b8729cf5dc 115 int16_t ecgsigned16;
saleiferis 13:a555fd1253e7 116 int k; // loop iteration
saleiferis 12:ad628acddbf7 117 float signal[BUFF_SIZE]={0}; //store signal segment to be filtered
saleiferis 12:ad628acddbf7 118 float bp_signal[BUFF_SIZE]={0};
saleiferis 12:ad628acddbf7 119 float derivative[BUFF_SIZE]={0};
saleiferis 12:ad628acddbf7 120 float squared[BUFF_SIZE]={0};
saleiferis 12:ad628acddbf7 121 float integral[BUFF_SIZE] = {0};
saleiferis 12:ad628acddbf7 122
saleiferis 12:ad628acddbf7 123 // Variables for preprocessing
saleiferis 11:cbd9182d14d2 124 float y = 0.0; //filtered sample to be displayed
saleiferis 12:ad628acddbf7 125 float prev_y = 0.0; // keep track of previous output to calculate derivative
saleiferis 12:ad628acddbf7 126 float sq_y = 0.0;
saleiferis 12:ad628acddbf7 127 float movmean = 0.0; // result of moving window integration
saleiferis 12:ad628acddbf7 128
saleiferis 12:ad628acddbf7 129 // Variables for peak-finding
saleiferis 12:ad628acddbf7 130 int rr1[8], rr2[8], rravg1, rravg2, rrlow = 0, rrhigh = 0, rrmiss = 0;
saleiferis 16:f6bfa6b66e96 131 long unsigned int i, j, sample = 0, current = 0, lastQRS = 0, lastSlope = 0, currentSlope = 0;
saleiferis 12:ad628acddbf7 132 float peak_i = 0, peak_f = 0, threshold_i1 = 0, threshold_i2 = 0, threshold_f1 = 0, threshold_f2 = 0, spk_i = 0, spk_f = 0, npk_i = 0, npk_f = 0;
saleiferis 12:ad628acddbf7 133 bool qrs, regular = true, prevRegular;
saleiferis 12:ad628acddbf7 134 // Initializing the RR averages
saleiferis 12:ad628acddbf7 135 for (i = 0; i < 8; i++)
saleiferis 12:ad628acddbf7 136 {
saleiferis 12:ad628acddbf7 137 rr1[i] = 0;
saleiferis 12:ad628acddbf7 138 rr2[i] = 0;
saleiferis 12:ad628acddbf7 139 }
saleiferis 12:ad628acddbf7 140
saleiferis 9:171171516ebd 141
saleiferis 8:2005014df05c 142 while(1){
saleiferis 10:28b8729cf5dc 143 if(max86150Sensor.check()>0){
saleiferis 10:28b8729cf5dc 144
saleiferis 11:cbd9182d14d2 145 //ecgsigned16 = (int16_t) (max86150Sensor.getFIFOECG()>>2);
saleiferis 11:cbd9182d14d2 146 //max86150Sensor.nextSample();
saleiferis 11:cbd9182d14d2 147 //pc.printf("%f\n",(float)ecgsigned16);
saleiferis 11:cbd9182d14d2 148
saleiferis 12:ad628acddbf7 149 // if buffer is full
saleiferis 16:f6bfa6b66e96 150 if (sample >= BUFF_SIZE){
saleiferis 13:a555fd1253e7 151 for (k=0; k<BUFF_SIZE-1; k++){ //discard oldest sample, shift samples in buffer
saleiferis 13:a555fd1253e7 152 signal[k] = signal[k+1];
saleiferis 13:a555fd1253e7 153 bp_signal[k] = bp_signal[k+1];
saleiferis 13:a555fd1253e7 154 derivative[k] = derivative[k+1];
saleiferis 13:a555fd1253e7 155 integral[k] = integral[k+1];
saleiferis 13:a555fd1253e7 156 squared[k] = squared[k+1];
saleiferis 12:ad628acddbf7 157
saleiferis 11:cbd9182d14d2 158 }
saleiferis 16:f6bfa6b66e96 159 current = BUFF_SIZE-1; // indicates that buffer is full
saleiferis 12:ad628acddbf7 160 prev_y = y;
saleiferis 11:cbd9182d14d2 161 y = 0.0; // reset filter output for current sample
saleiferis 11:cbd9182d14d2 162 }else{ //Buffer is not full yet
saleiferis 16:f6bfa6b66e96 163 current = sample; //position at buffer is same as sample number
saleiferis 11:cbd9182d14d2 164 }
saleiferis 11:cbd9182d14d2 165 ecgsigned16 = (int16_t) (max86150Sensor.getFIFOECG()>>2); //read a sample
saleiferis 11:cbd9182d14d2 166 max86150Sensor.nextSample(); // advance tail to get sample in next iteration
saleiferis 16:f6bfa6b66e96 167 signal[current] = (float)ecgsigned16; //add sample to buffer
saleiferis 16:f6bfa6b66e96 168 sample++;
saleiferis 11:cbd9182d14d2 169
saleiferis 16:f6bfa6b66e96 170 if (current< FIR_SIZE-1){
saleiferis 11:cbd9182d14d2 171 // buffer is not full yet
saleiferis 11:cbd9182d14d2 172 }else{ //buffer is full, filter current sample
saleiferis 14:ee2175578993 173 for(k = 0; k < FIR_SIZE; k++){ //FIR bandpass filter
saleiferis 16:f6bfa6b66e96 174 y = y + FIR_BP[k] * signal[current-k];
saleiferis 11:cbd9182d14d2 175 }
saleiferis 16:f6bfa6b66e96 176 bp_signal[current] = y;
saleiferis 12:ad628acddbf7 177 }
saleiferis 12:ad628acddbf7 178 sq_y = pow(y-prev_y,2);
saleiferis 16:f6bfa6b66e96 179 squared[current] = sq_y;
saleiferis 12:ad628acddbf7 180 //moving window integration
saleiferis 12:ad628acddbf7 181 movmean = 0.0; // reset for current sample
saleiferis 13:a555fd1253e7 182 for(k=0; k<(int)WINDOW_SIZE/2; k++){
saleiferis 16:f6bfa6b66e96 183 //pc.printf("%d\n",(int)current - (int)(WINDOW_SIZE));
saleiferis 16:f6bfa6b66e96 184 if ((int)current - (int)(WINDOW_SIZE) > k){ //there are enough samples in squared[]
saleiferis 16:f6bfa6b66e96 185 // movmean = movmean + squared[(current-k-(int)WINDOW_SIZE/2)] + squared[current+k-(int)WINDOW_SIZE/2];
saleiferis 16:f6bfa6b66e96 186 movmean = movmean + squared[current-k];
saleiferis 12:ad628acddbf7 187
saleiferis 12:ad628acddbf7 188 }else{
saleiferis 12:ad628acddbf7 189 break;
saleiferis 12:ad628acddbf7 190 }
saleiferis 11:cbd9182d14d2 191 }
saleiferis 13:a555fd1253e7 192 movmean = movmean/(float)(k+1);
saleiferis 16:f6bfa6b66e96 193 integral[current] = movmean;
saleiferis 12:ad628acddbf7 194
saleiferis 12:ad628acddbf7 195 pc.printf("%f %f\n",movmean/1000, y/50);
saleiferis 12:ad628acddbf7 196
saleiferis 12:ad628acddbf7 197 // Preprocessing done
saleiferis 14:ee2175578993 198
saleiferis 12:ad628acddbf7 199 // Start peak-finding
saleiferis 13:a555fd1253e7 200 qrs = false;
saleiferis 16:f6bfa6b66e96 201 if (integral[current] >= threshold_i1 || highpass[current] >= threshold_f1){
saleiferis 16:f6bfa6b66e96 202 peak_i = integral[current];
saleiferis 16:f6bfa6b66e96 203 peak_f = bp_signal[current];
saleiferis 14:ee2175578993 204 }
saleiferis 12:ad628acddbf7 205
saleiferis 12:ad628acddbf7 206
saleiferis 12:ad628acddbf7 207
saleiferis 12:ad628acddbf7 208
saleiferis 10:28b8729cf5dc 209 }
saleiferis 14:ee2175578993 210 } end while(1)*/
saleiferis 10:28b8729cf5dc 211
saleiferis 0:89ec48e52250 212 }