From 4530cb6ce21da63b0b85a69c8e7e6df9fa271581 Mon Sep 17 00:00:00 2001 From: Shivam Gupta Date: Sat, 26 Sep 2020 23:04:23 +0530 Subject: [PATCH 01/18] forked From d45888ca82f67e732b08ed26f99cf268b1f6b2f6 Mon Sep 17 00:00:00 2001 From: Shivam Gupta Date: Sat, 26 Sep 2020 23:06:30 +0530 Subject: [PATCH 02/18] Initial commit for MAX30102 --- src/MAX30100.cpp | 193 ---------------------------------------- src/MAX30102.cpp | 224 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 224 insertions(+), 193 deletions(-) delete mode 100644 src/MAX30100.cpp create mode 100644 src/MAX30102.cpp diff --git a/src/MAX30100.cpp b/src/MAX30100.cpp deleted file mode 100644 index e0235c1..0000000 --- a/src/MAX30100.cpp +++ /dev/null @@ -1,193 +0,0 @@ -/* -Arduino-MAX30100 oximetry / heart rate integrated sensor library -Copyright (C) 2016 OXullo Intersecans - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ - -#include - -#include "MAX30100.h" - -MAX30100::MAX30100() -{ -} - -bool MAX30100::begin() -{ - Wire.begin(); - Wire.setClock(I2C_BUS_SPEED); - - if (getPartId() != EXPECTED_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 MAX30100::setMode(Mode mode) -{ - writeRegister(MAX30100_REG_MODE_CONFIGURATION, mode); -} - -void MAX30100::setLedsPulseWidth(LEDPulseWidth ledPulseWidth) -{ - uint8_t previous = readRegister(MAX30100_REG_SPO2_CONFIGURATION); - writeRegister(MAX30100_REG_SPO2_CONFIGURATION, (previous & 0xfc) | ledPulseWidth); -} - -void MAX30100::setSamplingRate(SamplingRate samplingRate) -{ - uint8_t previous = readRegister(MAX30100_REG_SPO2_CONFIGURATION); - writeRegister(MAX30100_REG_SPO2_CONFIGURATION, (previous & 0xe3) | (samplingRate << 2)); -} - -void MAX30100::setLedsCurrent(LEDCurrent irLedCurrent, LEDCurrent redLedCurrent) -{ - writeRegister(MAX30100_REG_LED_CONFIGURATION, redLedCurrent << 4 | irLedCurrent); -} - -void MAX30100::setHighresModeEnabled(bool enabled) -{ - uint8_t previous = readRegister(MAX30100_REG_SPO2_CONFIGURATION); - if (enabled) { - writeRegister(MAX30100_REG_SPO2_CONFIGURATION, previous | MAX30100_SPC_SPO2_HI_RES_EN); - } else { - writeRegister(MAX30100_REG_SPO2_CONFIGURATION, previous & ~MAX30100_SPC_SPO2_HI_RES_EN); - } -} - -void MAX30100::update() -{ - readFifoData(); -} - -bool MAX30100::getRawValues(uint16_t *ir, uint16_t *red) -{ - if (!readoutsBuffer.isEmpty()) { - SensorReadout readout = readoutsBuffer.pop(); - - *ir = readout.ir; - *red = readout.red; - - return true; - } else { - return false; - } -} - -void MAX30100::resetFifo() -{ - writeRegister(MAX30100_REG_FIFO_WRITE_POINTER, 0); - writeRegister(MAX30100_REG_FIFO_READ_POINTER, 0); - writeRegister(MAX30100_REG_FIFO_OVERFLOW_COUNTER, 0); -} - -uint8_t MAX30100::readRegister(uint8_t address) -{ - Wire.beginTransmission(MAX30100_I2C_ADDRESS); - Wire.write(address); - Wire.endTransmission(false); - Wire.requestFrom(MAX30100_I2C_ADDRESS, 1); - - return Wire.read(); -} - -void MAX30100::writeRegister(uint8_t address, uint8_t data) -{ - Wire.beginTransmission(MAX30100_I2C_ADDRESS); - Wire.write(address); - Wire.write(data); - Wire.endTransmission(); -} - -void MAX30100::burstRead(uint8_t baseAddress, uint8_t *buffer, uint8_t length) -{ - Wire.beginTransmission(MAX30100_I2C_ADDRESS); - Wire.write(baseAddress); - Wire.endTransmission(false); - Wire.requestFrom((uint8_t)MAX30100_I2C_ADDRESS, length); - - uint8_t idx = 0; - while (Wire.available()) { - buffer[idx++] = Wire.read(); - } -} - -void MAX30100::readFifoData() -{ - uint8_t buffer[MAX30100_FIFO_DEPTH*4]; - uint8_t toRead; - - toRead = (readRegister(MAX30100_REG_FIFO_WRITE_POINTER) - readRegister(MAX30100_REG_FIFO_READ_POINTER)) & (MAX30100_FIFO_DEPTH-1); - - if (toRead) { - burstRead(MAX30100_REG_FIFO_DATA, buffer, 4 * toRead); - - for (uint8_t i=0 ; i < toRead ; ++i) { - // Warning: the values are always left-aligned - readoutsBuffer.push({ - .ir=(uint16_t)((buffer[i*4] << 8) | buffer[i*4 + 1]), - .red=(uint16_t)((buffer[i*4 + 2] << 8) | buffer[i*4 + 3])}); - } - } -} - -void MAX30100::startTemperatureSampling() -{ - uint8_t modeConfig = readRegister(MAX30100_REG_MODE_CONFIGURATION); - modeConfig |= MAX30100_MC_TEMP_EN; - - writeRegister(MAX30100_REG_MODE_CONFIGURATION, modeConfig); -} - -bool MAX30100::isTemperatureReady() -{ - return !(readRegister(MAX30100_REG_MODE_CONFIGURATION) & MAX30100_MC_TEMP_EN); -} - -float MAX30100::retrieveTemperature() -{ - int8_t tempInteger = readRegister(MAX30100_REG_TEMPERATURE_DATA_INT); - float tempFrac = readRegister(MAX30100_REG_TEMPERATURE_DATA_FRAC); - - return tempFrac * 0.0625 + tempInteger; -} - -void MAX30100::shutdown() -{ - uint8_t modeConfig = readRegister(MAX30100_REG_MODE_CONFIGURATION); - modeConfig |= MAX30100_MC_SHDN; - - writeRegister(MAX30100_REG_MODE_CONFIGURATION, modeConfig); -} - -void MAX30100::resume() -{ - uint8_t modeConfig = readRegister(MAX30100_REG_MODE_CONFIGURATION); - modeConfig &= ~MAX30100_MC_SHDN; - - writeRegister(MAX30100_REG_MODE_CONFIGURATION, modeConfig); -} - -uint8_t MAX30100::getPartId() -{ - return readRegister(0xff); -} diff --git a/src/MAX30102.cpp b/src/MAX30102.cpp new file mode 100644 index 0000000..60a237a --- /dev/null +++ b/src/MAX30102.cpp @@ -0,0 +1,224 @@ +/* +Arduino-MAX30102 oximetry / heart rate integrated sensor library by Shivam Gupta (gupta.shivam1996@gmail.com) + +Based on MAX30100 library, Copyright (C) 2016 OXullo Intersecans +All alogrithms and methods used are from the above author, +I have only modified this enough to make it work with the new MAX30102 sensor. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#include + +#include "MAX30102.h" + +MAX30102::MAX30102() +{ +} + +bool MAX30102::begin() +{ + Wire.begin(); + Wire.setClock(I2C_BUS_SPEED); + + if (getPartId() != EXPECTED_PART_ID) { + return false; + } + + setMode(DEFAULT_MODE); + setLedsPulseWidth(DEFAULT_PULSE_WIDTH); + setSamplingRate(DEFAULT_SAMPLING_RATE); + setRangeADC(DEFAULT_ADC_RANGE); + setRedLedCurrent(DEFAULT_RED_LED_CURRENT); + setIRLedCurrent(DEFAULT_IR_LED_CURRENT); + + return true; +} + +void MAX30102::setMode(Mode mode) +{ + uint8_t previous = readRegister(MAX30102_REG_MODE_CONFIGURATION); + writeRegister(MAX30102_REG_MODE_CONFIGURATION, (previous & 0xf8) | mode); +} + +void MAX30102::setLedsPulseWidth(LEDPulseWidth ledPulseWidth) +{ + uint8_t previous = readRegister(MAX30102_REG_SPO2_CONFIGURATION); + writeRegister(MAX30102_REG_SPO2_CONFIGURATION, (previous & 0xfc) | ledPulseWidth); +} + +void MAX30102::setSamplingRate(SamplingRate samplingRate) +{ + uint8_t previous = readRegister(MAX30102_REG_SPO2_CONFIGURATION); + writeRegister(MAX30102_REG_SPO2_CONFIGURATION, (previous & 0xe3) | (samplingRate << 2)); +} + +void MAX30102::setRedLedCurrent(uint8_t redLedCurrent) +{ + writeRegister(MAX30102_REG_LED_RED_PA, redLedCurrent); +} + +void MAX30102::setIRLedCurrent(uint8_t IRLedCurrent) +{ + writeRegister(MAX30102_REG_LED_IR_PA, IRLedCurrent); +} + +void MAX30102::setSlot1(SlotSetting slotsetting) +{ + uint8_t previous = readRegister(MAX30102_REG_MULTI_LED_CTRL_1AND2); + writeRegister(MAX30102_REG_MULTI_LED_CTRL_1AND2, (previous & 0xf8) | slotsetting); +} + +void MAX30102::setSlot2(SlotSetting slotsetting) +{ + uint8_t previous = readRegister(MAX30102_REG_MULTI_LED_CTRL_1AND2); + writeRegister(MAX30102_REG_MULTI_LED_CTRL_1AND2, (previous & 0x8f) | slotsetting); +} + +void MAX30102::setSlot3(SlotSetting slotsetting) +{ + uint8_t previous = readRegister(MAX30102_REG_MULTI_LED_CTRL_3AND4); + writeRegister(MAX30102_REG_MULTI_LED_CTRL_3AND4, (previous & 0xf8) | slotsetting); +} + +void MAX30102::setSlot4(SlotSetting slotsetting) +{ + uint8_t previous = readRegister(MAX30102_REG_MULTI_LED_CTRL_3AND4); + writeRegister(MAX30102_REG_MULTI_LED_CTRL_3AND4, (previous & 0x8f) | slotsetting); +} + +void MAX30102::setRangeADC(ADCRange adcRange) +{ + uint8_t previous = readRegister(MAX30102_REG_SPO2_CONFIGURATION); + writeRegister(MAX30102_REG_SPO2_CONFIGURATION, (previous & 0x9f) | (adcRange << 5)); +} + +void MAX30102::update() +{ + readFifoData(); +} + +bool MAX30102::getRawValues(uint16_t *ir, uint16_t *red) +{ + if (!readoutsBuffer.isEmpty()) { + SensorReadout readout = readoutsBuffer.pop(); + + *ir = readout.ir; + *red = readout.red; + + return true; + } else { + return false; + } +} + +void MAX30102::resetFifo() +{ + writeRegister(MAX30102_REG_FIFO_WRITE_POINTER, 0); + writeRegister(MAX30102_REG_FIFO_READ_POINTER, 0); + writeRegister(MAX30102_REG_FIFO_OVERFLOW_COUNTER, 0); +} + +uint8_t MAX30102::readRegister(uint8_t address) +{ + Wire.beginTransmission(MAX30102_I2C_ADDRESS); + Wire.write(address); + Wire.endTransmission(false); + Wire.requestFrom(MAX30102_I2C_ADDRESS, 1); + + return Wire.read(); +} + +void MAX30102::writeRegister(uint8_t address, uint8_t data) +{ + Wire.beginTransmission(MAX30102_I2C_ADDRESS); + Wire.write(address); + Wire.write(data); + Wire.endTransmission(); +} + +void MAX30102::burstRead(uint8_t baseAddress, uint8_t *buffer, uint8_t length) +{ + Wire.beginTransmission(MAX30102_I2C_ADDRESS); + Wire.write(baseAddress); + Wire.endTransmission(false); + Wire.requestFrom((uint8_t)MAX30102_I2C_ADDRESS, length); + + uint8_t idx = 0; + while (Wire.available()) { + buffer[idx++] = Wire.read(); + } +} + +void MAX30102::readFifoData() +{ + uint8_t buffer[MAX30102_FIFO_DEPTH*4]; + uint8_t toRead; + + toRead = (readRegister(MAX30102_REG_FIFO_WRITE_POINTER) - readRegister(MAX30102_REG_FIFO_READ_POINTER)) & (MAX30102_FIFO_DEPTH-1); + + if (toRead) { + burstRead(MAX30102_REG_FIFO_DATA, buffer, 4 * toRead); + + for (uint8_t i=0 ; i < toRead ; ++i) { + // Warning: the values are always left-aligned + readoutsBuffer.push({ + .ir=(uint16_t)((buffer[i*4] << 8) | buffer[i*4 + 1]), + .red=(uint16_t)((buffer[i*4 + 2] << 8) | buffer[i*4 + 3])}); + } + } +} + + +void MAX30102::startTemperatureSampling() +{ + uint8_t modeConfig = readRegister(MAX30102_REG_TEMP_CONFIG); + modeConfig |= MAX30102_TC_TEMP_EN; + + writeRegister(MAX30102_REG_TEMP_CONFIG, modeConfig); +} + +bool MAX30102::isTemperatureReady() +{ + return !(readRegister(MAX30102_REG_TEMP_CONFIG) & MAX30102_TC_TEMP_EN); +} + +float MAX30102::retrieveTemperature() +{ + int8_t tempInteger = readRegister(MAX30102_REG_TEMPERATURE_DATA_INT); + float tempFrac = readRegister(MAX30102_REG_TEMPERATURE_DATA_FRAC); + + return tempFrac * 0.0625 + tempInteger; +} + +void MAX30102::shutdown() +{ + uint8_t modeConfig = readRegister(MAX30102_REG_MODE_CONFIGURATION); + modeConfig |= MAX30102_MC_SHDN; + + writeRegister(MAX30102_REG_MODE_CONFIGURATION, modeConfig); +} + +void MAX30102::resume() +{ + uint8_t modeConfig = readRegister(MAX30102_REG_MODE_CONFIGURATION); + modeConfig &= ~MAX30102_MC_SHDN; + + writeRegister(MAX30102_REG_MODE_CONFIGURATION, modeConfig); +} + +uint8_t MAX30102::getPartId() +{ + return readRegister(0xff); +} From e46446325bf18547f03dd03d2e5f5d32a94d4671 Mon Sep 17 00:00:00 2001 From: Shivam Gupta Date: Sat, 26 Sep 2020 23:07:30 +0530 Subject: [PATCH 03/18] Initial commit for MAX30102 --- src/{MAX30100.h => MAX30102.h} | 42 ++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 15 deletions(-) rename src/{MAX30100.h => MAX30102.h} (57%) diff --git a/src/MAX30100.h b/src/MAX30102.h similarity index 57% rename from src/MAX30100.h rename to src/MAX30102.h index f7fa179..ab4f2b0 100644 --- a/src/MAX30100.h +++ b/src/MAX30102.h @@ -1,6 +1,9 @@ /* -Arduino-MAX30100 oximetry / heart rate integrated sensor library -Copyright (C) 2016 OXullo Intersecans +Arduino-MAX30102 oximetry / heart rate integrated sensor library by Shivam Gupta (gupta.shivam1996@gmail.com) + +Based on MAX30100 library, Copyright (C) 2016 OXullo Intersecans +All alogrithms and methods used are from the above author, +I have only modified this enough to make it work with the new MAX30102 sensor. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -16,22 +19,25 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#ifndef MAX30100_H -#define MAX30100_H +#ifndef MAX30102_H +#define MAX30102_H #include #define CIRCULAR_BUFFER_XS #include "CircularBuffer.h" -#include "MAX30100_Registers.h" +#include "MAX30102_Registers.h" -#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 -#define RINGBUFFER_SIZE 16 +#define DEFAULT_MODE MAX30102_MODE_HRONLY +#define DEFAULT_SAMPLING_RATE MAX30102_SAMPRATE_100HZ +#define DEFAULT_PULSE_WIDTH MAX30102_SPC_PW_118US_16BITS +#define DEFAULT_RED_LED_CURRENT 0xff +#define DEFAULT_IR_LED_CURRENT 0xff +#define DEFAULT_ADC_RANGE MAX30102_ADCRange_8192 +//Max30102 part ID is 0x15 +#define EXPECTED_PART_ID 0x15 +//Max30102 fifo size is 32 +#define RINGBUFFER_SIZE 32 #define I2C_BUS_SPEED 400000UL @@ -40,14 +46,20 @@ typedef struct { uint16_t red; } SensorReadout; -class MAX30100 { +class MAX30102 { public: - MAX30100(); + MAX30102(); bool begin(); void setMode(Mode mode); void setLedsPulseWidth(LEDPulseWidth ledPulseWidth); void setSamplingRate(SamplingRate samplingRate); - void setLedsCurrent(LEDCurrent irLedCurrent, LEDCurrent redLedCurrent); + void setRangeADC(ADCRange adcRange); + void setRedLedCurrent(uint8_t redLedCurrent); + void setIRLedCurrent(uint8_t IRLedCurrent); + void setSlot1(SlotSetting slotsetting); + void setSlot2(SlotSetting slotsetting); + void setSlot3(SlotSetting slotsetting); + void setSlot4(SlotSetting slotsetting); void setHighresModeEnabled(bool enabled); void update(); bool getRawValues(uint16_t *ir, uint16_t *red); From a464fed8c4ff3f2e9f0fea2b6a93ce14d1d257cc Mon Sep 17 00:00:00 2001 From: Shivam Gupta Date: Sat, 26 Sep 2020 23:09:24 +0530 Subject: [PATCH 04/18] Initial commit for MAX30102 --- ...X30100_BeatDetector.cpp => MAX30102_BeatDetector.cpp} | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) rename src/{MAX30100_BeatDetector.cpp => MAX30102_BeatDetector.cpp} (90%) diff --git a/src/MAX30100_BeatDetector.cpp b/src/MAX30102_BeatDetector.cpp similarity index 90% rename from src/MAX30100_BeatDetector.cpp rename to src/MAX30102_BeatDetector.cpp index 0f3c797..12beb0b 100644 --- a/src/MAX30100_BeatDetector.cpp +++ b/src/MAX30102_BeatDetector.cpp @@ -1,6 +1,9 @@ /* -Arduino-MAX30100 oximetry / heart rate integrated sensor library -Copyright (C) 2016 OXullo Intersecans +Arduino-MAX30102 oximetry / heart rate integrated sensor library by Shivam Gupta (gupta.shivam1996@gmail.com) + +Based on MAX30100 library, Copyright (C) 2016 OXullo Intersecans +All alogrithms and methods used are from the above author, +I have only modified this enough to make it work with the new MAX30102 sensor. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,7 +21,7 @@ along with this program. If not, see . #include -#include "MAX30100_BeatDetector.h" +#include "MAX30102_BeatDetector.h" #ifndef min #define min(a,b) \ From 42d153cb67d937bb60eb89fffd9636cf17af60b3 Mon Sep 17 00:00:00 2001 From: Shivam Gupta Date: Sat, 26 Sep 2020 23:10:11 +0530 Subject: [PATCH 05/18] Initial commit for MAX30102 --- ...AX30100_BeatDetector.h => MAX30102_BeatDetector.h} | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) rename src/{MAX30100_BeatDetector.h => MAX30102_BeatDetector.h} (84%) diff --git a/src/MAX30100_BeatDetector.h b/src/MAX30102_BeatDetector.h similarity index 84% rename from src/MAX30100_BeatDetector.h rename to src/MAX30102_BeatDetector.h index 2d11247..b8a2fb5 100644 --- a/src/MAX30100_BeatDetector.h +++ b/src/MAX30102_BeatDetector.h @@ -1,6 +1,9 @@ /* -Arduino-MAX30100 oximetry / heart rate integrated sensor library -Copyright (C) 2016 OXullo Intersecans +Arduino-MAX30102 oximetry / heart rate integrated sensor library by Shivam Gupta (gupta.shivam1996@gmail.com) + +Based on MAX30100 library, Copyright (C) 2016 OXullo Intersecans +All alogrithms and methods used are from the above author, +I have only modified this enough to make it work with the new MAX30102 sensor. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -16,8 +19,8 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#ifndef MAX30100_BEATDETECTOR_H -#define MAX30100_BEATDETECTOR_H +#ifndef MAX30102_BEATDETECTOR_H +#define MAX30102_BEATDETECTOR_H #include From 289dacc32efe805143a4b59d13ff15212254779d Mon Sep 17 00:00:00 2001 From: Shivam Gupta Date: Sat, 26 Sep 2020 23:11:19 +0530 Subject: [PATCH 06/18] Initial commit for MAX30102 --- src/{MAX30100_Filters.h => MAX30102_Filters.h} | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) rename src/{MAX30100_Filters.h => MAX30102_Filters.h} (78%) diff --git a/src/MAX30100_Filters.h b/src/MAX30102_Filters.h similarity index 78% rename from src/MAX30100_Filters.h rename to src/MAX30102_Filters.h index dd48a56..193ad85 100644 --- a/src/MAX30100_Filters.h +++ b/src/MAX30102_Filters.h @@ -1,6 +1,9 @@ /* -Arduino-MAX30100 oximetry / heart rate integrated sensor library -Copyright (C) 2016 OXullo Intersecans +Arduino-MAX30102 oximetry / heart rate integrated sensor library by Shivam Gupta (gupta.shivam1996@gmail.com) + +Based on MAX30100 library, Copyright (C) 2016 OXullo Intersecans +All alogrithms and methods used are from the above author, +I have only modified this enough to make it work with the new MAX30102 sensor. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -16,8 +19,8 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#ifndef MAX30100_FILTERS_H -#define MAX30100_FILTERS_H +#ifndef MAX30102_FILTERS_H +#define MAX30102_FILTERS_H // http://www.schwietering.com/jayduino/filtuino/ // Low pass butterworth filter order=1 alpha1=0.1 From fcb97024203db20e90c8e251884eafd05e2c89ef Mon Sep 17 00:00:00 2001 From: Shivam Gupta Date: Sat, 26 Sep 2020 23:13:12 +0530 Subject: [PATCH 07/18] Initial commit for MAX30102 --- ...ximeter.cpp => MAX30102_PulseOximeter.cpp} | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) rename src/{MAX30100_PulseOximeter.cpp => MAX30102_PulseOximeter.cpp} (85%) diff --git a/src/MAX30100_PulseOximeter.cpp b/src/MAX30102_PulseOximeter.cpp similarity index 85% rename from src/MAX30100_PulseOximeter.cpp rename to src/MAX30102_PulseOximeter.cpp index a7bfe61..4f487ef 100644 --- a/src/MAX30100_PulseOximeter.cpp +++ b/src/MAX30102_PulseOximeter.cpp @@ -1,6 +1,9 @@ /* -Arduino-MAX30100 oximetry / heart rate integrated sensor library -Copyright (C) 2016 OXullo Intersecans +Arduino-MAX30102 oximetry / heart rate integrated sensor library by Shivam Gupta (gupta.shivam1996@gmail.com) + +Based on MAX30100 library, Copyright (C) 2016 OXullo Intersecans +All alogrithms and methods used are from the above author, +I have only modified this enough to make it work with the new MAX30102 sensor. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,7 +21,7 @@ along with this program. If not, see . #include -#include "MAX30100_PulseOximeter.h" +#include "MAX30102_PulseOximeter.h" PulseOximeter::PulseOximeter() : @@ -46,8 +49,9 @@ bool PulseOximeter::begin(PulseOximeterDebuggingMode debuggingMode_) return false; } - hrm.setMode(MAX30100_MODE_SPO2_HR); - hrm.setLedsCurrent(irLedCurrent, (LEDCurrent)redLedCurrentIndex); + hrm.setMode(MAX30102_MODE_SPO2_HR); + hrm.setIRLedCurrent(irLedCurrent); + hrm.setRedLedCurrent((uint8_t)redLedCurrentIndex); irDCRemover = DCRemover(DC_REMOVER_ALPHA); redDCRemover = DCRemover(DC_REMOVER_ALPHA); @@ -85,10 +89,11 @@ void PulseOximeter::setOnBeatDetectedCallback(void (*cb)()) onBeatDetected = cb; } -void PulseOximeter::setIRLedCurrent(LEDCurrent irLedNewCurrent) +void PulseOximeter::setIRLedCurrent(uint8_t irLedNewCurrent) { irLedCurrent = irLedNewCurrent; - hrm.setLedsCurrent(irLedCurrent, (LEDCurrent)redLedCurrentIndex); + hrm.setIRLedCurrent(irLedCurrent); + hrm.setRedLedCurrent((uint8_t)redLedCurrentIndex); } void PulseOximeter::shutdown() @@ -160,7 +165,7 @@ void PulseOximeter::checkCurrentBias() // red and IR leds. The numbers are really magic: the less possible to avoid oscillations if (millis() - tsLastBiasCheck > CURRENT_ADJUSTMENT_PERIOD_MS) { bool changed = false; - if (irDCRemover.getDCW() - redDCRemover.getDCW() > 70000 && redLedCurrentIndex < MAX30100_LED_CURR_50MA) { + if (irDCRemover.getDCW() - redDCRemover.getDCW() > 70000 && redLedCurrentIndex < 0xff) { ++redLedCurrentIndex; changed = true; } else if (redDCRemover.getDCW() - irDCRemover.getDCW() > 70000 && redLedCurrentIndex > 0) { @@ -169,7 +174,8 @@ void PulseOximeter::checkCurrentBias() } if (changed) { - hrm.setLedsCurrent(irLedCurrent, (LEDCurrent)redLedCurrentIndex); + hrm.setIRLedCurrent(irLedCurrent); + hrm.setRedLedCurrent((uint8_t)redLedCurrentIndex); tsLastCurrentAdjustment = millis(); if (debuggingMode != PULSEOXIMETER_DEBUGGINGMODE_NONE) { From 200f4e027c1407425a64383187e9d56d6558e8cd Mon Sep 17 00:00:00 2001 From: Shivam Gupta Date: Sat, 26 Sep 2020 23:16:37 +0530 Subject: [PATCH 08/18] Initial commit for MAX30102 Updated for Max30102, with new register addresses and added features such as more fine control on led pulse amplitude and multi led mode --- src/MAX30100_Registers.h | 111 --------------------------------------- src/MAX30102_Registers.h | 87 ++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+), 111 deletions(-) delete mode 100644 src/MAX30100_Registers.h create mode 100644 src/MAX30102_Registers.h diff --git a/src/MAX30100_Registers.h b/src/MAX30100_Registers.h deleted file mode 100644 index df12be1..0000000 --- a/src/MAX30100_Registers.h +++ /dev/null @@ -1,111 +0,0 @@ -/* -Arduino-MAX30100 oximetry / heart rate integrated sensor library -Copyright (C) 2016 OXullo Intersecans - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ - -#ifndef MAX30100_REGISTERS_H -#define MAX30100_REGISTERS_H - -#define MAX30100_I2C_ADDRESS 0x57 - -// Interrupt status register (RO) -#define MAX30100_REG_INTERRUPT_STATUS 0x00 -#define MAX30100_IS_PWR_RDY (1 << 0) -#define MAX30100_IS_SPO2_RDY (1 << 4) -#define MAX30100_IS_HR_RDY (1 << 5) -#define MAX30100_IS_TEMP_RDY (1 << 6) -#define MAX30100_IS_A_FULL (1 << 7) - -// Interrupt enable register -#define MAX30100_REG_INTERRUPT_ENABLE 0x01 -#define MAX30100_IE_ENB_SPO2_RDY (1 << 4) -#define MAX30100_IE_ENB_HR_RDY (1 << 5) -#define MAX30100_IE_ENB_TEMP_RDY (1 << 6) -#define MAX30100_IE_ENB_A_FULL (1 << 7) - -// FIFO control and data registers -#define MAX30100_REG_FIFO_WRITE_POINTER 0x02 -#define MAX30100_REG_FIFO_OVERFLOW_COUNTER 0x03 -#define MAX30100_REG_FIFO_READ_POINTER 0x04 -#define MAX30100_REG_FIFO_DATA 0x05 // Burst read does not autoincrement addr - -// Mode Configuration register -#define MAX30100_REG_MODE_CONFIGURATION 0x06 -#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_REG_SPO2_CONFIGURATION 0x07 -#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 -#define MAX30100_REG_LED_CONFIGURATION 0x09 -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; - -// Temperature integer part register -#define MAX30100_REG_TEMPERATURE_DATA_INT 0x16 -// Temperature fractional part register -#define MAX30100_REG_TEMPERATURE_DATA_FRAC 0x17 - -// Revision ID register (RO) -#define MAX30100_REG_REVISION_ID 0xfe -// Part ID register -#define MAX30100_REG_PART_ID 0xff - -#define MAX30100_FIFO_DEPTH 0x10 - -#endif diff --git a/src/MAX30102_Registers.h b/src/MAX30102_Registers.h new file mode 100644 index 0000000..1e9e56e --- /dev/null +++ b/src/MAX30102_Registers.h @@ -0,0 +1,87 @@ +/* +Arduino-MAX30102 oximetry / heart rate integrated sensor library by Shivam Gupta (gupta.shivam1996@gmail.com) + +Based on MAX30100 library, Copyright (C) 2016 OXullo Intersecans +All alogrithms and methods used are from the above author, +I have only modified this enough to make it work with the new MAX30102 sensor. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#ifndef MAX30102_PULSEOXIMETER_H +#define MAX30102_PULSEOXIMETER_H + +#define SAMPLING_FREQUENCY 100 +#define CURRENT_ADJUSTMENT_PERIOD_MS 500 +#define DEFAULT_IR_LED_CURRENT 0xFF //51mA +#define RED_LED_CURRENT_START 0x88 //27mA +#define DC_REMOVER_ALPHA 0.95 + +#include + +#include "MAX30102.h" +#include "MAX30102_BeatDetector.h" +#include "MAX30102_Filters.h" +#include "MAX30102_SpO2Calculator.h" + +typedef enum PulseOximeterState { + PULSEOXIMETER_STATE_INIT, + PULSEOXIMETER_STATE_IDLE, + PULSEOXIMETER_STATE_DETECTING +} PulseOximeterState; + +typedef enum PulseOximeterDebuggingMode { + PULSEOXIMETER_DEBUGGINGMODE_NONE, + PULSEOXIMETER_DEBUGGINGMODE_RAW_VALUES, + PULSEOXIMETER_DEBUGGINGMODE_AC_VALUES, + PULSEOXIMETER_DEBUGGINGMODE_PULSEDETECT +} PulseOximeterDebuggingMode; + + +class PulseOximeter { +public: + PulseOximeter(); + + bool begin(PulseOximeterDebuggingMode debuggingMode_=PULSEOXIMETER_DEBUGGINGMODE_NONE); + void update(); + float getHeartRate(); + uint8_t getSpO2(); + uint8_t getRedLedCurrentBias(); + void setOnBeatDetectedCallback(void (*cb)()); + void setIRLedCurrent(uint8_t irLedCurrent); + void shutdown(); + void resume(); + +private: + void checkSample(); + void checkCurrentBias(); + + PulseOximeterState state; + PulseOximeterDebuggingMode debuggingMode; + uint32_t tsFirstBeatDetected; + uint32_t tsLastBeatDetected; + uint32_t tsLastBiasCheck; + uint32_t tsLastCurrentAdjustment; + BeatDetector beatDetector; + DCRemover irDCRemover; + DCRemover redDCRemover; + FilterBuLp1 lpf; + uint8_t redLedCurrentIndex; + uint8_t irLedCurrent; + SpO2Calculator spO2calculator; + MAX30102 hrm; + + void (*onBeatDetected)(); +}; +#endif From 8041d6796bdad78284809abf7160bfad6279dd89 Mon Sep 17 00:00:00 2001 From: Shivam Gupta Date: Sat, 26 Sep 2020 23:18:06 +0530 Subject: [PATCH 09/18] Initial commit for MAX30102 --- ...lseOximeter.h => MAX30102_PulseOximeter.h} | 29 ++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-) rename src/{MAX30100_PulseOximeter.h => MAX30102_PulseOximeter.h} (73%) diff --git a/src/MAX30100_PulseOximeter.h b/src/MAX30102_PulseOximeter.h similarity index 73% rename from src/MAX30100_PulseOximeter.h rename to src/MAX30102_PulseOximeter.h index 7fa690a..1e9e56e 100644 --- a/src/MAX30100_PulseOximeter.h +++ b/src/MAX30102_PulseOximeter.h @@ -1,6 +1,9 @@ /* -Arduino-MAX30100 oximetry / heart rate integrated sensor library -Copyright (C) 2016 OXullo Intersecans +Arduino-MAX30102 oximetry / heart rate integrated sensor library by Shivam Gupta (gupta.shivam1996@gmail.com) + +Based on MAX30100 library, Copyright (C) 2016 OXullo Intersecans +All alogrithms and methods used are from the above author, +I have only modified this enough to make it work with the new MAX30102 sensor. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -16,21 +19,21 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#ifndef MAX30100_PULSEOXIMETER_H -#define MAX30100_PULSEOXIMETER_H +#ifndef MAX30102_PULSEOXIMETER_H +#define MAX30102_PULSEOXIMETER_H #define SAMPLING_FREQUENCY 100 #define CURRENT_ADJUSTMENT_PERIOD_MS 500 -#define DEFAULT_IR_LED_CURRENT MAX30100_LED_CURR_50MA -#define RED_LED_CURRENT_START MAX30100_LED_CURR_27_1MA +#define DEFAULT_IR_LED_CURRENT 0xFF //51mA +#define RED_LED_CURRENT_START 0x88 //27mA #define DC_REMOVER_ALPHA 0.95 #include -#include "MAX30100.h" -#include "MAX30100_BeatDetector.h" -#include "MAX30100_Filters.h" -#include "MAX30100_SpO2Calculator.h" +#include "MAX30102.h" +#include "MAX30102_BeatDetector.h" +#include "MAX30102_Filters.h" +#include "MAX30102_SpO2Calculator.h" typedef enum PulseOximeterState { PULSEOXIMETER_STATE_INIT, @@ -56,7 +59,7 @@ class PulseOximeter { uint8_t getSpO2(); uint8_t getRedLedCurrentBias(); void setOnBeatDetectedCallback(void (*cb)()); - void setIRLedCurrent(LEDCurrent irLedCurrent); + void setIRLedCurrent(uint8_t irLedCurrent); void shutdown(); void resume(); @@ -75,9 +78,9 @@ class PulseOximeter { DCRemover redDCRemover; FilterBuLp1 lpf; uint8_t redLedCurrentIndex; - LEDCurrent irLedCurrent; + uint8_t irLedCurrent; SpO2Calculator spO2calculator; - MAX30100 hrm; + MAX30102 hrm; void (*onBeatDetected)(); }; From a721884d0d5c43a3a8033b978f2e56edd8b7bd30 Mon Sep 17 00:00:00 2001 From: Shivam Gupta Date: Sat, 26 Sep 2020 23:21:09 +0530 Subject: [PATCH 10/18] Initial commit for MAX30102 --- ...00_SpO2Calculator.cpp => MAX30102_SpO2Calculator.cpp} | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) rename src/{MAX30100_SpO2Calculator.cpp => MAX30102_SpO2Calculator.cpp} (84%) diff --git a/src/MAX30100_SpO2Calculator.cpp b/src/MAX30102_SpO2Calculator.cpp similarity index 84% rename from src/MAX30100_SpO2Calculator.cpp rename to src/MAX30102_SpO2Calculator.cpp index c15c572..4c4a072 100644 --- a/src/MAX30100_SpO2Calculator.cpp +++ b/src/MAX30102_SpO2Calculator.cpp @@ -1,6 +1,9 @@ /* -Arduino-MAX30100 oximetry / heart rate integrated sensor library -Copyright (C) 2016 OXullo Intersecans +Arduino-MAX30102 oximetry / heart rate integrated sensor library by Shivam Gupta (gupta.shivam1996@gmail.com) + +Based on MAX30100 library, Copyright (C) 2016 OXullo Intersecans +All alogrithms and methods used are from the above author, +I have only modified this enough to make it work with the new MAX30102 sensor. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,7 +21,7 @@ along with this program. If not, see . #include -#include "MAX30100_SpO2Calculator.h" +#include "MAX30102_SpO2Calculator.h" // SaO2 Look-up Table // http://www.ti.com/lit/an/slaa274b/slaa274b.pdf From 353c73d339a480de63958efc6d36f4f107deed31 Mon Sep 17 00:00:00 2001 From: Shivam Gupta Date: Sat, 26 Sep 2020 23:23:21 +0530 Subject: [PATCH 11/18] Initial commit for MAX30102 --- ...{MAX30100_SpO2Calculator.h => MAX30102_SpO2Calculator.h} | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) rename src/{MAX30100_SpO2Calculator.h => MAX30102_SpO2Calculator.h} (89%) diff --git a/src/MAX30100_SpO2Calculator.h b/src/MAX30102_SpO2Calculator.h similarity index 89% rename from src/MAX30100_SpO2Calculator.h rename to src/MAX30102_SpO2Calculator.h index 9044888..f1ca03f 100644 --- a/src/MAX30100_SpO2Calculator.h +++ b/src/MAX30102_SpO2Calculator.h @@ -1,5 +1,5 @@ /* -Arduino-MAX30100 oximetry / heart rate integrated sensor library +Arduino-MAX30102 oximetry / heart rate integrated sensor library Copyright (C) 2016 OXullo Intersecans This program is free software: you can redistribute it and/or modify @@ -16,8 +16,8 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#ifndef MAX30100_SPO2CALCULATOR_H -#define MAX30100_SPO2CALCULATOR_H +#ifndef MAX30102_SPO2CALCULATOR_H +#define MAX30102_SPO2CALCULATOR_H #include From caacd21f37ec9929d882074a31a12517442eeb15 Mon Sep 17 00:00:00 2001 From: Shivam Gupta Date: Sat, 26 Sep 2020 23:27:37 +0530 Subject: [PATCH 12/18] Update MAX30102_Registers.h --- src/MAX30102_Registers.h | 201 ++++++++++++++++++++++++++------------- 1 file changed, 136 insertions(+), 65 deletions(-) diff --git a/src/MAX30102_Registers.h b/src/MAX30102_Registers.h index 1e9e56e..b981a28 100644 --- a/src/MAX30102_Registers.h +++ b/src/MAX30102_Registers.h @@ -19,69 +19,140 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#ifndef MAX30102_PULSEOXIMETER_H -#define MAX30102_PULSEOXIMETER_H - -#define SAMPLING_FREQUENCY 100 -#define CURRENT_ADJUSTMENT_PERIOD_MS 500 -#define DEFAULT_IR_LED_CURRENT 0xFF //51mA -#define RED_LED_CURRENT_START 0x88 //27mA -#define DC_REMOVER_ALPHA 0.95 - -#include - -#include "MAX30102.h" -#include "MAX30102_BeatDetector.h" -#include "MAX30102_Filters.h" -#include "MAX30102_SpO2Calculator.h" - -typedef enum PulseOximeterState { - PULSEOXIMETER_STATE_INIT, - PULSEOXIMETER_STATE_IDLE, - PULSEOXIMETER_STATE_DETECTING -} PulseOximeterState; - -typedef enum PulseOximeterDebuggingMode { - PULSEOXIMETER_DEBUGGINGMODE_NONE, - PULSEOXIMETER_DEBUGGINGMODE_RAW_VALUES, - PULSEOXIMETER_DEBUGGINGMODE_AC_VALUES, - PULSEOXIMETER_DEBUGGINGMODE_PULSEDETECT -} PulseOximeterDebuggingMode; - - -class PulseOximeter { -public: - PulseOximeter(); - - bool begin(PulseOximeterDebuggingMode debuggingMode_=PULSEOXIMETER_DEBUGGINGMODE_NONE); - void update(); - float getHeartRate(); - uint8_t getSpO2(); - uint8_t getRedLedCurrentBias(); - void setOnBeatDetectedCallback(void (*cb)()); - void setIRLedCurrent(uint8_t irLedCurrent); - void shutdown(); - void resume(); - -private: - void checkSample(); - void checkCurrentBias(); - - PulseOximeterState state; - PulseOximeterDebuggingMode debuggingMode; - uint32_t tsFirstBeatDetected; - uint32_t tsLastBeatDetected; - uint32_t tsLastBiasCheck; - uint32_t tsLastCurrentAdjustment; - BeatDetector beatDetector; - DCRemover irDCRemover; - DCRemover redDCRemover; - FilterBuLp1 lpf; - uint8_t redLedCurrentIndex; - uint8_t irLedCurrent; - SpO2Calculator spO2calculator; - MAX30102 hrm; - - void (*onBeatDetected)(); -}; +#ifndef MAX30102_REGISTERS_H +#define MAX30102_REGISTERS_H + +#define MAX30102_I2C_ADDRESS 0x57 + +// Interrupt status register (RO) +#define MAX30102_REG_INTERRUPT_STATUS_A 0x00 +#define MAX30102_IS_PWR_RDY (1 << 0) +#define MAX30102_IS_ALC_OVF (1 << 5) +#define MAX30102_IS_PPG_RDY (1 << 6) +#define MAX30102_IS_A_FULL (1 << 7) + +// Interrupt status register (R1) +#define MAX30102_REG_INTERRUPT_STATUS_B 0x01 +#define MAX30102_IS_TEMP_RDY (1 << 1) + +// Interrupt enable register E1 +#define MAX30102_REG_INTERRUPT_ENABLE_A 0x02 +#define MAX30102_IE_ENB_ALC_OVF (1 << 5) +#define MAX30102_IE_ENB_PPG_RDY (1 << 6) +#define MAX30102_IE_ENB_A_FULL (1 << 7) + +// Interrupt enable register E2 +#define MAX30102_REG_INTERRUPT_ENABLE_B 0x03 +#define MAX30102_IE_ENB_TEMP_RDY (1 << 1) + +// FIFO control and data registers +#define MAX30102_REG_FIFO_WRITE_POINTER 0x04 +#define MAX30102_REG_FIFO_OVERFLOW_COUNTER 0x05 +#define MAX30102_REG_FIFO_READ_POINTER 0x06 +#define MAX30102_REG_FIFO_DATA 0x07 // Burst read does not autoincrement addr + +//FIFO config registers +#define MAX30102_REG_FIFO_CONFIG 0x08 +#define MAX30102_FC_FIFO_ROLLOVER_EN 1 << 4 +typedef enum FIFO_A_Full { + MAX30102_FC_FIFO_A_FULL_0 = 0x0, + MAX30102_FC_FIFO_A_FULL_1 = 0x1, + MAX30102_FC_FIFO_A_FULL_2 = 0x2, + MAX30102_FC_FIFO_A_FULL_3 = 0x3, + MAX30102_FC_FIFO_A_FULL_4 = 0x4, + MAX30102_FC_FIFO_A_FULL_5 = 0x5, + MAX30102_FC_FIFO_A_FULL_6 = 0x6, + MAX30102_FC_FIFO_A_FULL_7 = 0x7, + MAX30102_FC_FIFO_A_FULL_8 = 0x8, + MAX30102_FC_FIFO_A_FULL_9 = 0x9, + MAX30102_FC_FIFO_A_FULL_10 = 0xA, + MAX30102_FC_FIFO_A_FULL_11 = 0xB, + MAX30102_FC_FIFO_A_FULL_12 = 0xC, + MAX30102_FC_FIFO_A_FULL_15 = 0xF, + MAX30102_FC_FIFO_A_FULL_13 = 0xD, + MAX30102_FC_FIFO_A_FULL_14 = 0xE + +} FIFO_A_Full; + +typedef enum SampleAverage { + MAX30102_SMP_AVE_1 = 0x0, + MAX30102_SMP_AVE_2 = 0x1, + MAX30102_SMP_AVE_4 = 0x2, + MAX30102_SMP_AVE_8 = 0x3, + MAX30102_SMP_AVE_16 = 0x4, + MAX30102_SMP_AVE_32 = 0x5 +} SampleAverage; + + +// Mode Configuration register +#define MAX30102_REG_MODE_CONFIGURATION 0x09 +#define MAX30102_MC_RESET (1 << 6) +#define MAX30102_MC_SHDN (1 << 7) +typedef enum Mode { + MAX30102_MODE_HRONLY = 0x02, + MAX30102_MODE_SPO2_HR = 0x03, + MAX30102_MODE_MULTI = 0x07 +} Mode; + +// SpO2 Configuration register +// Check tables 8 and 9, p19 of the MAX30102 datasheet to see the permissible +// combinations of sampling rates and pulse widths +#define MAX30102_REG_SPO2_CONFIGURATION 0x0A + +typedef enum ADCRange { + MAX30102_ADCRange_2048 = 0x0, + MAX30102_ADCRange_4096 = 0x1, + MAX30102_ADCRange_8192 = 0x2, + MAX30102_ADCRange_16384 = 0x3, +} ADCRange; + +typedef enum SamplingRate { + MAX30102_SAMPRATE_50HZ = 0x00, + MAX30102_SAMPRATE_100HZ = 0x01, + MAX30102_SAMPRATE_167HZ = 0x02, + MAX30102_SAMPRATE_200HZ = 0x03, + MAX30102_SAMPRATE_400HZ = 0x04, + MAX30102_SAMPRATE_600HZ = 0x05, + MAX30102_SAMPRATE_800HZ = 0x06, + MAX30102_SAMPRATE_1000HZ = 0x07 +} SamplingRate; + +typedef enum LEDPulseWidth { + MAX30102_SPC_PW_69US_15BITS = 0x00, + MAX30102_SPC_PW_118US_16BITS = 0x01, + MAX30102_SPC_PW_215US_17BITS = 0x02, + MAX30102_SPC_PW_411US_18BITS = 0x03 +} LEDPulseWidth; + +// LED Configuration registers +#define MAX30102_REG_LED_RED_PA 0x0C +#define MAX30102_REG_LED_IR_PA 0x0D + +// Multi LED Mode Control registers, refer page 21 of datasheet +#define MAX30102_REG_MULTI_LED_CTRL_1AND2 0x11 +#define MAX30102_REG_MULTI_LED_CTRL_3AND4 0x12 + +typedef enum SlotSetting { + MAX30102_SLOT_SETTING_OFF = 0x0, + MAX30102_SLOT_SETTING_RED = 0x1, + MAX30102_SLOT_SETTING_IR = 0x1 +} SlotSetting; + + +// Temperature integer part register +#define MAX30102_REG_TEMPERATURE_DATA_INT 0x1F +// Temperature fractional part register +#define MAX30102_REG_TEMPERATURE_DATA_FRAC 0x20 + +//Temperature emable +#define MAX30102_REG_TEMP_CONFIG 0x21 +#define MAX30102_TC_TEMP_EN 1 << 0 + +// Revision ID register (RO) +#define MAX30102_REG_REVISION_ID 0xfe +// Part ID register +#define MAX30102_REG_PART_ID 0xff + +#define MAX30102_FIFO_DEPTH 0x20 + #endif From 171408d824a2bcab13db7475e654d2574731f9b1 Mon Sep 17 00:00:00 2001 From: Shivam Gupta Date: Sat, 26 Sep 2020 23:30:13 +0530 Subject: [PATCH 13/18] Initial commit for MAX30102 --- src/MAX30102_SpO2Calculator.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/MAX30102_SpO2Calculator.h b/src/MAX30102_SpO2Calculator.h index f1ca03f..c618076 100644 --- a/src/MAX30102_SpO2Calculator.h +++ b/src/MAX30102_SpO2Calculator.h @@ -1,6 +1,9 @@ /* -Arduino-MAX30102 oximetry / heart rate integrated sensor library -Copyright (C) 2016 OXullo Intersecans +Arduino-MAX30102 oximetry / heart rate integrated sensor library by Shivam Gupta (gupta.shivam1996@gmail.com) + +Based on MAX30100 library, Copyright (C) 2016 OXullo Intersecans +All alogrithms and methods used are from the above author, +I have only modified this enough to make it work with the new MAX30102 sensor. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by From 3764b1535366778b4066117217cebc736a9f45ea Mon Sep 17 00:00:00 2001 From: Shivam Gupta Date: Sat, 26 Sep 2020 23:40:42 +0530 Subject: [PATCH 14/18] Initial Release for MAX30102 --- .github/issue_template.md | 6 +- .travis.yml | 4 +- README.md | 44 +++---- examples/MAX30100_Debug/MAX30100_Debug.ino | 81 ------------ .../MAX30100_Minimal/MAX30100_Minimal.ino | 80 ------------ .../MAX30100_RawData/MAX30100_RawData.ino | 80 ------------ examples/MAX30100_Tester/MAX30100_Tester.ino | 120 ------------------ extras/recorder/README.md | 6 +- extras/recorder/recorder.py | 2 +- extras/rolling_graph/README.md | 2 +- extras/rolling_graph/rolling_graph.pde | 13 +- library.json | 14 +- library.properties | 8 +- 13 files changed, 48 insertions(+), 412 deletions(-) delete mode 100644 examples/MAX30100_Debug/MAX30100_Debug.ino delete mode 100644 examples/MAX30100_Minimal/MAX30100_Minimal.ino delete mode 100644 examples/MAX30100_RawData/MAX30100_RawData.ino delete mode 100644 examples/MAX30100_Tester/MAX30100_Tester.ino diff --git a/.github/issue_template.md b/.github/issue_template.md index 251d2e3..0e7010d 100644 --- a/.github/issue_template.md +++ b/.github/issue_template.md @@ -1,7 +1,7 @@ ### Troubleshooting checklist - [ ] I read the README (on master) thoroughly -- [ ] I ran the MAX30100_Tester and I'm going to paste the output down below +- [ ] I ran the MAX30102_Tester and I'm going to paste the output down below - [ ] I filled in all the details of my setup down below ### Description of the issue @@ -11,6 +11,6 @@ ### Details of my setup * Arduino hardware: -* MAX30100 breakout: +* MAX30102 breakout: * Arduino framework version: -* MAX30100 library version: +* MAX30102 library version: diff --git a/.travis.yml b/.travis.yml index dbeba73..b44139a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,8 +8,8 @@ cache: - "~/.platformio" env: - - PLATFORMIO_CI_SRC=examples/MAX30100_Minimal - - PLATFORMIO_CI_SRC=examples/MAX30100_Debug + - PLATFORMIO_CI_SRC=examples/MAX30102_Minimal + - PLATFORMIO_CI_SRC=examples/MAX30102_Debug install: - pip install -U platformio diff --git a/README.md b/README.md index 35ea124..66b5724 100644 --- a/README.md +++ b/README.md @@ -1,28 +1,22 @@ -# Arduino-MAX30100 +# Arduino-MAX30102 -[![Build Status](https://travis-ci.org/oxullo/Arduino-MAX30100.svg?branch=master)](https://travis-ci.org/oxullo/Arduino-MAX30100) +Arduino library for the Maxim Integrated MAX30102 oximetry / heart rate sensor. -Arduino library for the Maxim Integrated MAX30100 oximetry / heart rate sensor. - -![MAX30100](http://www.mouser.com/images/microsites/Maxim_MAX30100.jpg) +![MAX30102](https://www.amazon.in/xcluma-MAX30102-Upgraded-Ultra-Low-Compatible/dp/B07TZCNG2G/ref=sr_1_1?crid=3H93UW42TRQWY&dchild=1&keywords=xcluma+max30102&qid=1601127280&sprefix=xcluma+max%2Caps%2C299&sr=8-1) ## Disclaimer The library is offered only for educational purposes and it is not meant for medical uses. Use it at your sole risk. -## Notes - -Maxim integrated stopped the production of the MAX30100 in favor of MAX30101 and MAX30102. -Therefore this library won't be seeing any further improvement, besides fixes. - *IMPORTANT: when submitting issues, make sure to fill ALL the fields indicated in the template text of the issue. The issue will be marked as invalid and closed immediately otherwise.* ## Hardware -This library has been tested with the MikroElektronika Heart rate click daughterboard: +This library has been tested with two different breakout boards for MAX30102 -http://www.mikroe.com/click/heart-rate/ +https://www.amazon.in/xcluma-MAX30102-Upgraded-Ultra-Low-Compatible/dp/B07TZCNG2G/ref=sr_1_1?crid=3H93UW42TRQWY&dchild=1&keywords=xcluma+max30102&qid=1601127280&sprefix=xcluma+max%2Caps%2C299&sr=8-1 +https://robokits.co.in/sensors/heart-beat-sensor/max30102-oximetry-sensor-module along with an Arduino UNO r3. Any Arduino supporting the Wire library should work. @@ -41,7 +35,7 @@ up by 4,7kOhm or less resistors. ## Architecture -The library offers a low-level driver class, MAX30100. +The library offers a low-level driver class, MAX30102. This component allows for low level communication with the device. A rather simple but working implementation of the heart rate and SpO2 calculation @@ -61,18 +55,18 @@ The PulseOximeter class is not optimised for battery-based projects. The included examples show how to use the PulseOximeter class: - * MAX30100_Minimal: a minimal example that dumps human-readable results via serial - * MAX30100_Debug: used in conjunction with the Processing pde "rolling_graph" (extras folder), to show the sampled data at various processing stages - * MAX30100_RawData: demonstrates how to access raw data from the sensor - * MAX30100_Tester: this sketch helps to find out potential issues with the sensor + * MAX30102_Minimal: a minimal example that dumps human-readable results via serial + * MAX30102_Debug: used in conjunction with the Processing pde "rolling_graph" (extras folder), to show the sampled data at various processing stages + * MAX30102_RawData: demonstrates how to access raw data from the sensor + * MAX30102_Tester: this sketch helps to find out potential issues with the sensor ## Troubleshooting -Run the MAX30100_Tester example to inspect the state of your rig. +Run the MAX30102_Tester example to inspect the state of your rig. When run with a properly connected sensor, it should print: ``` -Initializing MAX30100..Success +Initializing MAX30102..Success Enabling HR/SPO2 mode..done. Configuring LEDs biases to 50mA..done. Lowering the current to 7.6mA..done. @@ -95,7 +89,7 @@ Typical issues when attempting to run the examples: In particular when the tester fails with: ``` -Initializing MAX30100..FAILED: I2C error +Initializing MAX30102..FAILED: I2C error ``` This is likely to be caused by an improper pullup setup for the I2C lines. @@ -109,7 +103,7 @@ to 3.3V, you should ensure that its inputs are compatible with the 3.3V logic le An original Atmel ATMega328p considers anything above 3V as HIGH, so it might work well without level shifting hardware. -Since the MAX30100 I2C pins maximum ratings aren't bound to Vdd, a cheap option to avoid +Since the MAX30102 I2C pins maximum ratings aren't bound to Vdd, a cheap option to avoid level shifting is to simply pull SDA and SCL up to 5V instead of 3.3V. ### Sketchy beat frequency readouts @@ -119,14 +113,14 @@ by default at 50mA on all examples, excluding the Tester (which sets it to 7.6mA This value is somehow critical and it must be experimented with. The current can be adjusted using PulseOximeter::setIRLedCurrent(). -Check the _MAX30100_Minimal_ example. +Check the _MAX30102_Minimal_ example. ### Advanced debugging Two tools are available for further inspection and error reporting: * extras/recorder: a python script that records a session that can be then analysed with the provided collection of jupyter notebooks -* extras/rolling_graph: to be used in conjunction with _MAX30100_Debug_ example, it provides a visual feedback of the LED tracking and heartbeat detector +* extras/rolling_graph: to be used in conjunction with _MAX30102_Debug_ example, it provides a visual feedback of the LED tracking and heartbeat detector Both tools have additional information on the README.md in their respective directories. @@ -136,13 +130,13 @@ Both tools have additional information on the README.md in their respective dire This combination works without level shifting devices at 400kHz I2C clock rate. -* Arduino UNO r3, MAX30100 custom board with 4.7kOhm pullups to 5V to SDA, SCL, INT +* Arduino UNO r3, MAX30102 custom board with 4.7kOhm pullups to 5V to SDA, SCL, INT As above, working at 400kHz * Sparkfun Arduino Pro 328p 8MHz 3.3V, Mikroelektronika Heart rate click -Even if this combination works (MAX30100 communication), the slower clock speed fails to deliver +Even if this combination works (MAX30102 communication), the slower clock speed fails to deliver the required performance deadlines for a 100Hz sampling. ## Troubled breakouts diff --git a/examples/MAX30100_Debug/MAX30100_Debug.ino b/examples/MAX30100_Debug/MAX30100_Debug.ino deleted file mode 100644 index d08e6b7..0000000 --- a/examples/MAX30100_Debug/MAX30100_Debug.ino +++ /dev/null @@ -1,81 +0,0 @@ -/* -Arduino-MAX30100 oximetry / heart rate integrated sensor library -Copyright (C) 2016 OXullo Intersecans - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ - -// This example must be used in conjunction with the Processing sketch located -// in extras/rolling_graph - -#include -#include "MAX30100_PulseOximeter.h" - -#define REPORTING_PERIOD_MS 1000 - -// PulseOximeter is the higher level interface to the sensor -// it offers: -// * beat detection reporting -// * heart rate calculation -// * SpO2 (oxidation level) calculation -PulseOximeter pox; - -uint32_t tsLastReport = 0; - -// Callback (registered below) fired when a pulse is detected -void onBeatDetected() -{ - Serial.println("B:1"); -} - -void setup() -{ - Serial.begin(115200); - - // Initialize the PulseOximeter instance and register a beat-detected callback - // The parameter passed to the begin() method changes the samples flow that - // the library spews to the serial. - // Options: - // * PULSEOXIMETER_DEBUGGINGMODE_PULSEDETECT : filtered samples and beat detection threshold - // * PULSEOXIMETER_DEBUGGINGMODE_RAW_VALUES : sampled values coming from the sensor, with no processing - // * PULSEOXIMETER_DEBUGGINGMODE_AC_VALUES : sampled values after the DC removal filter - - // Initialize the PulseOximeter instance - // Failures are generally due to an improper I2C wiring, missing power supply - // or wrong target chip - if (!pox.begin(PULSEOXIMETER_DEBUGGINGMODE_PULSEDETECT)) { - Serial.println("ERROR: Failed to initialize pulse oximeter"); - for(;;); - } - - pox.setOnBeatDetectedCallback(onBeatDetected); -} - -void loop() -{ - // Make sure to call update as fast as possible - pox.update(); - - // Asynchronously dump heart rate and oxidation levels to the serial - // For both, a value of 0 means "invalid" - if (millis() - tsLastReport > REPORTING_PERIOD_MS) { - Serial.print("H:"); - Serial.println(pox.getHeartRate()); - - Serial.print("O:"); - Serial.println(pox.getSpO2()); - - tsLastReport = millis(); - } -} diff --git a/examples/MAX30100_Minimal/MAX30100_Minimal.ino b/examples/MAX30100_Minimal/MAX30100_Minimal.ino deleted file mode 100644 index 456feae..0000000 --- a/examples/MAX30100_Minimal/MAX30100_Minimal.ino +++ /dev/null @@ -1,80 +0,0 @@ -/* -Arduino-MAX30100 oximetry / heart rate integrated sensor library -Copyright (C) 2016 OXullo Intersecans - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ - -#include -#include "MAX30100_PulseOximeter.h" - -#define REPORTING_PERIOD_MS 1000 - -// PulseOximeter is the higher level interface to the sensor -// it offers: -// * beat detection reporting -// * heart rate calculation -// * SpO2 (oxidation level) calculation -PulseOximeter pox; - -uint32_t tsLastReport = 0; - -// Callback (registered below) fired when a pulse is detected -void onBeatDetected() -{ - Serial.println("Beat!"); -} - -void setup() -{ - Serial.begin(115200); - - Serial.print("Initializing pulse oximeter.."); - - // Initialize the PulseOximeter instance - // Failures are generally due to an improper I2C wiring, missing power supply - // or wrong target chip - if (!pox.begin()) { - Serial.println("FAILED"); - for(;;); - } else { - Serial.println("SUCCESS"); - } - - // The default current for the IR LED is 50mA and it could be changed - // by uncommenting the following line. Check MAX30100_Registers.h for all the - // available options. - // pox.setIRLedCurrent(MAX30100_LED_CURR_7_6MA); - - // Register a callback for the beat detection - pox.setOnBeatDetectedCallback(onBeatDetected); -} - -void loop() -{ - // Make sure to call update as fast as possible - pox.update(); - - // Asynchronously dump heart rate and oxidation levels to the serial - // For both, a value of 0 means "invalid" - if (millis() - tsLastReport > REPORTING_PERIOD_MS) { - Serial.print("Heart rate:"); - Serial.print(pox.getHeartRate()); - Serial.print("bpm / SpO2:"); - Serial.print(pox.getSpO2()); - Serial.println("%"); - - tsLastReport = millis(); - } -} diff --git a/examples/MAX30100_RawData/MAX30100_RawData.ino b/examples/MAX30100_RawData/MAX30100_RawData.ino deleted file mode 100644 index 5b186bc..0000000 --- a/examples/MAX30100_RawData/MAX30100_RawData.ino +++ /dev/null @@ -1,80 +0,0 @@ -/* -Arduino-MAX30100 oximetry / heart rate integrated sensor library -Copyright (C) 2016 OXullo Intersecans - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ - -// The example shows how to retrieve raw values from the sensor -// experimenting with the most relevant configuration parameters. -// Use the "Serial Plotter" app from arduino IDE 1.6.7+ to plot the output - -#include -#include "MAX30100.h" - -// Sampling is tightly related to the dynamic range of the ADC. -// refer to the datasheet for further info -#define SAMPLING_RATE MAX30100_SAMPRATE_100HZ - -// 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 - - -// Instantiate a MAX30100 sensor class -MAX30100 sensor; - -void setup() -{ - Serial.begin(115200); - - Serial.print("Initializing MAX30100.."); - - // Initialize the sensor - // Failures are generally due to an improper I2C wiring, missing power supply - // or wrong target chip - if (!sensor.begin()) { - Serial.println("FAILED"); - for(;;); - } else { - Serial.println("SUCCESS"); - } - - // Set up the wanted parameters - sensor.setMode(MAX30100_MODE_SPO2_HR); - sensor.setLedsCurrent(IR_LED_CURRENT, RED_LED_CURRENT); - sensor.setLedsPulseWidth(PULSE_WIDTH); - sensor.setSamplingRate(SAMPLING_RATE); - sensor.setHighresModeEnabled(HIGHRES_MODE); -} - -void loop() -{ - uint16_t ir, red; - - sensor.update(); - - while (sensor.getRawValues(&ir, &red)) { - Serial.print(ir); - Serial.print('\t'); - Serial.println(red); - } -} diff --git a/examples/MAX30100_Tester/MAX30100_Tester.ino b/examples/MAX30100_Tester/MAX30100_Tester.ino deleted file mode 100644 index f24b436..0000000 --- a/examples/MAX30100_Tester/MAX30100_Tester.ino +++ /dev/null @@ -1,120 +0,0 @@ -/* -Arduino-MAX30100 oximetry / heart rate integrated sensor library -Copyright (C) 2017 OXullo Intersecans - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ - -// This example can be used to test connectivity and operation of the sensor -// check the README file on the repo's root for a troubleshooting guide in case -// any of the tests running fail - -#include -#include "MAX30100.h" - -MAX30100 sensor; - -void setup() -{ - Serial.begin(115200); - - Serial.print("Initializing MAX30100.."); - - if (!sensor.begin()) { - Serial.print("FAILED: "); - - uint8_t partId = sensor.getPartId(); - if (partId == 0xff) { - Serial.println("I2C error"); - } else { - Serial.print("wrong part ID 0x"); - Serial.print(partId, HEX); - Serial.print(" (expected: 0x"); - Serial.println(EXPECTED_PART_ID, HEX); - } - // Stop here - for(;;); - } else { - Serial.println("Success"); - } - - Serial.print("Enabling HR/SPO2 mode.."); - sensor.setMode(MAX30100_MODE_SPO2_HR); - Serial.println("done."); - - Serial.print("Configuring LEDs biases to 50mA.."); - sensor.setLedsCurrent(MAX30100_LED_CURR_50MA, MAX30100_LED_CURR_50MA); - Serial.println("done."); - - delay(1000); - - Serial.print("Lowering the current to 7.6mA.."); - sensor.setLedsCurrent(MAX30100_LED_CURR_7_6MA, MAX30100_LED_CURR_7_6MA); - Serial.println("done."); - - delay(1000); - - Serial.print("Shutting down.."); - sensor.shutdown(); - Serial.println("done."); - - delay(1000); - - Serial.print("Resuming normal operation.."); - sensor.resume(); - delay(500); - Serial.println("done."); - - uint32_t tsTempSampStart = millis(); - Serial.print("Sampling die temperature.."); - sensor.startTemperatureSampling(); - while(!sensor.isTemperatureReady()) { - if (millis() - tsTempSampStart > 1000) { - Serial.println("ERROR: timeout"); - // Stop here - for(;;); - } - } - - float temperature = sensor.retrieveTemperature(); - Serial.print("done, temp="); - Serial.print(temperature); - Serial.println("C"); - - if (temperature < 5) { - Serial.println("WARNING: Temperature probe reported an odd value"); - } else { - Serial.println("All test pass."); - } - - Serial.println(); - Serial.println("Press any key to go into sampling loop mode"); - while (!Serial.available()); - - sensor.resetFifo(); -} - -void loop() -{ - uint16_t ir, red; - - sensor.update(); - - while (sensor.getRawValues(&ir, &red)) { - Serial.print("IR="); - Serial.print(ir); - Serial.print(" RED="); - Serial.println(red); - } -} diff --git a/extras/recorder/README.md b/extras/recorder/README.md index 19f888c..0c5382c 100644 --- a/extras/recorder/README.md +++ b/extras/recorder/README.md @@ -7,10 +7,10 @@ This tool pipes a raw session from the sensor into a file for further analysis. The recorder and the analysis notebook require python and analysis libraries. Virtualenv is warmly suggested. -* Flash the example firmware MAX30100_RawData to the microcontroller board +* Flash the example firmware MAX30102_RawData to the microcontroller board * Install the required libraries - $ virtualenv max30100env - $ source max30100env/bin/activate + $ virtualenv max30102env + $ source max30102env/bin/activate $ pip install -Ur requirements.txt * Ensure the board is connected diff --git a/extras/recorder/recorder.py b/extras/recorder/recorder.py index 0f63b40..6ebc7ac 100755 --- a/extras/recorder/recorder.py +++ b/extras/recorder/recorder.py @@ -12,7 +12,7 @@ # # Data logger -# to be used in conjunction with the MAX30100_RawData example +# to be used in conjunction with the MAX30102_RawData example # diff --git a/extras/rolling_graph/README.md b/extras/rolling_graph/README.md index 3d5caf2..baab305 100644 --- a/extras/rolling_graph/README.md +++ b/extras/rolling_graph/README.md @@ -6,7 +6,7 @@ a visual inspection of the beat detection algorithm. ## Requirements * Processing 3+ (http://www.processing.org) -* Flash the example MAX30100_Debug to the target microcontroller +* Flash the example MAX30102_Debug to the target microcontroller ## Usage diff --git a/extras/rolling_graph/rolling_graph.pde b/extras/rolling_graph/rolling_graph.pde index 943af72..eeed840 100644 --- a/extras/rolling_graph/rolling_graph.pde +++ b/extras/rolling_graph/rolling_graph.pde @@ -1,6 +1,9 @@ /* -Arduino-MAX30100 oximetry / heart rate integrated sensor library -Copyright (C) 2016 OXullo Intersecans +Arduino-MAX30102 oximetry / heart rate integrated sensor library by Shivam Gupta (gupta.shivam1996@gmail.com) + +Based on MAX30100 library, Copyright (C) 2016 OXullo Intersecans +All alogrithms and methods used are from the above author, +I have only modified this enough to make it work with the new MAX30102 sensor.Copyright (C) 2016 OXullo Intersecans This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -16,7 +19,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -// Grapher helper for the Arduino MAX30100 library +// Grapher helper for the Arduino MAX30102 library import processing.serial.*; @@ -24,7 +27,7 @@ import processing.serial.*; // set this to -1 to enable the auto range mode final int ABSMAX = 800; // Adjust to the serial port. Under OSX, UNO platforms and alike are auto-detected. -final String serialPort = "/dev/tty.usbmodemFD13131"; +final String serialPort = "COM3"; final int WIDTH = 1200; @@ -158,4 +161,4 @@ void serialEvent (Serial myPort) } else if (sLine.substring(0, 2).equals("I:")) { redLedCurrentIndex = int(float(sLine.substring(2))); } -} \ No newline at end of file +} diff --git a/library.json b/library.json index 959c0e8..8ce3698 100644 --- a/library.json +++ b/library.json @@ -1,18 +1,18 @@ { - "name": "MAX30100lib", - "keywords": "pulse,oximetry,spo2,max30100,sensor,i2c", - "description": "Maxim-IC MAX30100 heart-rate sensor driver and pulse-oximetry components", + "name": "MAX30102lib", + "keywords": "pulse,oximetry,spo2,max30102,sensor,i2c", + "description": "Maxim-IC MAX30102 heart-rate sensor driver and pulse-oximetry components", "authors": { - "name": "OXullo Intersecans", - "email": "x@brainrapers.org", - "url": "https://github.com/oxullo/", + "name": "Shivam Gupta", + "email": "gupta.shivam1996@gmail.com", + "url": "https://github.com/thewiseguyshivam", "maintainer": true }, "repository": { "type": "git", - "url": "https://github.com/oxullo/Arduino-MAX30100" + "url": "https://github.com/oxullo/Arduino-MAX30102" }, "version": "1.2.1", "frameworks": "arduino", diff --git a/library.properties b/library.properties index 73a13f7..53a1cb8 100644 --- a/library.properties +++ b/library.properties @@ -1,9 +1,9 @@ -name=MAX30100lib +name=MAX30102lib version=1.2.1 author=OXullo Intersecans maintainer=OXullo Intersecans -sentence=Maxim-IC MAX30100 heart-rate sensor driver and pulse-oximetry components -paragraph=This library exposes most of the features of the MAX30100 and offers a modular approach to calculate pulse rate and SpO2 +sentence=Maxim-IC MAX30102 heart-rate sensor driver and pulse-oximetry components +paragraph=This library exposes most of the features of the MAX30102 and offers a modular approach to calculate pulse rate and SpO2 category=Sensors -url=https://github.com/oxullo/Arduino-MAX30100 +url=https://github.com/oxullo/Arduino-MAX30102 architectures=* From fa3da57f845fb3f2d18b4031f047816b9bf45879 Mon Sep 17 00:00:00 2001 From: Shivam Gupta Date: Sat, 26 Sep 2020 23:47:27 +0530 Subject: [PATCH 15/18] Metadata edits --- README.md | 1 + library.json | 4 ++-- library.properties | 8 ++++---- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 66b5724..777b9ed 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ Use it at your sole risk. This library has been tested with two different breakout boards for MAX30102 https://www.amazon.in/xcluma-MAX30102-Upgraded-Ultra-Low-Compatible/dp/B07TZCNG2G/ref=sr_1_1?crid=3H93UW42TRQWY&dchild=1&keywords=xcluma+max30102&qid=1601127280&sprefix=xcluma+max%2Caps%2C299&sr=8-1 + https://robokits.co.in/sensors/heart-beat-sensor/max30102-oximetry-sensor-module along with an Arduino UNO r3. Any Arduino supporting the Wire library should work. diff --git a/library.json b/library.json index 8ce3698..db841b7 100644 --- a/library.json +++ b/library.json @@ -12,9 +12,9 @@ "repository": { "type": "git", - "url": "https://github.com/oxullo/Arduino-MAX30102" + "url": "https://github.com/thewiseguyshivam/Arduino-MAX30102" }, - "version": "1.2.1", + "version": "1.0", "frameworks": "arduino", "platforms": "atmelavr" } diff --git a/library.properties b/library.properties index 53a1cb8..4bb84c3 100644 --- a/library.properties +++ b/library.properties @@ -1,9 +1,9 @@ name=MAX30102lib -version=1.2.1 -author=OXullo Intersecans -maintainer=OXullo Intersecans +version=1.0 +author=Shivam Gupta +maintainer=Shivam Gupta sentence=Maxim-IC MAX30102 heart-rate sensor driver and pulse-oximetry components paragraph=This library exposes most of the features of the MAX30102 and offers a modular approach to calculate pulse rate and SpO2 category=Sensors -url=https://github.com/oxullo/Arduino-MAX30102 +url=https://github.com/thewiseguyshivam/Arduino-MAX30102 architectures=* From 00241fef6c768bb5b91b211bfcdb3f7cd7ae1790 Mon Sep 17 00:00:00 2001 From: Shivam Gupta Date: Mon, 12 Oct 2020 18:19:22 +0530 Subject: [PATCH 16/18] Update README.md --- README.md | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 777b9ed..f5909d3 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,17 @@ Arduino library for the Maxim Integrated MAX30102 oximetry / heart rate sensor. -![MAX30102](https://www.amazon.in/xcluma-MAX30102-Upgraded-Ultra-Low-Compatible/dp/B07TZCNG2G/ref=sr_1_1?crid=3H93UW42TRQWY&dchild=1&keywords=xcluma+max30102&qid=1601127280&sprefix=xcluma+max%2Caps%2C299&sr=8-1) + +Based on a library written for the older MAX30100 sensor by OXullo Intersecans in 2016. +It has been ported to work with MAX30102 sensor breakouts, and new functions have been added to the library such as channel control, +so that all available functions of the device can be accessed with ease. + +All algorithms and example codes are written by the above author [OXullo Intersecans ], this is a fork building on that to extend support. +Original Library can be found here : https://github.com/oxullo/Arduino-MAX30100 + +vvvvvvvvvvvvvv +Carried over content, changed to fit the experiments I performed: +vvvvvvvvvvvvvv ## Disclaimer @@ -19,6 +29,8 @@ https://www.amazon.in/xcluma-MAX30102-Upgraded-Ultra-Low-Compatible/dp/B07TZCNG2 https://robokits.co.in/sensors/heart-beat-sensor/max30102-oximetry-sensor-module +https://in.element14.com/webapp/wcs/stores/servlet/ProductDisplay?catalogId=15001&langId=91&productSeoURL=maxim-integrated-products&storeId=10186&partNumber=2627165&krypto=R4I%2BFWxL8JW4fRaTcbt%2BHuLRKF64g5pcACQC6j4AdeuGGnr%2F0z4QoAgzJYIFu516Z9ZklPwUROYW5qFA%2BXaDmA%3D%3D + along with an Arduino UNO r3. Any Arduino supporting the Wire library should work. The only required connection to the sensor is the I2C bus (SDA, SCL lines, pulled up). @@ -127,18 +139,7 @@ Both tools have additional information on the README.md in their respective dire ## Tested devices -* Arduino UNO r3, Mikroelektronika Heart rate click (https://shop.mikroe.com/heart-rate-click) - -This combination works without level shifting devices at 400kHz I2C clock rate. - -* Arduino UNO r3, MAX30102 custom board with 4.7kOhm pullups to 5V to SDA, SCL, INT - -As above, working at 400kHz - -* Sparkfun Arduino Pro 328p 8MHz 3.3V, Mikroelektronika Heart rate click - -Even if this combination works (MAX30102 communication), the slower clock speed fails to deliver -the required performance deadlines for a 100Hz sampling. +#todo ## Troubled breakouts From 315759ec3c6f18d95fbb170631a3693705147cde Mon Sep 17 00:00:00 2001 From: Shivam Gupta Date: Mon, 12 Oct 2020 18:20:08 +0530 Subject: [PATCH 17/18] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f5909d3..1bf9181 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Arduino-MAX30102 -Arduino library for the Maxim Integrated MAX30102 oximetry / heart rate sensor. +Arduino library for the Maxim Integrated MAX30102 oximetry / heart rate sensor by Shivam Gupta Based on a library written for the older MAX30100 sensor by OXullo Intersecans in 2016. From 2877799f5836934e3cd78c8c55365dbe53859b85 Mon Sep 17 00:00:00 2001 From: Shivam Gupta Date: Mon, 12 Oct 2020 18:25:34 +0530 Subject: [PATCH 18/18] Add files via upload --- examples/MAX30102_Debug/MAX30102_Debug.ino | 84 ++++++++++++ .../MAX30102_Minimal/MAX30102_Minimal.ino | 83 ++++++++++++ .../MAX30102_RawData/MAX30102_RawData.ino | 85 ++++++++++++ examples/MAX30102_Tester/MAX30102_Tester.ino | 126 ++++++++++++++++++ 4 files changed, 378 insertions(+) create mode 100644 examples/MAX30102_Debug/MAX30102_Debug.ino create mode 100644 examples/MAX30102_Minimal/MAX30102_Minimal.ino create mode 100644 examples/MAX30102_RawData/MAX30102_RawData.ino create mode 100644 examples/MAX30102_Tester/MAX30102_Tester.ino diff --git a/examples/MAX30102_Debug/MAX30102_Debug.ino b/examples/MAX30102_Debug/MAX30102_Debug.ino new file mode 100644 index 0000000..2d58259 --- /dev/null +++ b/examples/MAX30102_Debug/MAX30102_Debug.ino @@ -0,0 +1,84 @@ +/* +Arduino-MAX30102 oximetry / heart rate integrated sensor library by Shivam Gupta (gupta.shivam1996@gmail.com) + +Based on MAX30100 library, Copyright (C) 2016 OXullo Intersecans +All alogrithms and methods used are from the above author, +I have only modified this enough to make it work with the new MAX30102 sensor. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +// This example must be used in conjunction with the Processing sketch located +// in extras/rolling_graph + +#include +#include "MAX30102_PulseOximeter.h" + +#define REPORTING_PERIOD_MS 1000 + +// PulseOximeter is the higher level interface to the sensor +// it offers: +// * beat detection reporting +// * heart rate calculation +// * SpO2 (oxidation level) calculation +PulseOximeter pox; + +uint32_t tsLastReport = 0; + +// Callback (registered below) fired when a pulse is detected +void onBeatDetected() +{ + Serial.println("B:1"); +} + +void setup() +{ + Serial.begin(115200); + + // Initialize the PulseOximeter instance and register a beat-detected callback + // The parameter passed to the begin() method changes the samples flow that + // the library spews to the serial. + // Options: + // * PULSEOXIMETER_DEBUGGINGMODE_PULSEDETECT : filtered samples and beat detection threshold + // * PULSEOXIMETER_DEBUGGINGMODE_RAW_VALUES : sampled values coming from the sensor, with no processing + // * PULSEOXIMETER_DEBUGGINGMODE_AC_VALUES : sampled values after the DC removal filter + + // Initialize the PulseOximeter instance + // Failures are generally due to an improper I2C wiring, missing power supply + // or wrong target chip + if (!pox.begin(PULSEOXIMETER_DEBUGGINGMODE_PULSEDETECT)) { + Serial.println("ERROR: Failed to initialize pulse oximeter"); + for(;;); + } + + pox.setOnBeatDetectedCallback(onBeatDetected); +} + +void loop() +{ + // Make sure to call update as fast as possible + pox.update(); + + // Asynchronously dump heart rate and oxidation levels to the serial + // For both, a value of 0 means "invalid" + if (millis() - tsLastReport > REPORTING_PERIOD_MS) { + Serial.print("H:"); + Serial.println(pox.getHeartRate()); + + Serial.print("O:"); + Serial.println(pox.getSpO2()); + + tsLastReport = millis(); + } +} diff --git a/examples/MAX30102_Minimal/MAX30102_Minimal.ino b/examples/MAX30102_Minimal/MAX30102_Minimal.ino new file mode 100644 index 0000000..2c74a51 --- /dev/null +++ b/examples/MAX30102_Minimal/MAX30102_Minimal.ino @@ -0,0 +1,83 @@ +/* +Arduino-MAX30102 oximetry / heart rate integrated sensor library by Shivam Gupta (gupta.shivam1996@gmail.com) + +Based on MAX30100 library, Copyright (C) 2016 OXullo Intersecans +All alogrithms and methods used are from the above author, +I have only modified this enough to make it work with the new MAX30102 sensor. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#include +#include "MAX30102_PulseOximeter.h" + +#define REPORTING_PERIOD_MS 1000 + +// PulseOximeter is the higher level interface to the sensor +// it offers: +// * beat detection reporting +// * heart rate calculation +// * SpO2 (oxidation level) calculation +PulseOximeter pox; + +uint32_t tsLastReport = 0; + +// Callback (registered below) fired when a pulse is detected +void onBeatDetected() +{ + Serial.println("Beat!"); +} + +void setup() +{ + Serial.begin(115200); + + Serial.print("Initializing pulse oximeter.."); + + // Initialize the PulseOximeter instance + // Failures are generally due to an improper I2C wiring, missing power supply + // or wrong target chip + if (!pox.begin()) { + Serial.println("FAILED"); + for(;;); + } else { + Serial.println("SUCCESS"); + } + + // The default current for the IR LED is 50mA and it could be changed + // by uncommenting the following line. Check MAX30102_Registers.h for all the + // available options. + // pox.setIRLedCurrent(MAX30102_LED_CURR_7_6MA); + + // Register a callback for the beat detection + pox.setOnBeatDetectedCallback(onBeatDetected); +} + +void loop() +{ + // Make sure to call update as fast as possible + pox.update(); + + // Asynchronously dump heart rate and oxidation levels to the serial + // For both, a value of 0 means "invalid" + if (millis() - tsLastReport > REPORTING_PERIOD_MS) { + Serial.print("Heart rate:"); + Serial.print(pox.getHeartRate()); + Serial.print("bpm / SpO2:"); + Serial.print(pox.getSpO2()); + Serial.println("%"); + + tsLastReport = millis(); + } +} diff --git a/examples/MAX30102_RawData/MAX30102_RawData.ino b/examples/MAX30102_RawData/MAX30102_RawData.ino new file mode 100644 index 0000000..c1a91de --- /dev/null +++ b/examples/MAX30102_RawData/MAX30102_RawData.ino @@ -0,0 +1,85 @@ +/* +Arduino-MAX30102 oximetry / heart rate integrated sensor library by Shivam Gupta (gupta.shivam1996@gmail.com) + +Based on MAX30100 library, Copyright (C) 2016 OXullo Intersecans +All alogrithms and methods used are from the above author, +I have only modified this enough to make it work with the new MAX30102 sensor. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +// The example shows how to retrieve raw values from the sensor +// experimenting with the most relevant configuration parameters. +// Use the "Serial Plotter" app from arduino IDE 1.6.7+ to plot the output + +#include +#include "MAX30102.h" + +// Sampling is tightly related to the dynamic range of the ADC. +// refer to the datasheet for further info +#define SAMPLING_RATE MAX30102_SAMPRATE_100HZ + +// The LEDs currents must be set to a level that avoids clipping and maximises the +// dynamic range +#define IR_LED_CURRENT 0xff +#define RED_LED_CURRENT 0x88 + +// 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 MAX30102_SPC_PW_1600US_16BITS +#define PULSE_WIDTH MAX30102_SPC_PW_411US_18BITS +#define HIGHRES_MODE true + + +// Instantiate a MAX30102 sensor class +MAX30102 sensor; + +void setup() +{ + Serial.begin(115200); + + Serial.print("Initializing MAX30102.."); + + // Initialize the sensor + // Failures are generally due to an improper I2C wiring, missing power supply + // or wrong target chip + if (!sensor.begin()) { + Serial.println("FAILED"); + for(;;); + } else { + Serial.println("SUCCESS"); + } + + // Set up the wanted parameters + sensor.setMode(MAX30102_MODE_SPO2_HR); + //sensor.setLedsCurrent(IR_LED_CURRENT, RED_LED_CURRENT); + sensor.setIRLedCurrent(IR_LED_CURRENT); + sensor.setRedLedCurrent(RED_LED_CURRENT); + sensor.setLedsPulseWidth(PULSE_WIDTH); + sensor.setSamplingRate(SAMPLING_RATE); + sensor.setRangeADC(MAX30102_ADCRange_16384); +} + +void loop() +{ + uint16_t ir, red; + + sensor.update(); + + while (sensor.getRawValues(&ir, &red)) { + Serial.print(ir); + Serial.print('\t'); + Serial.println(red); + } +} \ No newline at end of file diff --git a/examples/MAX30102_Tester/MAX30102_Tester.ino b/examples/MAX30102_Tester/MAX30102_Tester.ino new file mode 100644 index 0000000..29e8a69 --- /dev/null +++ b/examples/MAX30102_Tester/MAX30102_Tester.ino @@ -0,0 +1,126 @@ +/* +Arduino-MAX30102 oximetry / heart rate integrated sensor library by Shivam Gupta (gupta.shivam1996@gmail.com) + +Based on MAX30100 library, Copyright (C) 2016 OXullo Intersecans +All alogrithms and methods used are from the above author, +I have only modified this enough to make it work with the new MAX30102 sensor. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +// This example can be used to test connectivity and operation of the sensor +// check the README file on the repo's root for a troubleshooting guide in case +// any of the tests running fail + +#include +#include "MAX30102.h" + +MAX30102 sensor; + +void setup() +{ + Serial.begin(115200); + + Serial.print("Initializing MAX30102.."); + + if (!sensor.begin()) { + Serial.print("FAILED: "); + + uint8_t partId = sensor.getPartId(); + if (partId == 0xff) { + Serial.println("I2C error"); + } else { + Serial.print("wrong part ID 0x"); + Serial.print(partId, HEX); + Serial.print(" (expected: 0x"); + Serial.println(EXPECTED_PART_ID, HEX); + } + // Stop here + for(;;); + } else { + Serial.println("Success"); + } + + Serial.print("Enabling HR/SPO2 mode.."); + sensor.setMode(MAX30102_MODE_SPO2_HR); + Serial.println("done."); + + Serial.print("Configuring LEDs biases to 50mA.."); + sensor.setIRLedCurrent(0xff); + sensor.setRedLedCurrent(0xff); + Serial.println("done."); + + delay(1000); + + Serial.print("Lowering the current to 7.6mA.."); + sensor.setIRLedCurrent(0x26); + sensor.setRedLedCurrent(0x26); + //sensor.setLedsCurrent(MAX30102_LED_CURR_7_6MA, MAX30102_LED_CURR_7_6MA); + Serial.println("done."); + + delay(1000); + + Serial.print("Shutting down.."); + sensor.shutdown(); + Serial.println("done."); + + delay(1000); + + Serial.print("Resuming normal operation.."); + sensor.resume(); + delay(500); + Serial.println("done."); + + uint32_t tsTempSampStart = millis(); + Serial.print("Sampling die temperature.."); + sensor.startTemperatureSampling(); + while(!sensor.isTemperatureReady()) { + if (millis() - tsTempSampStart > 1000) { + Serial.println("ERROR: timeout"); + // Stop here + for(;;); + } + } + + float temperature = sensor.retrieveTemperature(); + Serial.print("done, temp="); + Serial.print(temperature); + Serial.println("C"); + + if (temperature < 5) { + Serial.println("WARNING: Temperature probe reported an odd value"); + } else { + Serial.println("All test pass."); + } + + Serial.println(); + Serial.println("Press any key to go into sampling loop mode"); + while (!Serial.available()); + + sensor.resetFifo(); +} + +void loop() +{ + uint16_t ir, red; + + sensor.update(); + + while (sensor.getRawValues(&ir, &red)) { + Serial.print("IR="); + Serial.print(ir); + Serial.print(" RED="); + Serial.println(red); + } +} \ No newline at end of file