MAX30100 pulse rate sensor

Dependencies:   PulseRate

Dependents:   PulseRate

Files at this revision

API Documentation at this revision

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

MAX30100.h Show annotated file Show diff for this revision Revisions of this file
PulseRate.lib Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed-os.lib Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show diff for this revision Revisions of this file
--- 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*)&register_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, &reg[0], 1);
+  reg[0] = reg[0] & 0xFC; // Set LED_PW to 00
+  reg[0] = reg[0] | pw;
+  i2c_write(MAX30100_ADDRESS, MAX30100_SPO2_CONFIG, &reg[0], 1);     // Mask LED_PW
+  reg[0] = (red<<4) | ir;
+  i2c_write(MAX30100_ADDRESS, MAX30100_LED_CONFIG, &reg[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, &reg[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, &reg[0], 1); // Mask SPO2_SR
+  i2c_read(MAX30100_ADDRESS, MAX30100_MODE_CONFIG, &reg[0], 1);
+  reg[0] = reg[0] & 0xf8; // Set Mode to 000
+  reg[0] = reg[0] | 0x03;
+  i2c_write(MAX30100_ADDRESS, MAX30100_SPO2_CONFIG, &reg[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, &reg[0], 1);  // Get the current register
+  reg[0] = reg[0] | 0x80;
+  i2c_write(MAX30100_ADDRESS, MAX30100_MODE_CONFIG, &reg[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, &reg[0], 1);  // Get the current register
+  reg[0] = reg[0] | 0x40;
+  i2c_write(MAX30100_ADDRESS, MAX30100_MODE_CONFIG, &reg[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, &reg[0], 1);  // Get the current register
+  reg[0] = reg[0] & 0x7F;
+  i2c_write(MAX30100_ADDRESS, MAX30100_MODE_CONFIG, &reg[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, &reg[0], 1);
+    pc.printf("MAX30100_INT_STATUS: %d\r\n",reg[0]);
+    i2c_read(MAX30100_ADDRESS, MAX30100_INT_ENABLE, &reg[0], 1);
+    pc.printf("MAX30100_INT_ENABLE: %d\r\n",reg[0]);
+    i2c_read(MAX30100_ADDRESS, MAX30100_FIFO_WR_PTR, &reg[0], 1);
+    pc.printf("MAX30100_FIFO_WR_PTR: %d\r\n",reg[0]);
+    i2c_read(MAX30100_ADDRESS, MAX30100_OVRFLOW_CTR, &reg[0], 1);
+    pc.printf("MAX30100_OVRFLOW_CTR: %d\r\n",reg[0]);
+    i2c_read(MAX30100_ADDRESS, MAX30100_FIFO_RD_PTR, &reg[0], 1);
+    pc.printf("MAX30100_FIFO_RD_PTR: %d\r\n",reg[0]);
+    i2c_read(MAX30100_ADDRESS, MAX30100_FIFO_DATA, &reg[0], 1);
+    pc.printf("MAX30100_FIFO_DATA: %d\r\n",reg[0]);
+    i2c_read(MAX30100_ADDRESS, MAX30100_MODE_CONFIG, &reg[0], 1);
+    pc.printf("MAX30100_MODE_CONFIG: %d\r\n",reg[0]);
+    i2c_read(MAX30100_ADDRESS, MAX30100_SPO2_CONFIG, &reg[0], 1);
+    pc.printf("MAX30100_SPO2_CONFIG: %d\r\n",reg[0]);
+    i2c_read(MAX30100_ADDRESS, MAX30100_LED_CONFIG, &reg[0], 1);
+    pc.printf("MAX30100_LED_CONFIG: %d\r\n",reg[0]);
+    i2c_read(MAX30100_ADDRESS, MAX30100_TEMP_INTG, &reg[0], 1);
+    pc.printf("MAX30100_TEMP_INTG: %d\r\n",reg[0]);
+    i2c_read(MAX30100_ADDRESS, MAX30100_TEMP_FRAC, &reg[0], 1);
+    pc.printf("MAX30100_TEMP_FRAC: %d\r\n",reg[0]);
+    i2c_read(MAX30100_ADDRESS, MAX30100_REV_ID, &reg[0], 1);
+    pc.printf("MAX30100_REV_ID: %d\r\n",reg[0]);
+    i2c_read(MAX30100_ADDRESS, MAX30100_PART_ID, &reg[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