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