SpO2 algorithm used in MAX30101 onboard MAX32620HSP. Algorithm is not perfect but it works

Dependencies:   mbed MAX14720 USBDevice

Committer:
douqan93
Date:
Thu Mar 28 08:07:54 2019 +0000
Revision:
0:af4d13000e95
This program for MAX32620HSP's onboard SpO2 sensor (MAX30101). Algorithm is not perfect but it works.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
douqan93 0:af4d13000e95 1 #include "mbed.h"
douqan93 0:af4d13000e95 2 #include "MAX14720.h"
douqan93 0:af4d13000e95 3 #include "MAX30102.h"
douqan93 0:af4d13000e95 4 #include "USBSerial.h"
douqan93 0:af4d13000e95 5 #include "System.h"
douqan93 0:af4d13000e95 6 #include "algorithm.h"
douqan93 0:af4d13000e95 7
douqan93 0:af4d13000e95 8 /// define the HVOUT Boost Voltage default for the MAX14720 PMIC
douqan93 0:af4d13000e95 9 #define HVOUT_VOLTAGE 4500 // set to 4500 mV
douqan93 0:af4d13000e95 10
douqan93 0:af4d13000e95 11 #define MAX14720_I2C_SLAVE_ADDR (0x54)
douqan93 0:af4d13000e95 12
douqan93 0:af4d13000e95 13 #define MAX_BRIGHTNESS 255
douqan93 0:af4d13000e95 14
douqan93 0:af4d13000e95 15 uint32_t aun_ir_buffer[500]; //IR LED sensor data
douqan93 0:af4d13000e95 16 int32_t n_ir_buffer_length; //data length
douqan93 0:af4d13000e95 17 uint32_t aun_red_buffer[500]; //Red LED sensor data
douqan93 0:af4d13000e95 18 int32_t n_sp02; //SPO2 value
douqan93 0:af4d13000e95 19 int8_t ch_spo2_valid; //indicator to show if the SP02 calculation is valid
douqan93 0:af4d13000e95 20 int32_t n_heart_rate; //heart rate value
douqan93 0:af4d13000e95 21 int8_t ch_hr_valid; //indicator to show if the heart rate calculation is valid
douqan93 0:af4d13000e95 22 uint8_t uch_dummy;
douqan93 0:af4d13000e95 23
douqan93 0:af4d13000e95 24 //Serial pc(USBTX, USBRX); //initializes the serial port
douqan93 0:af4d13000e95 25 /// Define with Maxim VID and a Maxim assigned PID, set to version 0x0001 and non-blocking
douqan93 0:af4d13000e95 26
douqan93 0:af4d13000e95 27 USBSerial usbSerial(0x0b6a, 0x0122, 0x0001, false);
douqan93 0:af4d13000e95 28
douqan93 0:af4d13000e95 29 /// I2C Master 2
douqan93 0:af4d13000e95 30 I2C i2c2(I2C2_SDA, I2C2_SCL); // used by MAX14720, MAX30101, LIS2DH
douqan93 0:af4d13000e95 31 /// SPI Master 0 with SPI0_SS for use with MAX30001
douqan93 0:af4d13000e95 32
douqan93 0:af4d13000e95 33 MAX14720 max14720(&i2c2, MAX14720_I2C_SLAVE_ADDR);
douqan93 0:af4d13000e95 34 DigitalOut led(LED1);
douqan93 0:af4d13000e95 35 DigitalIn INT(P4_0);
douqan93 0:af4d13000e95 36 int main(){
douqan93 0:af4d13000e95 37 //---------------------------------------------------
douqan93 0:af4d13000e95 38 // hold results for returning functions
douqan93 0:af4d13000e95 39 int result;
douqan93 0:af4d13000e95 40 // initialize HVOUT on the MAX14720 PMIC
douqan93 0:af4d13000e95 41 result = max14720.init();
douqan93 0:af4d13000e95 42 if (result == MAX14720_ERROR){
douqan93 0:af4d13000e95 43 printf("Error initializing MAX14720");
douqan93 0:af4d13000e95 44 }
douqan93 0:af4d13000e95 45 max14720.boostEn = MAX14720::BOOST_ENABLED;
douqan93 0:af4d13000e95 46 max14720.boostSetVoltage(HVOUT_VOLTAGE);
douqan93 0:af4d13000e95 47 //---------------------------------------------------
douqan93 0:af4d13000e95 48 uint32_t un_min, un_max, un_prev_data; //variables to calculate the on-board LED brightness that reflects the heartbeats
douqan93 0:af4d13000e95 49 int i;
douqan93 0:af4d13000e95 50 int32_t n_brightness;
douqan93 0:af4d13000e95 51 float f_temp;
douqan93 0:af4d13000e95 52 long unBlockedValue = 0;
douqan93 0:af4d13000e95 53
douqan93 0:af4d13000e95 54 maxim_max30102_reset(); //resets the MAX30102
douqan93 0:af4d13000e95 55 wait(1);
douqan93 0:af4d13000e95 56 maxim_max30102_init(); //initializes the MAX30102
douqan93 0:af4d13000e95 57
douqan93 0:af4d13000e95 58 n_brightness=0;
douqan93 0:af4d13000e95 59 un_min=0x3FFFF;
douqan93 0:af4d13000e95 60 un_max=0;
douqan93 0:af4d13000e95 61
douqan93 0:af4d13000e95 62 n_ir_buffer_length=500; //buffer length of 100 stores 5 seconds of samples running at 100sps
douqan93 0:af4d13000e95 63
douqan93 0:af4d13000e95 64 //read the first 500 samples, and determine the signal range
douqan93 0:af4d13000e95 65 for(i=0;i<n_ir_buffer_length;i++)
douqan93 0:af4d13000e95 66 {
douqan93 0:af4d13000e95 67 while(INT.read()==1); //wait until the interrupt pin asserts
douqan93 0:af4d13000e95 68
douqan93 0:af4d13000e95 69 maxim_max30102_read_fifo((aun_red_buffer+i), (aun_ir_buffer+i)); //read from MAX30102 FIFO
douqan93 0:af4d13000e95 70
douqan93 0:af4d13000e95 71 if(un_min>aun_red_buffer[i])
douqan93 0:af4d13000e95 72 un_min=aun_red_buffer[i]; //update signal min
douqan93 0:af4d13000e95 73 if(un_max<aun_red_buffer[i])
douqan93 0:af4d13000e95 74 un_max=aun_red_buffer[i]; //update signal max
douqan93 0:af4d13000e95 75 /*usbSerial.printf("red=");
douqan93 0:af4d13000e95 76 usbSerial.printf("%i", aun_red_buffer[i]);
douqan93 0:af4d13000e95 77 usbSerial.printf(", ir=");
douqan93 0:af4d13000e95 78 usbSerial.printf("%i\n\r", aun_ir_buffer[i]);*/
douqan93 0:af4d13000e95 79 }
douqan93 0:af4d13000e95 80 un_prev_data=aun_red_buffer[i];
douqan93 0:af4d13000e95 81
douqan93 0:af4d13000e95 82
douqan93 0:af4d13000e95 83 //calculate heart rate and SpO2 after first 500 samples (first 5 seconds of samples)
douqan93 0:af4d13000e95 84 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);
douqan93 0:af4d13000e95 85
douqan93 0:af4d13000e95 86 //Continuously taking samples from MAX30102. Heart rate and SpO2 are calculated every 1 second
douqan93 0:af4d13000e95 87
douqan93 0:af4d13000e95 88
douqan93 0:af4d13000e95 89 while (1) {
douqan93 0:af4d13000e95 90 i=0;
douqan93 0:af4d13000e95 91 un_min=0x3FFFF;
douqan93 0:af4d13000e95 92 un_max=0;
douqan93 0:af4d13000e95 93
douqan93 0:af4d13000e95 94 //dumping the first 100 sets of samples in the memory and shift the last 400 sets of samples to the top
douqan93 0:af4d13000e95 95 for(i=200;i<500;i++)
douqan93 0:af4d13000e95 96 {
douqan93 0:af4d13000e95 97 aun_red_buffer[i-200]=aun_red_buffer[i];
douqan93 0:af4d13000e95 98 aun_ir_buffer[i-200]=aun_ir_buffer[i];
douqan93 0:af4d13000e95 99
douqan93 0:af4d13000e95 100 //update the signal min and max
douqan93 0:af4d13000e95 101 if(un_min>aun_red_buffer[i])
douqan93 0:af4d13000e95 102 un_min=aun_red_buffer[i];
douqan93 0:af4d13000e95 103 if(un_max<aun_red_buffer[i])
douqan93 0:af4d13000e95 104 un_max=aun_red_buffer[i];
douqan93 0:af4d13000e95 105 }
douqan93 0:af4d13000e95 106
douqan93 0:af4d13000e95 107 //take 100 sets of samples before calculating the heart rate.
douqan93 0:af4d13000e95 108 for(i=300;i<500;i++)
douqan93 0:af4d13000e95 109 {
douqan93 0:af4d13000e95 110 un_prev_data=aun_red_buffer[i-1];
douqan93 0:af4d13000e95 111 while(INT.read()==1);
douqan93 0:af4d13000e95 112 maxim_max30102_read_fifo((aun_red_buffer+i), (aun_ir_buffer+i));
douqan93 0:af4d13000e95 113
douqan93 0:af4d13000e95 114 if(aun_red_buffer[i]>un_prev_data)
douqan93 0:af4d13000e95 115 {
douqan93 0:af4d13000e95 116 f_temp=aun_red_buffer[i]-un_prev_data;
douqan93 0:af4d13000e95 117 f_temp/=(un_max-un_min);
douqan93 0:af4d13000e95 118 f_temp*=MAX_BRIGHTNESS;
douqan93 0:af4d13000e95 119 n_brightness-=(int)f_temp;
douqan93 0:af4d13000e95 120 if(n_brightness<0)
douqan93 0:af4d13000e95 121 n_brightness=0;
douqan93 0:af4d13000e95 122 }
douqan93 0:af4d13000e95 123 else
douqan93 0:af4d13000e95 124 {
douqan93 0:af4d13000e95 125 f_temp=un_prev_data-aun_red_buffer[i];
douqan93 0:af4d13000e95 126 f_temp/=(un_max-un_min);
douqan93 0:af4d13000e95 127 f_temp*=MAX_BRIGHTNESS;
douqan93 0:af4d13000e95 128 n_brightness+=(int)f_temp;
douqan93 0:af4d13000e95 129 if(n_brightness>MAX_BRIGHTNESS)
douqan93 0:af4d13000e95 130 n_brightness=MAX_BRIGHTNESS;
douqan93 0:af4d13000e95 131 }
douqan93 0:af4d13000e95 132 //send samples and calculation result to terminal program through UART
douqan93 0:af4d13000e95 133 /*usbSerial.printf("red=");
douqan93 0:af4d13000e95 134 usbSerial.printf("%i", aun_red_buffer[i]);
douqan93 0:af4d13000e95 135 usbSerial.printf(", ir=");
douqan93 0:af4d13000e95 136 usbSerial.printf("%i", aun_ir_buffer[i]);*/
douqan93 0:af4d13000e95 137 usbSerial.printf("HR=%i\t", n_heart_rate);
douqan93 0:af4d13000e95 138 //usbSerial.printf("HRvalid=%i, ", ch_hr_valid);
douqan93 0:af4d13000e95 139 usbSerial.printf("SpO2=%i\n\r", n_sp02);
douqan93 0:af4d13000e95 140 //usbSerial.printf("SPO2Valid=%i\n\r", ch_spo2_valid);
douqan93 0:af4d13000e95 141 }
douqan93 0:af4d13000e95 142 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);
douqan93 0:af4d13000e95 143 }
douqan93 0:af4d13000e95 144 }