MAX30102 pulse oximeter library. Get raw data from IR and Red lights through I2C and the actual temperature in degrees Celcius.

Fork of MAX30100 by StepOne

Committer:
Filea
Date:
Tue Jun 21 09:43:15 2016 +0000
Revision:
1:02f411fefe6f
Parent:
max30100.cpp@0:e1e1947a9882
Modified the code from the library MAX30100 to work with MAX30102 pulse oximeter.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ajeje41 0:e1e1947a9882 1 /*
Filea 1:02f411fefe6f 2 * Library for the Maxim MAX30102 pulse oximetry system, I modified a copy of the MAX30100 library in May 2016
ajeje41 0:e1e1947a9882 3 */
ajeje41 0:e1e1947a9882 4
Filea 1:02f411fefe6f 5 #include "max30102.h"
ajeje41 0:e1e1947a9882 6 #include "functions.h"
Filea 1:02f411fefe6f 7
Filea 1:02f411fefe6f 8 Serial pc(USBTX, USBRX);
ajeje41 0:e1e1947a9882 9
Filea 1:02f411fefe6f 10 void MAX30102::setLEDs(pulseWidth pw, ledCurrent red, ledCurrent ir){
ajeje41 0:e1e1947a9882 11 char data_read[1];
ajeje41 0:e1e1947a9882 12 char data_write[1];
Filea 1:02f411fefe6f 13 i2c_read(MAX30102_ADDRESS, MAX30102_SPO2_CONFIG, data_read, 1);
Filea 1:02f411fefe6f 14 data_read[0] = data_read[0] & 0xFD; // Set LED_PW to 01
ajeje41 0:e1e1947a9882 15 data_write[0] = data_read[0] | pw;
Filea 1:02f411fefe6f 16 i2c_write(MAX30102_ADDRESS, MAX30102_SPO2_CONFIG, data_write, 1); // Mask LED_PW
Filea 1:02f411fefe6f 17 data_write[0] = (red);
Filea 1:02f411fefe6f 18 i2c_write(MAX30102_ADDRESS, MAX30102_LED_CONFIG_1, data_write, 1); // write LED1 configs
Filea 1:02f411fefe6f 19 data_write[0] = (ir);
Filea 1:02f411fefe6f 20 i2c_write(MAX30102_ADDRESS, MAX30102_LED_CONFIG_2, data_write, 1); // write LED2 configs
ajeje41 0:e1e1947a9882 21 }
ajeje41 0:e1e1947a9882 22
Filea 1:02f411fefe6f 23 void MAX30102::setSPO2(sampleRate sr, high_resolution hi_res){
ajeje41 0:e1e1947a9882 24 char data_read[1];
ajeje41 0:e1e1947a9882 25 char data_write[1];
Filea 1:02f411fefe6f 26 i2c_read(MAX30102_ADDRESS, MAX30102_SPO2_CONFIG, data_read, 1);
Filea 1:02f411fefe6f 27 data_read[0] = data_read[0] & 0x85; // Set ADC_rge to 00, SPO2_SR to 001 = sr100 and LEDpw to 01 = 118
ajeje41 0:e1e1947a9882 28 data_write[0] = data_read[0] | (sr<<2) | (hi_res<<6);
Filea 1:02f411fefe6f 29 i2c_write(MAX30102_ADDRESS, MAX30102_SPO2_CONFIG, data_write, 1); // Mask SPO2_SR
Filea 1:02f411fefe6f 30 i2c_read(MAX30102_ADDRESS, MAX30102_CONFIG, data_read, 1);
ajeje41 0:e1e1947a9882 31 data_write[0] = data_read[0] & 0xF8; // Set Mode to 000
Filea 1:02f411fefe6f 32 i2c_write(MAX30102_ADDRESS, MAX30102_CONFIG, data_write, 1); // Mask MODE
ajeje41 0:e1e1947a9882 33 }
ajeje41 0:e1e1947a9882 34
Filea 1:02f411fefe6f 35 void MAX30102::setInterruptSPO2(void){
ajeje41 0:e1e1947a9882 36 char data_read[1];
ajeje41 0:e1e1947a9882 37 char data_write[1];
Filea 1:02f411fefe6f 38 i2c_read(MAX30102_ADDRESS, MAX30102_INT_ENABLE, data_read, 1);
Filea 1:02f411fefe6f 39 data_write[0] = data_read[0] & 0x00; // Set Interrupt enable for SPO2 | 0x10 // New: disable prox! & ~0x10
Filea 1:02f411fefe6f 40 i2c_write(MAX30102_ADDRESS, MAX30102_INT_ENABLE, data_write, 1); // Mask ENB_SPO2_RDY
Filea 1:02f411fefe6f 41 }
ajeje41 0:e1e1947a9882 42
Filea 1:02f411fefe6f 43 int MAX30102::getNumSamp(void){
Filea 1:02f411fefe6f 44 char data_read[1] = {0};
Filea 1:02f411fefe6f 45 // i2c_write(MAX30102_ADDRESS, MAX30102_FIFO_W_POINTER, data_read, 1);
Filea 1:02f411fefe6f 46 // i2c_write(MAX30102_ADDRESS, MAX30102_FIFO_R_POINTER, data_read, 1);
Filea 1:02f411fefe6f 47 // wait(0.148);
Filea 1:02f411fefe6f 48 i2c_read(MAX30102_ADDRESS, MAX30102_FIFO_W_POINTER, data_read, 1);
ajeje41 0:e1e1947a9882 49 char wrPtr = data_read[0];
Filea 1:02f411fefe6f 50 i2c_read(MAX30102_ADDRESS, MAX30102_FIFO_R_POINTER, data_read, 1);
ajeje41 0:e1e1947a9882 51 char rdPtr = data_read[0];
Filea 1:02f411fefe6f 52 return ((int)wrPtr - (int)rdPtr); // New counting
Filea 1:02f411fefe6f 53 // return (abs( 16 + (int)wrPtr - (int)rdPtr ) % 16);
ajeje41 0:e1e1947a9882 54 }
ajeje41 0:e1e1947a9882 55
Filea 1:02f411fefe6f 56 void MAX30102::setTemp(void){
ajeje41 0:e1e1947a9882 57 char data_read[1];
ajeje41 0:e1e1947a9882 58 char data_write[1];
Filea 1:02f411fefe6f 59 i2c_read(MAX30102_ADDRESS, MAX30102_TEMP_CONFIG, data_read, 1);
Filea 1:02f411fefe6f 60 data_write[0] = data_read[0] | 0x01; // Enable temperature
Filea 1:02f411fefe6f 61 i2c_write(MAX30102_ADDRESS, MAX30102_TEMP_CONFIG, data_write, 1); // Mask MODE
Filea 1:02f411fefe6f 62 i2c_read(MAX30102_ADDRESS, MAX30102_TEMP_CONFIG, data_read, 1);
ajeje41 0:e1e1947a9882 63 }
ajeje41 0:e1e1947a9882 64
Filea 1:02f411fefe6f 65 void MAX30102::setSPO2mode(void){
ajeje41 0:e1e1947a9882 66 char data_read[1];
ajeje41 0:e1e1947a9882 67 char data_write[1];
Filea 1:02f411fefe6f 68 i2c_read(MAX30102_ADDRESS, MAX30102_CONFIG, data_read, 1);
ajeje41 0:e1e1947a9882 69 data_write[0] = data_read[0] | 0x03; // Set SPO2 Mode
Filea 1:02f411fefe6f 70 i2c_write(MAX30102_ADDRESS, MAX30102_CONFIG, data_write, 1);
ajeje41 0:e1e1947a9882 71 }
ajeje41 0:e1e1947a9882 72
Filea 1:02f411fefe6f 73 int MAX30102::readTemp(void){
ajeje41 0:e1e1947a9882 74 char data_read[1];
ajeje41 0:e1e1947a9882 75 char temp_int, temp_fract;
ajeje41 0:e1e1947a9882 76 int temp_measured;
Filea 1:02f411fefe6f 77 i2c_read(MAX30102_ADDRESS, MAX30102_TEMP_INTEGER, data_read, 1);
ajeje41 0:e1e1947a9882 78 temp_int = data_read[0];
Filea 1:02f411fefe6f 79 i2c_read(MAX30102_ADDRESS, MAX30102_TEMP_FRACTION, data_read, 1);
ajeje41 0:e1e1947a9882 80 temp_fract = data_read[0] & 0x0F;
ajeje41 0:e1e1947a9882 81 temp_measured = ((int)temp_int)+(((int)temp_fract) >> 4);
ajeje41 0:e1e1947a9882 82 return temp_measured;
ajeje41 0:e1e1947a9882 83 }
ajeje41 0:e1e1947a9882 84
Filea 1:02f411fefe6f 85 void MAX30102::readSensor(void){
Filea 1:02f411fefe6f 86 char data_read[6] = {0};
Filea 1:02f411fefe6f 87 HR = 0;
Filea 1:02f411fefe6f 88 SPO2 = 0;
Filea 1:02f411fefe6f 89 i2c_read(MAX30102_ADDRESS, MAX30102_FIFO_DATA_REG, data_read, 6); // Read six times from the FIFO
Filea 1:02f411fefe6f 90 HR = (data_read[0]<<16) | (data_read[1]<<8) | data_read[2]; // Combine values to get the actual number
Filea 1:02f411fefe6f 91 HR = HR>>2;
Filea 1:02f411fefe6f 92 SPO2 = (data_read[3]<<16) | (data_read[4]<<8) | data_read[5]; // Combine values to get the actual number
Filea 1:02f411fefe6f 93 SPO2 = SPO2>>2;
ajeje41 0:e1e1947a9882 94 }
ajeje41 0:e1e1947a9882 95
Filea 1:02f411fefe6f 96 void MAX30102::shutdown(void){
ajeje41 0:e1e1947a9882 97 char data_read[1];
ajeje41 0:e1e1947a9882 98 char data_write[1];
Filea 1:02f411fefe6f 99 i2c_read(MAX30102_ADDRESS, MAX30102_CONFIG, data_read, 1); // Get the current register
ajeje41 0:e1e1947a9882 100 data_write[0] = data_read[0] | 0x80;
Filea 1:02f411fefe6f 101 i2c_write(MAX30102_ADDRESS, MAX30102_CONFIG, data_write, 1); // mask the SHDN bit
ajeje41 0:e1e1947a9882 102 }
ajeje41 0:e1e1947a9882 103
Filea 1:02f411fefe6f 104 void MAX30102::reset(void){
ajeje41 0:e1e1947a9882 105 char data_read[1];
ajeje41 0:e1e1947a9882 106 char data_write[1];
Filea 1:02f411fefe6f 107 i2c_read(MAX30102_ADDRESS, MAX30102_CONFIG, data_read, 1); // Get the current register
ajeje41 0:e1e1947a9882 108 data_write[0] = data_read[0] | 0x40;
Filea 1:02f411fefe6f 109 i2c_write(MAX30102_ADDRESS, MAX30102_CONFIG, data_write, 1); // mask the RESET bit
ajeje41 0:e1e1947a9882 110 }
ajeje41 0:e1e1947a9882 111
Filea 1:02f411fefe6f 112 void MAX30102::startup(void){
ajeje41 0:e1e1947a9882 113 char data_read[1];
ajeje41 0:e1e1947a9882 114 char data_write[1];
Filea 1:02f411fefe6f 115 i2c_read(MAX30102_ADDRESS, MAX30102_CONFIG, data_read, 1); // Get the current register
ajeje41 0:e1e1947a9882 116 data_write[0] = data_read[0] & 0x7F;
Filea 1:02f411fefe6f 117 i2c_write(MAX30102_ADDRESS, MAX30102_CONFIG, data_write, 1); // mask the SHDN bit
ajeje41 0:e1e1947a9882 118 }
ajeje41 0:e1e1947a9882 119
Filea 1:02f411fefe6f 120 char MAX30102::getRevID(void){
ajeje41 0:e1e1947a9882 121 char data_read[1];
Filea 1:02f411fefe6f 122 i2c_read(MAX30102_ADDRESS, MAX30102_REVISION_ID, data_read, 1);
ajeje41 0:e1e1947a9882 123 return data_read[0];
ajeje41 0:e1e1947a9882 124 }
ajeje41 0:e1e1947a9882 125
Filea 1:02f411fefe6f 126 char MAX30102::getPartID(void){
ajeje41 0:e1e1947a9882 127 char data_read[1];
Filea 1:02f411fefe6f 128 i2c_read(MAX30102_ADDRESS, MAX30102_PART_ID, data_read, 1);
ajeje41 0:e1e1947a9882 129 return data_read[0];
ajeje41 0:e1e1947a9882 130 }
ajeje41 0:e1e1947a9882 131
Filea 1:02f411fefe6f 132 void MAX30102::begin(pulseWidth pw, ledCurrent ir, sampleRate sr){
ajeje41 0:e1e1947a9882 133 char data_write[1];
Filea 1:02f411fefe6f 134 data_write[0] = 0x02;
Filea 1:02f411fefe6f 135 i2c_write(MAX30102_ADDRESS, MAX30102_CONFIG, data_write, 1); // Heart rate only
ajeje41 0:e1e1947a9882 136 data_write[0] = ir;
Filea 1:02f411fefe6f 137 i2c_write(MAX30102_ADDRESS, MAX30102_LED_CONFIG_1, data_write, 1);
ajeje41 0:e1e1947a9882 138 data_write[0] = ((sr<<2)|pw);
Filea 1:02f411fefe6f 139 i2c_write(MAX30102_ADDRESS, MAX30102_SPO2_CONFIG, data_write, 1);
ajeje41 0:e1e1947a9882 140 }
ajeje41 0:e1e1947a9882 141
Filea 1:02f411fefe6f 142 void MAX30102::init(pulseWidth pw, sampleRate sr, high_resolution hi_res, ledCurrent red, ledCurrent ir){
Filea 1:02f411fefe6f 143 char data_write[1];
ajeje41 0:e1e1947a9882 144
ajeje41 0:e1e1947a9882 145 setLEDs(pw, red, ir);
ajeje41 0:e1e1947a9882 146 setSPO2(sr, hi_res);
ajeje41 0:e1e1947a9882 147
Filea 1:02f411fefe6f 148 data_write[0] = 0x10;
Filea 1:02f411fefe6f 149 i2c_write(MAX30102_ADDRESS, MAX30102_FIFO_CONFIG, data_write, 1);
Filea 1:02f411fefe6f 150
ajeje41 0:e1e1947a9882 151 }
ajeje41 0:e1e1947a9882 152
Filea 1:02f411fefe6f 153 void MAX30102::printRegisters(void){
ajeje41 0:e1e1947a9882 154 char data_read[1];
Filea 1:02f411fefe6f 155 i2c_read(MAX30102_ADDRESS, MAX30102_INT_STATUS, data_read, 1);
ajeje41 0:e1e1947a9882 156 pc.printf("INT_STATUS: %#4X\r\n", data_read[0]);
Filea 1:02f411fefe6f 157 i2c_read(MAX30102_ADDRESS, MAX30102_INT_ENABLE, data_read, 1);
ajeje41 0:e1e1947a9882 158 pc.printf("INT_ENABLE: %#4X\r\n", data_read[0]);
Filea 1:02f411fefe6f 159 i2c_read(MAX30102_ADDRESS, MAX30102_FIFO_W_POINTER, data_read, 1);
ajeje41 0:e1e1947a9882 160 pc.printf("FIFO_W_POINTER: %#4X\r\n", data_read[0]);
Filea 1:02f411fefe6f 161 i2c_read(MAX30102_ADDRESS, MAX30102_OVR_COUNTER, data_read, 1);
ajeje41 0:e1e1947a9882 162 pc.printf("OVR_COUNTER: %#4X\r\n", data_read[0]);
Filea 1:02f411fefe6f 163 i2c_read(MAX30102_ADDRESS, MAX30102_FIFO_R_POINTER, data_read, 1);
ajeje41 0:e1e1947a9882 164 pc.printf("FIFO_R_POINTER: %#4X\r\n", data_read[0]);
Filea 1:02f411fefe6f 165 i2c_read(MAX30102_ADDRESS, MAX30102_FIFO_DATA_REG, data_read, 1);
ajeje41 0:e1e1947a9882 166 pc.printf("FIFO_DATA_REG: %#4X\r\n", data_read[0]);
Filea 1:02f411fefe6f 167 i2c_read(MAX30102_ADDRESS, MAX30102_CONFIG, data_read, 1);
ajeje41 0:e1e1947a9882 168 pc.printf("CONFIG: %#4X\r\n", data_read[0]);
Filea 1:02f411fefe6f 169 i2c_read(MAX30102_ADDRESS, MAX30102_SPO2_CONFIG, data_read, 1);
ajeje41 0:e1e1947a9882 170 pc.printf("SPO2_CONFIG: %#4X\r\n", data_read[0]);
Filea 1:02f411fefe6f 171 i2c_read(MAX30102_ADDRESS, MAX30102_LED_CONFIG_2, data_read, 1);
ajeje41 0:e1e1947a9882 172 pc.printf("LED_CONFIG: %#4X\r\n", data_read[0]);
Filea 1:02f411fefe6f 173 i2c_read(MAX30102_ADDRESS, MAX30102_TEMP_INTEGER, data_read, 1);
ajeje41 0:e1e1947a9882 174 pc.printf("TEMP_INTEGER: %#4X\r\n", data_read[0]);
Filea 1:02f411fefe6f 175 i2c_read(MAX30102_ADDRESS, MAX30102_TEMP_FRACTION, data_read, 1);
ajeje41 0:e1e1947a9882 176 pc.printf("TEMP_FRACTION: %#4X\r\n", data_read[0]);
Filea 1:02f411fefe6f 177 i2c_read(MAX30102_ADDRESS, MAX30102_TEMP_CONFIG, data_read, 1);
Filea 1:02f411fefe6f 178 pc.printf("TEMP_CONFIG: %#4X\r\n", data_read[0]);
Filea 1:02f411fefe6f 179 i2c_read(MAX30102_ADDRESS, MAX30102_REVISION_ID, data_read, 1);
ajeje41 0:e1e1947a9882 180 pc.printf("REVISION_ID: %#4X\r\n", data_read[0]);
Filea 1:02f411fefe6f 181 i2c_read(MAX30102_ADDRESS, MAX30102_PART_ID, data_read, 1);
ajeje41 0:e1e1947a9882 182 pc.printf("PART_ID: %#4X\r\n", data_read[0]);
ajeje41 0:e1e1947a9882 183 }