MAX30100 pulse rate sensor
MAX30100.h
- Committer:
- kohlerba
- Date:
- 2017-11-26
- Revision:
- 4:008e40a7d035
- Parent:
- 3:fa37b0c705b3
File content as of revision 4:008e40a7d035:
#ifndef MAX30100_H
#define MAX30100_H
#include "mbed.h"
//definitions
#define MAX30100_ADDRESS 0xAE
// Registers
#define MAX30100_INT_STATUS 0x00 // Which interrupts are tripped
#define MAX30100_INT_ENABLE 0x01 // Which interrupts are active
#define MAX30100_FIFO_WR_PTR 0x02 // Where data is being written
#define MAX30100_OVRFLOW_CTR 0x03 // Number of lost samples
#define MAX30100_FIFO_RD_PTR 0x04 // Where to read from
#define MAX30100_FIFO_DATA 0x05 // Ouput data buffer
#define MAX30100_MODE_CONFIG 0x06 // Control register
#define MAX30100_SPO2_CONFIG 0x07 // Oximetry settings
#define MAX30100_LED_CONFIG 0x09 // Pulse width and power of LEDs
#define MAX30100_TEMP_INTG 0x16 // Temperature value, whole number
#define MAX30100_TEMP_FRAC 0x17 // Temperature value, fraction
#define MAX30100_REV_ID 0xFE // Part revision
#define MAX30100_PART_ID 0xFF // Part ID, normally 0x11
#define POR_PART_ID 0x11
//Mode Configuration register
#define MAX30100_MC_TEMP_EN (1 << 3)
#define MAX30100_MC_RESET (1 << 6)
#define MAX30100_MC_SHDN (1 << 7)
typedef enum Mode {
MAX30100_MODE_HRONLY = 0x02,
MAX30100_MODE_SPO2_HR = 0x03
} Mode;
// SpO2 Configuration register
// Check tables 8 and 9, p19 of the MAX30100 datasheet to see the permissible
// combinations of sampling rates and pulse widths
#define MAX30100_SPC_SPO2_HI_RES_EN (1 << 6)
typedef enum SamplingRate {
MAX30100_SAMPRATE_50HZ = 0x00,
MAX30100_SAMPRATE_100HZ = 0x01,
MAX30100_SAMPRATE_167HZ = 0x02,
MAX30100_SAMPRATE_200HZ = 0x03,
MAX30100_SAMPRATE_400HZ = 0x04,
MAX30100_SAMPRATE_600HZ = 0x05,
MAX30100_SAMPRATE_800HZ = 0x06,
MAX30100_SAMPRATE_1000HZ = 0x07
} SamplingRate;
typedef enum LEDPulseWidth {
MAX30100_SPC_PW_200US_13BITS = 0x00,
MAX30100_SPC_PW_400US_14BITS = 0x01,
MAX30100_SPC_PW_800US_15BITS = 0x02,
MAX30100_SPC_PW_1600US_16BITS = 0x03
} LEDPulseWidth;
// LED Configuration register
typedef enum LEDCurrent {
MAX30100_LED_CURR_0MA = 0x00,
MAX30100_LED_CURR_4_4MA = 0x01,
MAX30100_LED_CURR_7_6MA = 0x02,
MAX30100_LED_CURR_11MA = 0x03,
MAX30100_LED_CURR_14_2MA = 0x04,
MAX30100_LED_CURR_17_4MA = 0x05,
MAX30100_LED_CURR_20_8MA = 0x06,
MAX30100_LED_CURR_24MA = 0x07,
MAX30100_LED_CURR_27_1MA = 0x08,
MAX30100_LED_CURR_30_6MA = 0x09,
MAX30100_LED_CURR_33_8MA = 0x0a,
MAX30100_LED_CURR_37MA = 0x0b,
MAX30100_LED_CURR_40_2MA = 0x0c,
MAX30100_LED_CURR_43_6MA = 0x0d,
MAX30100_LED_CURR_46_8MA = 0x0e,
MAX30100_LED_CURR_50MA = 0x0f
} LEDCurrent;
#define DEFAULT_MODE MAX30100_MODE_HRONLY
#define DEFAULT_SAMPLING_RATE MAX30100_SAMPRATE_100HZ
#define DEFAULT_PULSE_WIDTH MAX30100_SPC_PW_1600US_16BITS
#define DEFAULT_RED_LED_CURRENT MAX30100_LED_CURR_50MA
#define DEFAULT_IR_LED_CURRENT MAX30100_LED_CURR_50MA
#define EXPECTED_PART_ID 0x11
//Set up I2C, (SDA,SCL)
static I2C i2c(I2C_SDA, I2C_SCL);
static Serial pc(USBTX, USBRX); // tx, rx
class MAX30100 {
protected:
public:
//Variables
uint16_t rawIRValue;
uint16_t rawRedValue;
//Wire read and write protocols
static int i2c_write (uint8_t i2c_addr, uint8_t register_addr, char* buffer, uint8_t Nbyte )
{
int ret;
char *tmp_buffer;
tmp_buffer = (char*)malloc(sizeof(char)*(Nbyte+1));
/* First, send device address. Then, send data and STOP condition */
tmp_buffer[0] = register_addr;
memcpy(tmp_buffer+1, buffer, Nbyte);
ret = i2c.write(i2c_addr, tmp_buffer, Nbyte+1, false);
return ret;
}
static int i2c_read (uint8_t i2c_addr, uint8_t register_addr, char* buffer, uint8_t Nbyte )
{
int ret;
/* Send device address, with no STOP condition */
ret = i2c.write(i2c_addr, (const char*)®ister_addr, 1, true);
if(!ret) {
/* Read data, with STOP condition */
ret = i2c.read((i2c_addr|0x01), buffer, Nbyte, false);
}
return ret;
}
//
uint8_t getRevID(void){
char buffer[1];
i2c_read(MAX30100_ADDRESS, MAX30100_REV_ID, &buffer[0], 1);
return buffer[0];
}
uint8_t getPartID(void){
char buffer[1];
i2c_read(MAX30100_ADDRESS, MAX30100_PART_ID, &buffer[0], 1);
return buffer[0];
}
void shutdown(void){
char reg[1];
i2c_read(MAX30100_ADDRESS, MAX30100_MODE_CONFIG, ®[0], 1);
reg[0] = reg[0] | MAX30100_MC_SHDN;
i2c_write(MAX30100_ADDRESS, MAX30100_MODE_CONFIG, ®[0], 1);
}
void resume(void){
char reg[1];
i2c_read(MAX30100_ADDRESS, MAX30100_MODE_CONFIG, ®[0], 1);
reg[0] = reg[0] & ~MAX30100_MC_SHDN;
i2c_write(MAX30100_ADDRESS, MAX30100_MODE_CONFIG, ®[0], 1);
}
void update(void){
readFifoData();
}
void printRegisters(void){
char reg[1];
i2c_read(MAX30100_ADDRESS, MAX30100_INT_STATUS, ®[0], 1);
pc.printf("MAX30100_INT_STATUS: %d\r\n",reg[0]);
i2c_read(MAX30100_ADDRESS, MAX30100_INT_ENABLE, ®[0], 1);
pc.printf("MAX30100_INT_ENABLE: %d\r\n",reg[0]);
i2c_read(MAX30100_ADDRESS, MAX30100_FIFO_WR_PTR, ®[0], 1);
pc.printf("MAX30100_FIFO_WR_PTR: %d\r\n",reg[0]);
i2c_read(MAX30100_ADDRESS, MAX30100_OVRFLOW_CTR, ®[0], 1);
pc.printf("MAX30100_OVRFLOW_CTR: %d\r\n",reg[0]);
i2c_read(MAX30100_ADDRESS, MAX30100_FIFO_RD_PTR, ®[0], 1);
pc.printf("MAX30100_FIFO_RD_PTR: %d\r\n",reg[0]);
i2c_read(MAX30100_ADDRESS, MAX30100_FIFO_DATA, ®[0], 1);
pc.printf("MAX30100_FIFO_DATA: %d\r\n",reg[0]);
i2c_read(MAX30100_ADDRESS, MAX30100_MODE_CONFIG, ®[0], 1);
pc.printf("MAX30100_MODE_CONFIG: %d\r\n",reg[0]);
i2c_read(MAX30100_ADDRESS, MAX30100_SPO2_CONFIG, ®[0], 1);
pc.printf("MAX30100_SPO2_CONFIG: %d\r\n",reg[0]);
i2c_read(MAX30100_ADDRESS, MAX30100_LED_CONFIG, ®[0], 1);
pc.printf("MAX30100_LED_CONFIG: %d\r\n",reg[0]);
i2c_read(MAX30100_ADDRESS, MAX30100_TEMP_INTG, ®[0], 1);
pc.printf("MAX30100_TEMP_INTG: %d\r\n",reg[0]);
i2c_read(MAX30100_ADDRESS, MAX30100_TEMP_FRAC, ®[0], 1);
pc.printf("MAX30100_TEMP_FRAC: %d\r\n",reg[0]);
i2c_read(MAX30100_ADDRESS, MAX30100_REV_ID, ®[0], 1);
pc.printf("MAX30100_REV_ID: %d\r\n",reg[0]);
i2c_read(MAX30100_ADDRESS, MAX30100_PART_ID, ®[0], 1);
pc.printf("MAX30100_PART_ID: %d\r\n",reg[0]);
}
bool begin(){
if(getPartID() != POR_PART_ID){
return false;
}
setMode(DEFAULT_MODE);
setLedsPulseWidth(DEFAULT_PULSE_WIDTH);
setSamplingRate(DEFAULT_SAMPLING_RATE);
setLedsCurrent(DEFAULT_IR_LED_CURRENT, DEFAULT_RED_LED_CURRENT);
setHighresModeEnabled(true);
return true;
}
void setMode(Mode mode){
char reg[1];
reg[0] = mode;
i2c_write(MAX30100_ADDRESS, MAX30100_MODE_CONFIG, ®[0], 1);
}
void setLedsPulseWidth(LEDPulseWidth ledPulseWidth){
char reg[1];
i2c_read(MAX30100_ADDRESS, MAX30100_SPO2_CONFIG, ®[0], 1);
reg[0] = (reg[0] & 0xfc) | ledPulseWidth;
i2c_write(MAX30100_ADDRESS, MAX30100_SPO2_CONFIG, ®[0], 1);
}
void setSamplingRate(SamplingRate samplingRate){
char reg[1];
i2c_read(MAX30100_ADDRESS, MAX30100_SPO2_CONFIG, ®[0], 1);
reg[0] = (reg[0] & 0xe3) | (samplingRate << 2);
i2c_write(MAX30100_ADDRESS, MAX30100_SPO2_CONFIG, ®[0], 1);
}
void setLedsCurrent(LEDCurrent irLedCurrent, LEDCurrent redLedCurrent){
char reg[1];
reg[0] = (redLedCurrent << 4) | irLedCurrent;
i2c_write(MAX30100_ADDRESS, MAX30100_LED_CONFIG, ®[0], 1);
}
void setHighresModeEnabled(bool enabled){
char reg[1];
i2c_read(MAX30100_ADDRESS, MAX30100_SPO2_CONFIG, ®[0], 1);
if(enabled){
reg[0] = reg[0] | MAX30100_SPC_SPO2_HI_RES_EN;
}
else{
reg[0] = reg[0] & ~MAX30100_SPC_SPO2_HI_RES_EN;
}
i2c_write(MAX30100_ADDRESS, MAX30100_SPO2_CONFIG, ®[0], 1);
}
void readFifoData(void){
char reg[4];
i2c_read(MAX30100_ADDRESS, MAX30100_FIFO_DATA, ®[0], 4);
rawIRValue = (reg[0] << 8) | reg[1];
rawRedValue = (reg[2] << 8) | reg[3];
}
void startTemperatureSampling(void){
char reg[1];
i2c_read(MAX30100_ADDRESS, MAX30100_MODE_CONFIG, ®[0], 1);
reg[0] = reg[0] | MAX30100_MC_TEMP_EN;
i2c_write(MAX30100_ADDRESS, MAX30100_MODE_CONFIG, ®[0], 1);
}
bool isTemperatureReady(void){
char reg[1];
bool ret;
ret = i2c_read(MAX30100_ADDRESS, MAX30100_MODE_CONFIG, ®[0], 1);
ret = ret & MAX30100_MC_TEMP_EN;
return !ret;
}
float retrieveTemperature(void){
char reg[2];
i2c_read(MAX30100_ADDRESS, MAX30100_TEMP_INTG, ®[0], 1);
i2c_read(MAX30100_ADDRESS, MAX30100_TEMP_FRAC, ®[1], 1);
return reg[0] + (reg[1] * 0.0625);
}
};
#endif
Bradley Kohler