Bradley Kohler
/
PulseRate
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