This blog provides an experience about the implementation of MCU firmware for ADI’s “Best-in-Class Optical Pulse Oximeter and Heart-Rate Sensor AFE for Wearable Health”: MAX86174A
https://www.analog.com/en/products/max86174a.html#product-overview
- Some important points are emphasized.
- Communication protocol: I2C
Step 1: Create driver files:
- max86174A.h
- max86174A.c
Step 2: Define the register’s address using a readable name in max86174A.h
- Referring to “Register Map” in the datasheet (page 43)
E.g.
#define MAX86174A_Status_1 0x00
#define MAX86174A_Status_2 0x01
…
Step 3: implement the necessary functions in max86174A.c
-
The most important communication function (communication):
uint32_t max86174A_ readReg (uint8_t reg, uint8_t len);
// Input is the register address, and the number of bytes that will be read from the register
// Output is the value in the target registervoid max86174A_writeReg (uint8_t reg, uint8_t *val);
// Input is the register address, and the pointer that is saving the value to be written, such as an array
-
The configuration functions:
void max86174A_reset();
// Register MAX86174A_System_Configuration_1 (0x11), set RESET bit to 1
void max86174A_setFs(uint32_t Fs);
// Register MAX86174A_FR_Clock_Divider_MSB (0x1B), set the value to the corresponding frame rate (fps)
void max86174A_enable_MEAS(uint8_t Num_MEAS)
// Set the register MAX86174A_System_Configuration_2, to enable the corresponding MEAS.
// Also should set the PPG1_PWRDN and PPG2_PWRDN to enable/disable the ADC channels, in register MAX86174A_System_Configuration_1 (0x11), here 0 is enable, 1 is disablevoid max86174A_setLED(uint8_t MEAS_x, uint8_t DRVA, uint8_t DRVA_POW, uint8_t DRVB, uint8_t DRVB_POW)
// The MEAS_x is the number of the measurement
// There are two LED drivers for each measurement, select which LEDs are driven in register MAX86174A_MEASx_Selects(0x20+8*MEAS_x),
// Then set the driving current in MAX86174A_MEASx_LEDA_Current (0x25+8*MEAS_x) and MEAS1_LEDB_Current(0x26+8*MEAS_x), respectively
// Important: if the LED4 is used, in the register MAX86174A_Output_Pin_Configuration, the TRIGLED4_SEL bit must be set to 1void max86174A_setPD(uint8_t MEAS_x, uint8_t ADC_TINT, uint8_t ADC_RGE)
// Set the ADC integrate time in MAX86174A_MEASx_Configuration_1 (0x21+8*MEAS_x)
// set ADC range in MAX86174A_MEASx_Configuration_2 (0x22+8*MEAS_x)void max86174A_start();
// In register MAX86174A_System_Configuration_1 (0x11), set SHDN bit to 0 to start running
void max86174A _stop();
// In register MAX86174A_System_Configuration_1 (0x11), set SHDN bit to 1 so stop running
void max86174A_read_FIFO_Data(double* data, uint32_t data_len)
// The data can only be readout from FIFO, each data is 3 bytes, so for reading one data, should read 3 byte from I2C, the register address is MAX86174A_FIFO_Data_Register (0x07)
void max86174A_set_interrupt_FIFO(uint8_t val_full)
// Set the FIFO size in MAX86174A_FIFO_Configuration_1 (0x08), the value in register is the number of empty FIFO, so the number of saved data should be subtracted from 256 (256-val_full)
// Configure the INTB pin, together with the host MCU, to let the MCU know FIFO is full, in register MAX86174A_Output_Pin_Configuration (0x17)
// Enable the interrupt signal at INTB pin, to let the host MCU know the FIFO is full, in register MAX86174A_Interrupt_Enable_1 (0x58)void max86174A_flushFifo()
// Empty the FIFO by set the FLUSH_FIFO bit to 1, in register MAX86174A_FIFO_Configuration_2 (0x09)
-
The initialization functions:
void max86174A _init_user();
// This function call the above-defined functions to make the PPG sensor work. Following is my flow for a reference:
max86174A_reset();
// MEAS1 and MEAS2 are enabled
max86174A _stop();
max86174A _enable_MEAS(2);
// Set the LED for MEAS1
max86174A _setLED(0, 0, 10, 0, 10);
// Set the PD for MEAS1
max86174A _setPD(0, 0, 0);
// Set the LED for MEAS2
max86174A _setLED(1, 0, 0, 0, 0);
// Set the PD for MEAS2
max86174A _setPD(1, 0, 0);
// Set sampling frequency as 100 fps
max86174A _setFs(100);
// Enable an interrupt signal in INTB when there are 250 samples in FIFO
max86174A _set_interrupt_FIFO(250);
// Empty FIFO for initiation
max86174A _flushFifo();
// Start the MAX86174A
max86174A _start();
Step 4: declare the functions above to the file “max86174A.h”:
Step 5: Include the file “max86174A.h” in the main.c:
- Call max86174A _init_user() in the initiation process
- Configure the interrupt callback, read the data from FIFO of max86174 after the INTB signals received.
Have fun!
Reference:
[1] MAX86174A datasheet: https://www.analog.com/media/en/technical-documentation/data-sheets/max86174a-b.pdf
Changed format
[edited by: Jiabin at 6:59 AM (GMT -5) on 17 Feb 2023]