Shunlong Xiao
Published © GPL3+

Read Your Oxygen and Heart Rate on iPhone!

This is the two-day Aggie Invent competition product sponsored by Maxim Integrated and Nexpaq.

IntermediateShowcase (no instructions)Over 1 day1,677
Read Your Oxygen and Heart Rate on iPhone!

Things used in this project

Story

Read more

Code

Sensor Firmware

C/C++
Sense the heart rate and oxygen of human body and transfer the data to the phone UI by I2C protocol
#include "mbed.h"
#include "nexpaq_mdk.h"
#include "algorithm.h"
#include "MAX30102.h"

//DigitalOut ledR(P2_4, LED_OFF);
//DigitalOut ledG(P2_5, LED_OFF);
//DigitalOut ledB(P2_6, LED_OFF);
DigitalIn button(P0_1, PullUp);

/***** Definitions *****/
#define		FUNCTION_TABLE_NUM					1
#define		UUID_NUM							16			//UUID number is 16, don't change it
#define     LOOP_DELAY                          100

#define 	MAX_BRIGHTNESS 						255
uint32_t aun_ir_buffer[500]; //IR LED sensor data
int32_t n_ir_buffer_length;    //data length
uint32_t aun_red_buffer[500];    //Red LED sensor data
int32_t n_sp02; //SPO2 value
int8_t ch_spo2_valid;   //indicator to show if the SP02 calculation is valid
int32_t n_heart_rate;   //heart rate value
int8_t  ch_hr_valid;    //indicator to show if the heart rate calculation is valid
uint8_t uch_dummy;

Serial pc(USBTX, USBRX);    //initializes the serial port

PwmOut ledB(P2_6);    //initializes the pwm output that connects to the on board LED
DigitalIn INT(P1_3);  //pin P13 connects to the interrupt output pin of the MAX30102  // P13 long

/***** Globals *****/
void my_function_CMD_2700(unsigned char *pData, unsigned char len);
const MDK_REGISTER_CMD my_cmd_func_table[FUNCTION_TABLE_NUM] = {
    {0x2700, my_function_CMD_2700},		// Command -> function
};

int lastBtn = 1;
unsigned char dataarray[2];

/***** Functions *****/
void my_function_CMD_2700(unsigned char *pData, unsigned char len)
{
    unsigned char response = 0x00;
    //ledR = (pData[0]>0) ? LED_ON : LED_OFF ;
    //ledG = (pData[1]>0) ? LED_ON : LED_OFF ;
    //ledB = (pData[2]>0) ? LED_ON : LED_OFF ;
    np_api_upload(0x2701, &response, 1);
}

/******************************************************************************/
void app_setup()
{
    if ( np_api_register((MDK_REGISTER_CMD*)my_cmd_func_table, FUNCTION_TABLE_NUM) == MDK_REGISTER_FAILD ) {
        // Register failed handle code
        error("MDK Register Failed");
    }
}

void app_loop()
{
    dataarray[0] = n_heart_rate;
    dataarray[1] = n_sp02;
    np_api_upload(0x2800, dataarray, 2);


}

int main(void)
{

    np_api_init();
    app_setup();
    np_api_start();
    uint32_t un_min, un_max, un_prev_data;  //variables to calculate the on-board LED brightness that reflects the heartbeats
    int i;
    int32_t n_brightness;
    float f_temp;

    maxim_max30102_reset(); //resets the MAX30102
    // initialize serial communication at 115200 bits per second:
    pc.baud(9600);   // 115200  long
    pc.format(8,SerialBase::None,1);
    //wait(1);

    //read and clear status register
    maxim_max30102_read_reg(0,&uch_dummy);

    //wait until the user presses a key
    //while(pc.readable()==0)
    //{
    // pc.printf("\x1B[2J");  //clear terminal program screen
    // pc.printf("Press any key to start conversion\n\r");
    // wait(1);
    //}
    //uch_dummy=getchar();

    maxim_max30102_init();  //initializes the MAX30102


    n_brightness=0;
    un_min=0x3FFFF;
    un_max=0;

    n_ir_buffer_length=500; //buffer length of 100 stores 5 seconds of samples running at 100sps


    while(1) {
        Thread::wait(LOOP_DELAY);  //long
        //wait(1);  //long

        np_api_bsl_chk();
		// app_loop();

        un_min=0x3FFFF;
        un_max=0;

        //dumping the first 100 sets of samples in the memory and shift the last 400 sets of samples to the top
        for(i=100; i<500; i++) {
            aun_red_buffer[i-100]=aun_red_buffer[i];
            aun_ir_buffer[i-100]=aun_ir_buffer[i];

            //update the signal min and max
            if(un_min>aun_red_buffer[i])
                un_min=aun_red_buffer[i];
            if(un_max<aun_red_buffer[i])
                un_max=aun_red_buffer[i];
        }

        //take 100 sets of samples before calculating the heart rate.
        for(i=400; i<500; i++) {
            un_prev_data=aun_red_buffer[i-1];
            while(INT.read()==1);
            maxim_max30102_read_fifo((aun_red_buffer+i), (aun_ir_buffer+i));

            if(aun_red_buffer[i]>un_prev_data) {
                f_temp=aun_red_buffer[i]-un_prev_data;
                f_temp/=(un_max-un_min);
                f_temp*=MAX_BRIGHTNESS;
                n_brightness-=(int)f_temp;
                if(n_brightness<0)
                    n_brightness=0;
            } else {
                f_temp=un_prev_data-aun_red_buffer[i];
                f_temp/=(un_max-un_min);
                f_temp*=MAX_BRIGHTNESS;
                n_brightness+=(int)f_temp;
                if(n_brightness>MAX_BRIGHTNESS)
                    n_brightness=MAX_BRIGHTNESS;
            }

            ledB.write(1-(float)n_brightness/256);     // we can write fraction into the led register????!!!! long


            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);
            //send samples and calculation result to terminal program through UART

            if (n_heart_rate>200)  {
                n_heart_rate=255;
            }
            if (n_sp02>100)  {
                n_sp02=255;
            }
           pc.printf(", HR=%i, ", n_heart_rate);
            pc.printf("HRvalid=%i, ", ch_hr_valid);
           pc.printf("SpO2=%i, ", n_sp02);
            pc.printf("SPO2Valid=%i\n\r", ch_spo2_valid);
             app_loop();
            //wait(1);    // long
        }
       

    }
    return 0;
}

Credits

Shunlong Xiao

Shunlong Xiao

1 project • 1 follower
Ph.D. in Power Electronics Interest in internet of things

Comments