Learning about the MAX32630FTHR board (Part 3): Preliminary use of the MAX30102 and the measurement principles of heart rate and blood oxygen
[Copy link]
This post was last edited by anning865 on 2017-8-6 17:30 In the previous post, the MAX32630FTHR board was used to drive the heart rate pulse sensor, and the heart rate value and pulse image were obtained. This post introduces and studies an optical sensor MAX30102 produced by Maxim. Maxim's MAX30102 is an integrated pulse oximeter and heart rate monitor biosensor module. It integrates a red LED and an infrared LED, a photodetector, an optical device, and a low-noise electronic circuit with ambient light suppression. MAX30102 uses a 1.8V power supply and an independent 5.0V power supply for the internal LED. It is used in wearable devices for heart rate and blood oxygen collection and detection, and is worn on fingers, earlobes, wrists, etc. The standard I2C-compatible communication interface can transmit the collected values to Arduino, KL25Z and other microcontrollers for heart rate and blood oxygen calculation. In addition, the chip can also shut down the module through software, and the standby current is close to zero, so that the power supply is always maintained. Because of its excellent performance, this chip is widely used in Samsung Galaxy S7 mobile phones. Compared with the previous generation product MAX30100 (MAX30100 has been discontinued and eliminated), MAX30102 integrates a glass cover to effectively eliminate external and internal light interference, and has the best and most reliable performance. Compared with pulse sensor, the advantages of MAX30102 are: 1. High integration: MAX30102 integrates two light-emitting LEDs, photodetection diodes, ADC, ambient light suppression circuit and optical mechanical housing to form a complete module. The advantages are small size, low energy consumption, low external interference, and easy system integration. 2. Digital output: MAX30102 itself has an 18-bit high-precision ADC and uses the I2C interface to communicate with the external MCU. It also has a FIFO, which can reduce the burden on the MCU and reduce power consumption. 3. Rich functions: MAX30102 integrates LED drive circuit, which can adjust the LED current according to different situations, and the sampling rate can also be selected according to different applications. In addition, an on-chip temperature sensor is integrated to monitor the on-chip temperature at any time (useful for blood oxygen saturation calculation). It is precisely because of the above advantages that the current analog integrated front end (AFE) is moving towards integration, miniaturization, and digitization, and the threshold for analog circuits is getting lower and lower. First, let's take a look at the block diagram of the MAX30102: Figure 1, block diagram of the MAX30102 The light-emitting part of the MAX30102 includes two LEDs, one is a red LED (660nm) and the other is an infrared LED (880nm). This is the most common configuration for measuring blood oxygen saturation SPO2. The receiving part is a photodiode that is sensitive to both visible light and infrared light. The received light intensity signal is converted into a current signal. After passing through the ambient light elimination circuit, it is finally sampled and converted by the built-in 18-bit ADC, and the analog part is completed. The digital converted by AD is stored in the data register after digital filtering, and can finally be read by the external MCU through the I2C bus. In terms of hardware, the power supply of the LED is not the same as the power supply of other parts, because the LED needs a large instantaneous current (maximum 50ma) to ensure sufficient output light intensity, which requires the forward voltage of the LED to be large enough (required to be above 3.1V). For the rest of the AD conversion and I2C bus parts, in order to achieve low power consumption, the voltage is required to be small enough (required to be 1.8V), so the sensor needs two independent power supplies. In addition, since the LED power supply will generate a large instantaneous current, a large capacitor should be added near the power pin to reduce the impact on the power supply voltage.
Figure 2, MAX30102 Pin Diagram There are three main traditional pulse measurement methods: one is to extract from the ECG signal; the second is to calculate the pulse rate from the fluctuations measured by the pressure sensor when measuring blood pressure; the third is photoelectric capacitance. The first two methods of extracting signals will limit the patient's activities. If used for a long time, it will increase the patient's physiological and psychological discomfort. As one of the most common methods of monitoring measurement, photoelectric capacitance pulse measurement has the characteristics of simple method, easy to wear, and high reliability. The basic principle of photoelectric capacitance is to use the different light transmittances caused by human tissue when the blood vessels pulsate to measure pulse and blood oxygen saturation. The sensor used consists of two parts: a light source and a photoelectric converter, which is fixed to the patient's finger, wrist or earlobe by a strap or clip. The light source generally uses a light-emitting diode with a specific wavelength that is selective for oxygenated hemoglobin (HbO2) and deoxygenated hemoglobin (Hb) in arterial blood (generally red light around 660nm and infrared light around 900nm). When the light beam passes through the human peripheral blood vessels, the transmittance of this light beam changes due to the change in volume caused by arterial pulsation and congestion. At this time, the photoelectric converter receives the light reflected by the human tissue, converts it into an electrical signal, amplifies it and outputs it. Since the pulse is a signal that changes periodically with the beating of the heart, the volume of the arterial blood vessels also changes periodically, so the change period of the electrical signal of the photoelectric converter is the pulse rate. At the same time, according to the definition of blood oxygen saturation, it is expressed as:
Figure 3. Definition of blood oxygen saturation
Figure 4. Absorption of oxygenated hemoglobin (HbO2) and deoxygenated hemoglobin (Hb) at different wavelengths MAX30102 itself integrates the complete light-emitting LED and driver part, light sensing and AD conversion part, ambient light interference elimination and digital filtering part, leaving only the digital interface to the user, greatly reducing the user's design burden. The user only needs to use the microcontroller to read the FIFO of the MAX30102 itself through the hardware I2C or simulated I2C interface to obtain the converted light intensity value, and the heart rate value and blood oxygen saturation can be obtained by writing the corresponding algorithm. In order to facilitate the verification of the use of MAX30102 and MAX32630FTHR board, I bought a ready-made MAX30102 module from Taobao. However, what is unexpected is that there are big problems with the design of this module itself. The pull-up voltage of its I2C bus is forced to be fixed at 1.8V, which causes the module to be 3.3v with the IO port,5v microcontroller can't communicate normally! It's really a stupid design! I wasted a lot of time to find the reason. Later, I saw some foreigners complaining on GITHUB, and then I understood! Finally, I could only solve it by flying wires.
Figure 5. A problematic module design on Xbao Figure 6. Problematic module and flying wire solution This time, let's simply verify that the MAX32630FTHR board can communicate with the MAX30102 through the I2C bus, so I wrote a program on MBED to read the temperature on the MAX30102 chip and print out the temperature result through the serial port. The specific procedure is as follows: - #include "mbed.h" #include "max32630fthr.h" #define false 0 #define true 1 MAX32630FTHR pegasus(MAX32630FTHR::VIO_3V3); Serial pc(USBTX, USBRX);//USB TO SERIAL DigitalIn INT(P3_2); //pin P3.2 connects to the interrupt output pin of the MAX30102 I2C i2cm1(P3_4, P3_5); #define I2C_WRITE_ADDR 0xAE #define I2C_READ_ADDR 0xAF //register addresses #define REG_INTR_STATUS_1 0x00 #define REG_INTR_STATUS_2 0x01 #define REG_INTR_ENABLE_1 0x02 #define REG_INTR_ENABLE_2 0x03 #define REG_FIFO_WR_PTR 0x04 #define REG_OVF_COUNTER 0x05 #define REG_FIFO_RD_PTR 0x06 #define REG_FIFO_DATA 0x07 #define REG_FIFO_CONFIG 0x08 #define REG_MODE_CONFIG 0x09 #define REG_SPO2_CONFIG 0x0A #define REG_LED1_PA 0x0C #define REG_LED2_PA 0x0D #define REG_PILOT_PA 0x10 #define REG_MULTI_LED_CTRL1 0x11 #define REG_MULTI_LED_CTRL2 0x12 #define REG_TEMP_INTR 0x1F #define REG_TEMP_FRAC 0x20 #define REG_TEMP_CONFIG 0x21 #define REG_PROX_INT_THRESH 0x30 #define REG_REV_ID 0xFE #define REG_PART_ID 0xFF bool maxim_max30102_write_reg(uint8_t uch_addr, uint8_t uch_data) /** * \brief Write a value to a MAX30102 register * \par Details * This function writes a value to a MAX30102 register * * \param[in] uch_addr - register address * \param[in] uch_data - register data * * \retval true on success */ { char ach_i2c_data[2]; ach_i2c_data[0]=uch_addr; ach_i2c_data[1]=uch_data; if(i2cm1.write(I2C_WRITE_ADDR, ach_i2c_data, 2, false)==0) return true; else return false; } bool maxim_max30102_read_reg(uint8_t uch_addr, uint8_t *puch_data) /** * \brief Read a MAX30102 register * \par Details * This function reads a MAX30102 register * * \param[in] uch_addr - register address * \param[out] puch_data - pointer that stores the register data * * \retval true on success */ { char ch_i2c_data; ch_i2c_data=uch_addr; if(i2cm1.write(I2C_WRITE_ADDR, &ch_i2c_data, 1, true)!=0) return false; if(i2cm1.read(I2C_READ_ADDR, &ch_i2c_data, 1, false)==0) { *puch_data=(uint8_t) ch_i2c_data; return true; } else return false; } bool maxim_max30102_reset() /** * \brief Reset the MAX30102 * \par Details * This function resets the MAX30102 * * \param None * * \retval true on success */ { if(!maxim_max30102_write_reg(REG_MODE_CONFIG,0x40)) return false; else return true; } bool maxim_max30102_init() /** * \brief Initialize the MAX30102 * \par Details * This function initializes the MAX30102 * * \param None * * \retval true on success */ { if(!maxim_max30102_write_reg(REG_INTR_ENABLE_1,0xc0)) // INTR setting return false; if(!maxim_max30102_write_reg(REG_INTR_ENABLE_2,0x02)) return false; if(!maxim_max30102_write_reg(REG_FIFO_WR_PTR,0x00)) //FIFO_WR_PTR[4:0] return false; if(!maxim_max30102_write_reg(REG_OVF_COUNTER,0x00)) //OVF_COUNTER[4:0] return false; if(!maxim_max30102_write_reg(REG_FIFO_RD_PTR,0x00)) //FIFO_RD_PTR[4:0] return false; if(!maxim_max30102_write_reg(REG_FIFO_CONFIG,0x0f)) //sample avg = 1, fifo rollover=false, fifo almost full = 17 return false; if(!maxim_max30102_write_reg(REG_MODE_CONFIG,0x03)) //0x02 for Red only, 0x03 for SpO2 mode 0x07 multimode LED return false; if(!maxim_max30102_write_reg(REG_SPO2_CONFIG,0x27)) // SPO2_ADC range = 4096nA, SPO2 sample rate (100 Hz), LED pulseWidth (400uS) return false; if(!maxim_max30102_write_reg(REG_LED1_PA,0x24)) //Choose value for ~ 7mA for LED1 return false; if(!maxim_max30102_write_reg(REG_LED2_PA,0x24)) //Choose value for ~ 7mA for LED2 return false; if(!maxim_max30102_write_reg(REG_PILOT_PA,0x7f)) // Choose value for ~ 25mA for Pilot LED return false; if(!maxim_max30102_write_reg(REG_TEMP_CONFIG,0x01)) // En temp return false; return true; } int main() { uint8_t temp_inter,temp_fra; float temp_value; maxim_max30102_reset(); //resets the MAX30102 // initialize serial communication at 9600 bits per second: pc.baud(9600); pc.format(8,SerialBase::None,1); pc.printf("ready to go!"); wait(1); //read and clear status register maxim_max30102_read_reg(0,&temp_inter); maxim_max30102_init(); while(1) { while(INT.read()==1); maxim_max30102_read_reg(REG_TEMP_INTR,&temp_inter); maxim_max30102_read_reg(REG_TEMP_FRAC,&temp_fra); temp_value=temp_inter+temp_fra*0.0625; pc.printf("temperature is %6.4f \n\r", temp_value); } }
复制代码 Remember to add MAX32630FTHR and MBED library files to the above code on the MBED platform. Figure 7, Experimental pictures (The LED of MAX30102 is already on) Figure 8. Serial port outputs temperature data Finally, the KEIL PACK package has been released from the forum. MBED programs can finally be exported to KEIL for debugging, but I can't find it in the download options. I have consulted several forum friends about the FLASH options of MAX32630, hoping that some successful people can give me some advice. Attach the exported KEIL project file
FTHR_MAX30102_temp_uvision5_max32630fthr.zip
(4.62 MB, downloads: 2715)
maxim_max30102_write_reg(REG_INTR_ENABLE_1,0xc0)) // INTR setting return false; if(!maxim_max30102_write_reg(REG_INTR_ENABLE_2,0x02)) return false; if(!maxim_max30102_write_reg(REG_FIFO_WR_PTR,0x00)) //FIFO_WR_PTR[4:0] return false; if(!maxim_max30102_write_reg(REG_OVF_COUNTER,0x00)) //OVF_COUNTER[4:0] return false; if(!maxim_max30102_write_reg(REG_FIFO_RD_PTR,0x00)) //FIFO_RD_PTR[4:0] return false; if(!maxim_max30102_write_reg(REG_FIFO_CONFIG,0x0f)) //sample avg = 1, fifo rollover=false, fifo almost full = 17 return false; if(!maxim_max30102_write_reg(REG_MODE_CONFIG,0x03)) //0x02 for Red only, 0x03 for SpO2 mode 0x07 multimode LED return false; if(!maxim_max30102_write_reg(REG_SPO2_CONFIG,0x27)) // SPO2_ADC range = 4096nA, SPO2 sample rate (100 Hz), LED pulseWidth (400uS) return false; if(!maxim_max30102_write_reg(REG_LED1_PA,0x24)) //Choose value for ~ 7mA for LED1 return false; if(!maxim_max30102_write_reg(REG_LED2_PA,0x24)) // Choose value for ~ 7mA for LED2 return false; if(!maxim_max30102_write_reg(REG_PILOT_PA,0x7f)) // Choose value for ~ 25mA for Pilot LED return false; if(!maxim_max30102_write_reg(REG_TEMP_CONFIG,0x01)) // En temp return false; return true; } int main() { uint8_t temp_inter,temp_fra; float temp_value; maxim_max30102_reset(); //resets the MAX30102 // initialize serial communication at 9600 bits per second: pc.baud(9600); pc.format(8,SerialBase::None,1); pc.printf("ready to go!"); wait(1); //read and clear status register maxim_max30102_read_reg(0,&temp_inter); maxim_max30102_init(); while(1) { while(INT.read()==1); maxim_max30102_read_reg(REG_TEMP_INTR,&temp_inter); maxim_max30102_read_reg(REG_TEMP_FRAC,&temp_fra); temp_value=temp_inter+temp_fra*0.0625 ; pc.printf("temperature is %6.4f \n\r", temp_value); } }[/code] Remember to add MAX32630FTHR and MBED library files in the above code on the MBED platform. Figure 7. Experimental picture (the LED of MAX30102 is already on) Figure 8. Serial port output temperature data [font=微软雅黑Finally, the KEIL PACK package has been released by the forum. The MBED program can finally be exported to KEIL for debugging. However, I did not find the MAX32630 FLASH option in the download options. I asked several forum friends for help. I hope someone who has succeeded can give me some advice. . Attach the exported KEIL project file
FTHR_MAX30102_temp_uvision5_max32630fthr.zip
(4.62 MB, downloads: 2715)
maxim_max30102_write_reg(REG_INTR_ENABLE_1,0xc0)) // INTR setting return false; if(!maxim_max30102_write_reg(REG_INTR_ENABLE_2,0x02)) return false; if(!maxim_max30102_write_reg(REG_FIFO_WR_PTR,0x00)) //FIFO_WR_PTR[4:0] return false; if(!maxim_max30102_write_reg(REG_OVF_COUNTER,0x00)) //OVF_COUNTER[4:0] return false; if(!maxim_max30102_write_reg(REG_FIFO_RD_PTR,0x00)) //FIFO_RD_PTR[4:0] return false; if(!maxim_max30102_write_reg(REG_FIFO_CONFIG,0x0f)) //sample avg = 1, fifo rollover=false, fifo almost full = 17 return false; if(!maxim_max30102_write_reg(REG_MODE_CONFIG,0x03)) //0x02 for Red only, 0x03 for SpO2 mode 0x07 multimode LED return false; if(!maxim_max30102_write_reg(REG_SPO2_CONFIG,0x27)) // SPO2_ADC range = 4096nA, SPO2 sample rate (100 Hz), LED pulseWidth (400uS) return false; if(!maxim_max30102_write_reg(REG_LED1_PA,0x24)) //Choose value for ~ 7mA for LED1 return false; if(!maxim_max30102_write_reg(REG_LED2_PA,0x24)) // Choose value for ~ 7mA for LED2 return false; if(!maxim_max30102_write_reg(REG_PILOT_PA,0x7f)) // Choose value for ~ 25mA for Pilot LED return false; if(!maxim_max30102_write_reg(REG_TEMP_CONFIG,0x01)) // En temp return false; return true; } int main() { uint8_t temp_inter,temp_fra; float temp_value; maxim_max30102_reset(); //resets the MAX30102 // initialize serial communication at 9600 bits per second: pc.baud(9600); pc.format(8,SerialBase::None,1); pc.printf("ready to go!"); wait(1); //read and clear status register maxim_max30102_read_reg(0,&temp_inter); maxim_max30102_init(); while(1) { while(INT.read()==1); maxim_max30102_read_reg(REG_TEMP_INTR,&temp_inter); maxim_max30102_read_reg(REG_TEMP_FRAC,&temp_fra); temp_value=temp_inter+temp_fra*0.0625 ; pc.printf("temperature is %6.4f \n\r", temp_value); } }[/code] Remember to add MAX32630FTHR and MBED library files in the above code on the MBED platform. Figure 7. Experimental picture (the LED of MAX30102 is already on) Figure 8. Serial port output temperature data [font=微软雅黑Finally, the KEIL PACK package has been released by the forum. The MBED program can finally be exported to KEIL for debugging. However, I did not find the MAX32630 FLASH option in the download options. I asked several forum friends for help. I hope someone who has succeeded can give me some advice. . Attach the exported KEIL project file
FTHR_MAX30102_temp_uvision5_max32630fthr.zip
(4.62 MB, downloads: 2715)
fifo rollover=false, fifo almost full = 17 return false; if(!maxim_max30102_write_reg(REG_MODE_CONFIG,0x03)) //0x02 for Red only, 0x03 for SpO2 mode 0x07 multimode LED return false; if(!maxim_max30102_write_reg(REG_SPO2_CONFIG,0x27)) // SPO2_ADC range = 4096nA, SPO2 sample rate (100 Hz), LED pulseWidth (400uS) return false; if(!maxim_max30102_write_reg(REG_LED1_PA,0x24)) //Choose value for ~ 7mA for LED1 return false; if(!maxim_max30102_write_reg(REG_LED2_PA,0x24)) // Choose value for ~ 7mA for LED2 return false; if(!maxim_max30102_write_reg(REG_PILOT_PA,0x7f)) // Choose value for ~ 25mA for Pilot LED return false; if(!maxim_max30102_write_reg(REG_TEMP_CONFIG,0x01)) // En temp return false; return true; } int main() { uint8_t temp_inter,temp_fra; float temp_value; maxim_max30102_reset(); //resets the MAX30102 // initialize serial communication at 9600 bits per second: pc.baud(9600); pc.format(8,SerialBase::None,1); pc.printf("ready to go!"); wait(1); //read and clear status register maxim_max30102_read_reg(0,&temp_inter); maxim_max30102_init(); while(1) { while(INT.read()==1); maxim_max30102_read_reg(REG_TEMP_INTR,&temp_inter); maxim_max30102_read_reg(REG_TEMP_FRAC,&temp_fra); temp_value=temp_inter+temp_fra*0.0625; pc.printf("temperature is %6.4f \n\r", temp_value); } }[/code] Remember to add MAX32630FTHR and MBED library files in the above code on the MBED platform. Figure 7. Experimental picture (the LED of MAX30102 is already on) Figure 8. Serial port output temperature data [font=微软雅黑Finally, the KEIL PACK package has been released by the forum. The MBED program can finally be exported to KEIL for debugging. However, I did not find the MAX32630 FLASH option in the download options. I asked several forum friends for help. I hope someone who has succeeded can give me some advice. . Attach the exported KEIL project file
FTHR_MAX30102_temp_uvision5_max32630fthr.zip
(4.62 MB, downloads: 2715)
fifo rollover=false, fifo almost full = 17 return false; if(!maxim_max30102_write_reg(REG_MODE_CONFIG,0x03)) //0x02 for Red only, 0x03 for SpO2 mode 0x07 multimode LED return false; if(!maxim_max30102_write_reg(REG_SPO2_CONFIG,0x27)) // SPO2_ADC range = 4096nA, SPO2 sample rate (100 Hz), LED pulseWidth (400uS) return false; if(!maxim_max30102_write_reg(REG_LED1_PA,0x24)) //Choose value for ~ 7mA for LED1 return false; if(!maxim_max30102_write_reg(REG_LED2_PA,0x24)) // Choose value for ~ 7mA for LED2 return false; if(!maxim_max30102_write_reg(REG_PILOT_PA,0x7f)) // Choose value for ~ 25mA for Pilot LED return false; if(!maxim_max30102_write_reg(REG_TEMP_CONFIG,0x01)) // En temp return false; return true; } int main() { uint8_t temp_inter,temp_fra; float temp_value; maxim_max30102_reset(); //resets the MAX30102 // initialize serial communication at 9600 bits per second: pc.baud(9600); pc.format(8,SerialBase::None,1); pc.printf("ready to go!"); wait(1); //read and clear status register maxim_max30102_read_reg(0,&temp_inter); maxim_max30102_init(); while(1) { while(INT.read()==1); maxim_max30102_read_reg(REG_TEMP_INTR,&temp_inter); maxim_max30102_read_reg(REG_TEMP_FRAC,&temp_fra); temp_value=temp_inter+temp_fra*0.0625; pc.printf("temperature is %6.4f \n\r", temp_value); } }[/code] Remember to add MAX32630FTHR and MBED library files in the above code on the MBED platform. Figure 7. Experimental picture (the LED of MAX30102 is already on) Figure 8. Serial port output temperature data [font=微软雅黑Finally, the KEIL PACK package has been released by the forum. The MBED program can finally be exported to KEIL for debugging. However, I did not find the MAX32630 FLASH option in the download options. I asked several forum friends for help. I hope someone who has succeeded can give me some advice. . Attach the exported KEIL project file
FTHR_MAX30102_temp_uvision5_max32630fthr.zip
(4.62 MB, downloads: 2715)
baud(9600); pc.format(8,SerialBase::None,1); pc.printf("ready to go!"); wait(1); //read and clear status register maxim_max30102_read_reg(0,&temp_inter); maxim_max30102_init(); while(1) { while(INT.read()==1); maxim_max30102_read_reg(REG_TEMP_INTR,&temp_inter); maxim_max30102_read_reg(REG_TEMP_FRAC,&temp_fra); temp_value=temp_inter+temp_fra*0.0625; pc.printf("temperature is %6.4f \n\r", temp_value); } }[/code] Remember to add MAX32630FTHR and MBED library files on the MBED platform. Figure 7. Experimental picture (the LED of MAX30102 is already on) Figure 8. Serial port outputs temperature data Finally, the PACK package of KEIL has been sent out by the forum. The MBED program can finally be exported to KEIL for debugging. However, I did not find the FLASH option of MAX32630 in the download options. I asked several forum friends for help. I hope some successful people can give me some advice. Attach the exported KEIL project file
FTHR_MAX30102_temp_uvision5_max32630fthr.zip
(4.62 MB, downloads: 2715)
baud(9600); pc.format(8,SerialBase::None,1); pc.printf("ready to go!"); wait(1); //read and clear status register maxim_max30102_read_reg(0,&temp_inter); maxim_max30102_init(); while(1) { while(INT.read()==1); maxim_max30102_read_reg(REG_TEMP_INTR,&temp_inter); maxim_max30102_read_reg(REG_TEMP_FRAC,&temp_fra); temp_value=temp_inter+temp_fra*0.0625; pc.printf("temperature is %6.4f \n\r", temp_value); } }[/code] Remember to add MAX32630FTHR and MBED library files on the MBED platform. Figure 7. Experimental picture (the LED of MAX30102 is already on) Figure 8. Serial port outputs temperature data Finally, the PACK package of KEIL has been sent out by the forum. The MBED program can finally be exported to KEIL for debugging. However, I did not find the FLASH option of MAX32630 in the download options. I asked several forum friends for help. I hope some successful people can give me some advice. Attach the exported KEIL project file
FTHR_MAX30102_temp_uvision5_max32630fthr.zip
(4.62 MB, downloads: 2715)
|