MAX30100 pulse rate sensor
Revision 3:fa37b0c705b3, committed 2017-11-26
- Comitter:
- kohlerba
- Date:
- Sun Nov 26 21:56:10 2017 +0000
- Parent:
- 2:d329886938f1
- Child:
- 4:008e40a7d035
- Commit message:
- PulseRate example using serial COM
Changed in this revision
--- a/MAX30100.h Wed Aug 23 19:04:51 2017 +0000
+++ b/MAX30100.h Sun Nov 26 21:56:10 2017 +0000
@@ -4,7 +4,7 @@
#include "mbed.h"
//definitions
-#define MAX30100_ADDRESS 0x57
+#define MAX30100_ADDRESS 0xAE
// Registers
#define MAX30100_INT_STATUS 0x00 // Which interrupts are tripped
@@ -60,7 +60,8 @@
}ledCurrent;
//Set up I2C, (SDA,SCL)
-I2C i2c(I2C_SDA, I2C_SCL);
+static I2C i2c(I2C_SDA, I2C_SCL);
+static Serial pc(USBTX, USBRX); // tx, rx
uint16_t IR = 0; // Last IR reflectance datapoint
uint16_t RED = 0; // Last Red reflectance datapoint
@@ -72,93 +73,146 @@
public:
//Wire read and write protocols
- void writeByte(uint8_t address, uint8_t subAddress, uint8_t data)
+static int i2c_write (uint8_t i2c_addr, uint8_t register_addr, char* buffer, uint8_t Nbyte )
{
- char data_write[2];
- data_write[0] = subAddress;
- data_write[1] = data;
- i2c.write(address, data_write, 2, 0);
-}
+ int ret;
+ char *tmp_buffer;
+
+ tmp_buffer = (char*)malloc(sizeof(char)*(Nbyte+1));
- char readByte(uint8_t address, uint8_t subAddress)
-{
- char data[1]; // `data` will store the register data
- char data_write[1];
- data_write[0] = subAddress;
- i2c.write(address, data_write, 1, 1); // no stop
- i2c.read(address, data, 1, 0);
- return data[0];
+ /* 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;
}
- void readBytes(uint8_t address, uint8_t subAddress, uint8_t count, uint8_t * dest)
-{
- char data[14];
- char data_write[1];
- data_write[0] = subAddress;
- i2c.write(address, data_write, 1, 1); // no stop
- i2c.read(address, data, count, 0);
- for(int ii = 0; ii < count; ii++) {
- dest[ii] = data[ii];
+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;
}
//
-
+
void setLEDs(pulseWidth pw, ledCurrent red, ledCurrent ir){
- uint8_t reg = readByte(MAX30100_ADDRESS, MAX30100_SPO2_CONFIG);
- reg = reg & 0xFC; // Set LED_PW to 00
- writeByte(MAX30100_ADDRESS, MAX30100_SPO2_CONFIG, reg | pw); // Mask LED_PW
- writeByte(MAX30100_ADDRESS, MAX30100_LED_CONFIG, (red<<4) | ir); // write LED configs
+ char reg[1];
+ i2c_read(MAX30100_ADDRESS, MAX30100_SPO2_CONFIG, ®[0], 1);
+ reg[0] = reg[0] & 0xFC; // Set LED_PW to 00
+ reg[0] = reg[0] | pw;
+ i2c_write(MAX30100_ADDRESS, MAX30100_SPO2_CONFIG, ®[0], 1); // Mask LED_PW
+ reg[0] = (red<<4) | ir;
+ i2c_write(MAX30100_ADDRESS, MAX30100_LED_CONFIG, ®[0], 1); // write LED configs
}
void setSPO2(sampleRate sr){
- uint8_t reg = readByte(MAX30100_ADDRESS, MAX30100_SPO2_CONFIG);
- reg = reg & 0xE3; // Set SPO2_SR to 000
- writeByte(MAX30100_ADDRESS, MAX30100_SPO2_CONFIG, reg | (sr<<2)); // Mask SPO2_SR
- reg = readByte(MAX30100_ADDRESS, MAX30100_MODE_CONFIG);
- reg = reg & 0xf8; // Set Mode to 000
- writeByte(MAX30100_ADDRESS, MAX30100_SPO2_CONFIG, reg | 0x03); // Mask MODE
+ char reg[1];
+ i2c_read(MAX30100_ADDRESS, MAX30100_SPO2_CONFIG, ®[0], 1);
+ reg[0] = reg[0] & 0xE3; // Set SPO2_SR to 000
+ reg[0] = reg[0] | (sr<<2);
+ i2c_write(MAX30100_ADDRESS, MAX30100_SPO2_CONFIG, ®[0], 1); // Mask SPO2_SR
+ i2c_read(MAX30100_ADDRESS, MAX30100_MODE_CONFIG, ®[0], 1);
+ reg[0] = reg[0] & 0xf8; // Set Mode to 000
+ reg[0] = reg[0] | 0x03;
+ i2c_write(MAX30100_ADDRESS, MAX30100_SPO2_CONFIG, ®[0], 1); // Mask MODE
}
int getNumSamp(void){
- uint8_t wrPtr = readByte(MAX30100_ADDRESS, MAX30100_FIFO_WR_PTR);
- uint8_t rdPtr = readByte(MAX30100_ADDRESS, MAX30100_FIFO_RD_PTR);
- return (abs( 16 + wrPtr - rdPtr ) % 16);
+ char wrPtr[1];
+ char rdPtr[1];
+ i2c_read(MAX30100_ADDRESS, MAX30100_FIFO_WR_PTR, &wrPtr[0], 1);
+ i2c_read(MAX30100_ADDRESS, MAX30100_FIFO_RD_PTR, &rdPtr[0], 1);
+ return (abs( 16 + wrPtr[0] - rdPtr[0] ) % 16);
}
void readSensor(void){
- uint8_t temp[4] = {0}; // Temporary buffer for read values
- readBytes(MAX30100_ADDRESS, MAX30100_FIFO_DATA, 4, &temp[0]); // Read four times from the FIFO
+ char temp[4] = {0}; // Temporary buffer for read values
+ i2c_read(MAX30100_ADDRESS, MAX30100_FIFO_DATA, &temp[0], 4); // Read four times from the FIFO
IR = (temp[0]<<8) | temp[1]; // Combine values to get the actual number
RED = (temp[2]<<8) | temp[3]; // Combine values to get the actual number
}
void shutdown(void){
- uint8_t reg = readByte(MAX30100_ADDRESS, MAX30100_MODE_CONFIG); // Get the current register
- writeByte(MAX30100_ADDRESS, MAX30100_MODE_CONFIG, reg | 0x80); // mask the SHDN bit
+ char reg[1];
+ i2c_read(MAX30100_ADDRESS, MAX30100_MODE_CONFIG, ®[0], 1); // Get the current register
+ reg[0] = reg[0] | 0x80;
+ i2c_write(MAX30100_ADDRESS, MAX30100_MODE_CONFIG, ®[0], 1); // mask the SHDN bit
}
void reset(void){
- uint8_t reg = readByte(MAX30100_ADDRESS, MAX30100_MODE_CONFIG); // Get the current register
- writeByte(MAX30100_ADDRESS, MAX30100_MODE_CONFIG, reg | 0x40); // mask the RESET bit
+ char reg[1];
+ i2c_read(MAX30100_ADDRESS, MAX30100_MODE_CONFIG, ®[0], 1); // Get the current register
+ reg[0] = reg[0] | 0x40;
+ i2c_write(MAX30100_ADDRESS, MAX30100_MODE_CONFIG, ®[0], 1); // mask the RESET bit
}
void startup(void){
- uint8_t reg = readByte(MAX30100_ADDRESS, MAX30100_MODE_CONFIG); // Get the current register
- writeByte(MAX30100_ADDRESS, MAX30100_MODE_CONFIG, reg & 0x7F); // mask the SHDN bit
+ char reg[1];
+ i2c_read(MAX30100_ADDRESS, MAX30100_MODE_CONFIG, ®[0], 1); // Get the current register
+ reg[0] = reg[0] & 0x7F;
+ i2c_write(MAX30100_ADDRESS, MAX30100_MODE_CONFIG, ®[0], 1); // mask the SHDN bit
}
-int getRevID(void){
- return readByte(MAX30100_ADDRESS, MAX30100_REV_ID);
+uint8_t getRevID(void){
+ char buffer[1];
+ i2c_read(MAX30100_ADDRESS, MAX30100_REV_ID, &buffer[0], 1);
+ return buffer[0];
}
-int getPartID(void){
- return readByte(MAX30100_ADDRESS, MAX30100_PART_ID);
+uint8_t getPartID(void){
+ char buffer[1];
+ i2c_read(MAX30100_ADDRESS, MAX30100_PART_ID, &buffer[0], 1);
+ return buffer[0];
}
void begin(pulseWidth pw, ledCurrent ir, sampleRate sr){
- writeByte(MAX30100_ADDRESS, MAX30100_MODE_CONFIG, 0x02); // Heart rate only
- writeByte(MAX30100_ADDRESS, MAX30100_LED_CONFIG, ir);
- writeByte(MAX30100_ADDRESS, MAX30100_SPO2_CONFIG, (sr<<2)|pw);
+ char buffer[1];
+ buffer[0] = 0x02;
+ i2c_write(MAX30100_ADDRESS, MAX30100_MODE_CONFIG, &buffer[0], 1); // Heart rate only
+ buffer[0] = ir;
+ i2c_write(MAX30100_ADDRESS, MAX30100_LED_CONFIG, &buffer[0], 1);
+ buffer[0] = (sr<<2)|pw;
+ i2c_write(MAX30100_ADDRESS, MAX30100_SPO2_CONFIG, &buffer[0], 1);
}
+
+void printRegisters(){
+ 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]);
+}
+
};
#endif
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/PulseRate.lib Sun Nov 26 21:56:10 2017 +0000 @@ -0,0 +1,1 @@ +https://developer.mbed.org/users/kohlerba/code/PulseRate/#d329886938f1
--- a/main.cpp Wed Aug 23 19:04:51 2017 +0000
+++ b/main.cpp Sun Nov 26 21:56:10 2017 +0000
@@ -3,34 +3,65 @@
DigitalOut led(LED1);
-Serial pc(USBTX, USBRX); // tx, rx
+MAX30100 max;
+uint32_t tsLastPollUs = 0;
+
+// Tweakable parameters
+// Sampling and polling frequency must be set consistently
+#define POLL_PERIOD_US 1E06 / 100
+#define SAMPLING_RATE MAX30100_SAMPRATE_100HZ
-MAX30100 max;
+// The LEDs currents must be set to a level that avoids clipping and maximises the
+// dynamic range
+#define IR_LED_CURRENT MAX30100_LED_CURR_50MA
+#define RED_LED_CURRENT MAX30100_LED_CURR_27_1MA
+
+// The pulse width of the LEDs driving determines the resolution of
+// the ADC (which is a Sigma-Delta).
+// set HIGHRES_MODE to true only when setting PULSE_WIDTH to MAX30100_SPC_PW_1600US_16BITS
+#define PULSE_WIDTH MAX30100_SPC_PW_1600US_16BITS
+#define HIGHRES_MODE true
int main() {
- max.begin(pw1600, i50, sr100);
- max.setLEDs(pw1600, i27, i50);
-
- int partID = max.getPartID();
-
- if(partID == POR_PART_ID){
- pc.printf("MAX30100 is online...\n\r");
- }
-
- else{
- pc.printf("MAX30100 is offline...\n\r");
- pc.printf("Value is %d\n\r",partID);
- pc.printf("Should be %d\n\r",POR_PART_ID);
- while(1){
- wait(1);
- }
- }
-
- int revID = max.getRevID();
-
- pc.printf("RevID is %d\n\r",revID);
-
- //max.setLEDs(pw1600, i50, i14);
-
+/*
+pc.printf("POR State:\n\r");
+max.printRegisters();
+pc.printf("\n\r");
+
+max.begin();
+pc.printf("Begin State:\n\r");
+max.printRegisters();
+wait(1);
+pc.printf("\n\r");
+
+max.setMode(MAX30100_MODE_SPO2_HR);
+pc.printf("\n\rSPO2 and HR Mode:\n\r");
+max.printRegisters();
+wait(1);
+
+pc.printf("\n\rSetting LEDs to 50mA:\n\r");
+max.setLedsCurrent(MAX30100_LED_CURR_50MA, MAX30100_LED_CURR_50MA);
+max.printRegisters();
+wait(10);
+
+pc.printf("\n\rSetting LEDs to 7.6mA\n\r");
+max.setLedsCurrent(MAX30100_LED_CURR_7_6MA, MAX30100_LED_CURR_7_6MA);
+max.printRegisters();
+pc.printf("\n\r");
return 1;
+*/
+max.begin();
+max.setMode(MAX30100_MODE_SPO2_HR);
+max.setLedsCurrent(IR_LED_CURRENT, RED_LED_CURRENT);
+max.setLedsPulseWidth(PULSE_WIDTH);
+max.setSamplingRate(SAMPLING_RATE);
+max.setHighresModeEnabled(HIGHRES_MODE);
+
+while(1){
+if(us_ticker_read() < tsLastPollUs || us_ticker_read() - tsLastPollUs > POLL_PERIOD_US){
+ max.update();
+ tsLastPollUs = us_ticker_read();
+ pc.printf("$%d %d;", max.rawIRValue/10, max.rawRedValue/10);
}
+}
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed-os.lib Sun Nov 26 21:56:10 2017 +0000 @@ -0,0 +1,1 @@ +https://github.com/ARMmbed/mbed-os/#98ba8acb83cfc65f30a8a0771a27c71443ab093a
--- a/mbed.bld Wed Aug 23 19:04:51 2017 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -http://mbed.org/users/mbed_official/code/mbed/builds/fd96258d940d \ No newline at end of file
Bradley Kohler