Post Go back to editing

Read the MAX30102 data to -999,Request help

Category: Software

The program code is as follows:

int main(void)
{
/* USER CODE BEGIN 1 */

char ach_i2c_data1[6];

uint32_t un_min, un_max, un_prev_data;
int i;
int32_t n_brightness;
float f_temp;
uint8_t temp_num=0;
uint8_t temp[6];
uint8_t str[100];

/* USER CODE END 1 */

/* MCU Configuration--------------------------------------------------------*/

/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();

/* USER CODE BEGIN Init */

/* USER CODE END Init */

/* Configure the system clock */
SystemClock_Config();

/* USER CODE BEGIN SysInit */

/* USER CODE END SysInit */

/* Initialize all configured peripherals */
MX_GPIO_Init();
/* USER CODE BEGIN 2 */

IIC_Init();

if(maxim_max30102_reset())//复位 MAX30102
{}
// printf("max30102_reset failed!\r\n");
if(maxim_max30102_read_reg(REG_INTR_STATUS_1,&uch_dummy))//read and clear status register
{}
// printf("read_reg REG_INTR_STATUS_1 failed!\r\n");
if(maxim_max30102_init())//初始化MAX30102
{}
// printf("max30102_init failed!\r\n");

id = max30102_Bus_Read(REG_PART_ID); //Read ID is normal  OK



/* USER CODE END 2 */

/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */

/* USER CODE BEGIN 3 */
un_min=0x3FFFF;
un_max=0;
unsigned char uch_temp;

//read the first 100 samples, and determine the signal range
for (i = 0; i < BUFFER_SIZE; i++)
{
while (HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_15)== GPIO_PIN_SET) ;
// ff = max30102_Bus_Read(REG_INTR_STATUS_1);
// while(ff & 0x40 != 0X40);

maxim_max30102_read_fifo((aun_red_buffer + i), ( aun_ir_buffer + i)); //read from MAX30102 FIFO

if(un_min>aun_red_buffer[i])
un_min=aun_red_buffer[i]; //update signal min
if(un_max<aun_red_buffer[i])
un_max=aun_red_buffer[i]; //update signal max
}

//calculate heart rate and SpO2 after first 100 samples (first 4 seconds of samples)
rf_heart_rate_and_oxygen_saturation(aun_ir_buffer, BUFFER_SIZE, aun_red_buffer, &n_spo2, &ch_spo2_valid, &n_heart_rate, &ch_hr_valid, &ratio, &correl);

while(1)
{
i=0;
un_min=0x3FFFF;
un_max=0;

//dumping the first 100 sets of samples in the memory and shift the last 400 sets of samples to the top
for (i = 25; i < 100; i++)
{
aun_red_buffer[i - 25] = aun_red_buffer[i];
aun_ir_buffer[i - 25] = aun_ir_buffer[i];

//update the signal min and max
if(un_min>aun_red_buffer[i])
un_min=aun_red_buffer[i];
if(un_max<aun_red_buffer[i])
un_max=aun_red_buffer[i];
}

//take 25 sets of samples before calculating the heart rate.
for (i = 75; i < 100; i++)
{

while (HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_15)== GPIO_PIN_SET ) ;
// ff = max30102_Bus_Read(REG_INTR_STATUS_1);
// while(ff & 0x40 != 0X40);
maxim_max30102_read_fifo((aun_red_buffer + i), ( aun_ir_buffer + i));//read from MAX30102 FIFO
}

rf_heart_rate_and_oxygen_saturation(aun_ir_buffer, BUFFER_SIZE, aun_red_buffer, &n_spo2, &ch_spo2_valid, &n_heart_rate, &ch_hr_valid, &ratio, &correl);



}


}
/* USER CODE END 3 */
}

int8_t maxim_max30102_init(void)
{


max30102_Bus_Write(REG_MODE_CONFIG,0x40);
HAL_Delay(20);

max30102_Bus_Write(REG_INTR_ENABLE_1,0xc0); // INTR setting 不使用接近功能,SPO2与HR理解开始
max30102_Bus_Write(REG_INTR_ENABLE_2,0x00);

max30102_Bus_Write(REG_FIFO_WR_PTR,0x00); //FIFO_WR_PTR[4:0]
max30102_Bus_Write(REG_OVF_COUNTER,0x00); //OVF_COUNTER[4:0]
max30102_Bus_Write(REG_FIFO_RD_PTR,0x00); //FIFO_RD_PTR[4:0]

max30102_Bus_Write(REG_FIFO_CONFIG,0x0f); //sample avg = 1, fifo rollover=false, fifo almost full = 17
max30102_Bus_Write(REG_MODE_CONFIG,0x03); //0x02 for Red only, 0x03 for SpO2 mode 0x07 multimode LED
max30102_Bus_Write(REG_SPO2_CONFIG,0x27); // SPO2_ADC range = 4096nA, SPO2 sample rate (100 Hz), LED pulseWidth (400uS)
max30102_Bus_Write(REG_LED1_PA,0x24); //Choose value for ~ 7mA for LED1
max30102_Bus_Write(REG_LED2_PA,0x24); // Choose value for ~ 7mA for LED2
max30102_Bus_Write(REG_PILOT_PA,0x7f); // Choose value for ~ 25mA for Pilot LED

max30102_Bus_Write(REG_TEMP_CONFIG,0X01);

max30102_Bus_Read(REG_INTR_STATUS_1);
max30102_Bus_Read(REG_INTR_STATUS_2);

}

The following is a logic analyzer waveform diagram:

0 ----INT

1 ---SDA

2 ---SCL

THANKS!

Parents
  • Hi, please can you tell me how the code is working? I use the "sparkfun electronics" code which is available in arduino library. I use that code but it is not working with MAX30102 sensor. data read and value is generation complete but the SPO2 values are hang around 100,99,98 only and the heart rate values are 150-160 approx. I paste the code here.

    "max30105.h file" -> work on both MAX30105 and Max30102 as per the "sparkfun" statement

    /***************************************************
     This is a library written for the Maxim MAX30105 Optical Smoke Detector
     It should also work with the MAX30102. However, the MAX30102 does not have a Green LED.

     These sensors use I2C to communicate, as well as a single (optional)
     interrupt line that is not currently supported in this driver.
     
     Written by Peter Jansen and Nathan Seidle (SparkFun)
     BSD license, all text above must be included in any redistribution.
     *****************************************************/

    #pragma once

    #if (ARDUINO >= 100)
     #include "Arduino.h"
    #else
     #include "WProgram.h"
    #endif

    #include <Wire.h>

    #define MAX30105_ADDRESS          0x57 //7-bit I2C Address
    //Note that MAX30102 has the same I2C address and Part ID

    #define I2C_SPEED_STANDARD        100000
    #define I2C_SPEED_FAST            400000

    //Define the size of the I2C buffer based on the platform the user has
    #if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__)

      //I2C_BUFFER_LENGTH is defined in Wire.H
      #define I2C_BUFFER_LENGTH BUFFER_LENGTH

    #elif defined(__SAMD21G18A__)

      //SAMD21 uses RingBuffer.h
      #define I2C_BUFFER_LENGTH SERIAL_BUFFER_SIZE

    #else

      //The catch-all default is 32
      #define I2C_BUFFER_LENGTH 32

    #endif

    class MAX30105 {
     public:
      MAX30105(void);

      boolean begin(TwoWire &wirePort = Wire, uint32_t i2cSpeed = I2C_SPEED_STANDARD, uint8_t i2caddr = MAX30105_ADDRESS);

      uint32_t getRed(void); //Returns immediate red value
      uint32_t getIR(void); //Returns immediate IR value
      uint32_t getGreen(void); //Returns immediate green value
      bool safeCheck(uint8_t maxTimeToCheck); //Given a max amount of time, check for new data

      // Configuration
      void softReset();
      void shutDown();
      void wakeUp();

      void setLEDMode(uint8_t mode);

      void setADCRange(uint8_t adcRange);
      void setSampleRate(uint8_t sampleRate);
      void setPulseWidth(uint8_t pulseWidth);

      void setPulseAmplitudeRed(uint8_t value);
      void setPulseAmplitudeIR(uint8_t value);
      void setPulseAmplitudeGreen(uint8_t value);
      void setPulseAmplitudeProximity(uint8_t value);

      void setProximityThreshold(uint8_t threshMSB);

      //Multi-led configuration mode (page 22)
      void enableSlot(uint8_t slotNumber, uint8_t device); //Given slot number, assign a device to slot
      void disableSlots(void);
     
      // Data Collection

      //Interrupts (page 13, 14)
      uint8_t getINT1(void); //Returns the main interrupt group
      uint8_t getINT2(void); //Returns the temp ready interrupt
      void enableAFULL(void); //Enable/disable individual interrupts
      void disableAFULL(void);
      void enableDATARDY(void);
      void disableDATARDY(void);
      void enableALCOVF(void);
      void disableALCOVF(void);
      void enablePROXINT(void);
      void disablePROXINT(void);
      void enableDIETEMPRDY(void);
      void disableDIETEMPRDY(void);

      //FIFO Configuration (page 18)
      void setFIFOAverage(uint8_t samples);
      void enableFIFORollover();
      void disableFIFORollover();
      void setFIFOAlmostFull(uint8_t samples);
     
      //FIFO Reading
      uint16_t check(void); //Checks for new data and fills FIFO
      uint8_t available(void); //Tells caller how many new samples are available (head - tail)
      void nextSample(void); //Advances the tail of the sense array
      uint32_t getFIFORed(void); //Returns the FIFO sample pointed to by tail
      uint32_t getFIFOIR(void); //Returns the FIFO sample pointed to by tail
      uint32_t getFIFOGreen(void); //Returns the FIFO sample pointed to by tail

      uint8_t getWritePointer(void);
      uint8_t getReadPointer(void);
      void clearFIFO(void); //Sets the read/write pointers to zero

      //Proximity Mode Interrupt Threshold
      void setPROXINTTHRESH(uint8_t val);

      // Die Temperature
      float readTemperature();
      float readTemperatureF();

      // Detecting ID/Revision
      uint8_t getRevisionID();
      uint8_t readPartID();  

      // Setup the IC with user selectable settings
      void setup(byte powerLevel = 0x1F, byte sampleAverage = 4, byte ledMode = 3, int sampleRate = 400, int pulseWidth = 411, int adcRange = 4096);

      // Low-level I2C communication
      uint8_t readRegister8(uint8_t address, uint8_t reg);
      void writeRegister8(uint8_t address, uint8_t reg, uint8_t value);

     private:
      TwoWire *_i2cPort; //The generic connection to user's chosen I2C hardware
      uint8_t _i2caddr;

      //activeLEDs is the number of channels turned on, and can be 1 to 3. 2 is common for Red+IR.
      byte activeLEDs; //Gets set during setup. Allows check() to calculate how many bytes to read from FIFO
     
      uint8_t revisionID;

      void readRevisionID();

      void bitMask(uint8_t reg, uint8_t mask, uint8_t thing);
     
       #define STORAGE_SIZE 4 //Each long is 4 bytes so limit this to fit on your micro
      typedef struct Record
      {
        uint32_t red[STORAGE_SIZE];
        uint32_t IR[STORAGE_SIZE];
        uint32_t green[STORAGE_SIZE];
        byte head;
        byte tail;
      } sense_struct; //This is our circular buffer of readings from the sensor

      sense_struct sense;

    };
    This is the C code
    /*
      Optical SP02 Detection (SPK Algorithm) using the MAX30105 Breakout
      By: Nathan Seidle @ SparkFun Electronics
      Date: October 19th, 2016

      This demo shows heart rate and SPO2 levels.

      It is best to attach the sensor to your finger using a rubber band or other tightening
      device. Humans are generally bad at applying constant pressure to a thing. When you
      press your finger against the sensor it varies enough to cause the blood in your
      finger to flow differently which causes the sensor readings to go wonky.

      This example is based on MAXREFDES117 and RD117_LILYPAD.ino from Maxim. Their example
      was modified to work with the SparkFun MAX30105 library and to compile under Arduino 1.6.11
      Please see license file for more info.

      Hardware Connections (Breakoutboard to Arduino):
      -5V = 5V (3.3V is allowed)
      -GND = GND
      -SDA = A4 (or SDA)
      -SCL = A5 (or SCL)
      -INT = Not connected
     
      The MAX30105 Breakout can handle 5V or 3.3V I2C logic. We recommend powering the board with 5V
      but it will also run at 3.3V.
    */

    #include <Wire.h>
    #include "MAX30105.h"
    #include "spo2_algorithm.h"

    MAX30105 particleSensor;

    #define MAX_BRIGHTNESS 255

    #if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__)
    //Arduino Uno doesn't have enough SRAM to store 100 samples of IR led data and red led data in 32-bit format
    //To solve this problem, 16-bit MSB of the sampled data will be truncated. Samples become 16-bit data.
    uint16_t irBuffer[100]; //infrared LED sensor data
    uint16_t redBuffer[100];  //red LED sensor data
    #else
    uint32_t irBuffer[100]; //infrared LED sensor data
    uint32_t redBuffer[100];  //red LED sensor data
    #endif

    int32_t bufferLength; //data length
    int32_t spo2; //SPO2 value
    int8_t validSPO2; //indicator to show if the SPO2 calculation is valid
    int32_t heartRate; //heart rate value
    int8_t validHeartRate; //indicator to show if the heart rate calculation is valid

    byte pulseLED = 22; //Must be on PWM pin
    byte readLED = 21; //Blinks with each data read

    void setup()
    {
      Serial.begin(115200); // initialize serial communication at 115200 bits per second:

      pinMode(pulseLED, OUTPUT);
      pinMode(readLED, OUTPUT);

      // Initialize sensor
      if (!particleSensor.begin(Wire, 400000)) //Use default I2C port, 400kHz speed
      {
        Serial.println(F("MAX30105 was not found. Please check wiring/power."));
        while (1);
      }

      Serial.println(F("Attach sensor to finger with rubber band. Press any key to start conversion"));
      while (Serial.available() == 0) ; //wait until user presses a key
      Serial.read();

      byte ledBrightness = 60; //Options: 0=Off to 255=50mA
      byte sampleAverage = 8; //Options: 1, 2, 4, 8, 16, 32
      byte ledMode = 2; //Options: 1 = Red only, 2 = Red + IR, 3 = Red + IR + Green
      byte sampleRate = 100; //Options: 50, 100, 200, 400, 800, 1000, 1600, 3200
      int pulseWidth = 411; //Options: 69, 118, 215, 411
      int adcRange = 4096; //Options: 2048, 4096, 8192, 16384

      particleSensor.setup(ledBrightness, sampleAverage, ledMode, sampleRate, pulseWidth, adcRange); //Configure sensor with these settings
    }

    void loop()
    {
      bufferLength = 100; //buffer length of 100 stores 4 seconds of samples running at 25sps

      //read the first 100 samples, and determine the signal range
      for (byte i = 0 ; i < bufferLength ; i++)
      {
        while (particleSensor.available() == false) //do we have new data?
          particleSensor.check(); //Check the sensor for new data

        redBuffer[i] = particleSensor.getRed();
        irBuffer[i] = particleSensor.getIR();
        particleSensor.nextSample(); //We're finished with this sample so move to next sample

        Serial.print(F("red="));
        Serial.print(redBuffer[i], DEC);
        Serial.print(F(", ir="));
        Serial.println(irBuffer[i], DEC);
      }

      //calculate heart rate and SpO2 after first 100 samples (first 4 seconds of samples)
      maxim_heart_rate_and_oxygen_saturation(irBuffer, bufferLength, redBuffer, &spo2, &validSPO2, &heartRate, &validHeartRate);

      //Continuously taking samples from MAX30102.  Heart rate and SpO2 are calculated every 1 second
      while (1)
      {
        //dumping the first 25 sets of samples in the memory and shift the last 75 sets of samples to the top
        for (byte i = 25; i < 100; i++)
        {
          redBuffer[i - 25] = redBuffer[i];
          irBuffer[i - 25] = irBuffer[i];
        }

        //take 25 sets of samples before calculating the heart rate.
        for (byte i = 75; i < 100; i++)
        {
          while (particleSensor.available() == false) //do we have new data?
            particleSensor.check(); //Check the sensor for new data

          digitalWrite(readLED, !digitalRead(readLED)); //Blink onboard LED with every data read

          redBuffer[i] = particleSensor.getRed();
          irBuffer[i] = particleSensor.getIR();
          particleSensor.nextSample(); //We're finished with this sample so move to next sample

          //send samples and calculation result to terminal program through UART
          Serial.print(F("red="));
          Serial.print(redBuffer[i], DEC);
          Serial.print(F(", ir="));
          Serial.print(irBuffer[i], DEC);

          Serial.print(F(", HR="));
          Serial.print(heartRate, DEC);

          Serial.print(F(", HRvalid="));
          Serial.print(validHeartRate, DEC);

          Serial.print(F(", SPO2="));
          Serial.print(spo2, DEC);

          Serial.print(F(", SPO2Valid="));
          Serial.println(validSPO2, DEC);
        }

        //After gathering 25 new samples recalculate HR and SP02
        maxim_heart_rate_and_oxygen_saturation(irBuffer, bufferLength, redBuffer, &spo2, &validSPO2, &heartRate, &validHeartRate);
      }
    }

    If you know what's wrong then please tell me
Reply
  • Hi, please can you tell me how the code is working? I use the "sparkfun electronics" code which is available in arduino library. I use that code but it is not working with MAX30102 sensor. data read and value is generation complete but the SPO2 values are hang around 100,99,98 only and the heart rate values are 150-160 approx. I paste the code here.

    "max30105.h file" -> work on both MAX30105 and Max30102 as per the "sparkfun" statement

    /***************************************************
     This is a library written for the Maxim MAX30105 Optical Smoke Detector
     It should also work with the MAX30102. However, the MAX30102 does not have a Green LED.

     These sensors use I2C to communicate, as well as a single (optional)
     interrupt line that is not currently supported in this driver.
     
     Written by Peter Jansen and Nathan Seidle (SparkFun)
     BSD license, all text above must be included in any redistribution.
     *****************************************************/

    #pragma once

    #if (ARDUINO >= 100)
     #include "Arduino.h"
    #else
     #include "WProgram.h"
    #endif

    #include <Wire.h>

    #define MAX30105_ADDRESS          0x57 //7-bit I2C Address
    //Note that MAX30102 has the same I2C address and Part ID

    #define I2C_SPEED_STANDARD        100000
    #define I2C_SPEED_FAST            400000

    //Define the size of the I2C buffer based on the platform the user has
    #if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__)

      //I2C_BUFFER_LENGTH is defined in Wire.H
      #define I2C_BUFFER_LENGTH BUFFER_LENGTH

    #elif defined(__SAMD21G18A__)

      //SAMD21 uses RingBuffer.h
      #define I2C_BUFFER_LENGTH SERIAL_BUFFER_SIZE

    #else

      //The catch-all default is 32
      #define I2C_BUFFER_LENGTH 32

    #endif

    class MAX30105 {
     public:
      MAX30105(void);

      boolean begin(TwoWire &wirePort = Wire, uint32_t i2cSpeed = I2C_SPEED_STANDARD, uint8_t i2caddr = MAX30105_ADDRESS);

      uint32_t getRed(void); //Returns immediate red value
      uint32_t getIR(void); //Returns immediate IR value
      uint32_t getGreen(void); //Returns immediate green value
      bool safeCheck(uint8_t maxTimeToCheck); //Given a max amount of time, check for new data

      // Configuration
      void softReset();
      void shutDown();
      void wakeUp();

      void setLEDMode(uint8_t mode);

      void setADCRange(uint8_t adcRange);
      void setSampleRate(uint8_t sampleRate);
      void setPulseWidth(uint8_t pulseWidth);

      void setPulseAmplitudeRed(uint8_t value);
      void setPulseAmplitudeIR(uint8_t value);
      void setPulseAmplitudeGreen(uint8_t value);
      void setPulseAmplitudeProximity(uint8_t value);

      void setProximityThreshold(uint8_t threshMSB);

      //Multi-led configuration mode (page 22)
      void enableSlot(uint8_t slotNumber, uint8_t device); //Given slot number, assign a device to slot
      void disableSlots(void);
     
      // Data Collection

      //Interrupts (page 13, 14)
      uint8_t getINT1(void); //Returns the main interrupt group
      uint8_t getINT2(void); //Returns the temp ready interrupt
      void enableAFULL(void); //Enable/disable individual interrupts
      void disableAFULL(void);
      void enableDATARDY(void);
      void disableDATARDY(void);
      void enableALCOVF(void);
      void disableALCOVF(void);
      void enablePROXINT(void);
      void disablePROXINT(void);
      void enableDIETEMPRDY(void);
      void disableDIETEMPRDY(void);

      //FIFO Configuration (page 18)
      void setFIFOAverage(uint8_t samples);
      void enableFIFORollover();
      void disableFIFORollover();
      void setFIFOAlmostFull(uint8_t samples);
     
      //FIFO Reading
      uint16_t check(void); //Checks for new data and fills FIFO
      uint8_t available(void); //Tells caller how many new samples are available (head - tail)
      void nextSample(void); //Advances the tail of the sense array
      uint32_t getFIFORed(void); //Returns the FIFO sample pointed to by tail
      uint32_t getFIFOIR(void); //Returns the FIFO sample pointed to by tail
      uint32_t getFIFOGreen(void); //Returns the FIFO sample pointed to by tail

      uint8_t getWritePointer(void);
      uint8_t getReadPointer(void);
      void clearFIFO(void); //Sets the read/write pointers to zero

      //Proximity Mode Interrupt Threshold
      void setPROXINTTHRESH(uint8_t val);

      // Die Temperature
      float readTemperature();
      float readTemperatureF();

      // Detecting ID/Revision
      uint8_t getRevisionID();
      uint8_t readPartID();  

      // Setup the IC with user selectable settings
      void setup(byte powerLevel = 0x1F, byte sampleAverage = 4, byte ledMode = 3, int sampleRate = 400, int pulseWidth = 411, int adcRange = 4096);

      // Low-level I2C communication
      uint8_t readRegister8(uint8_t address, uint8_t reg);
      void writeRegister8(uint8_t address, uint8_t reg, uint8_t value);

     private:
      TwoWire *_i2cPort; //The generic connection to user's chosen I2C hardware
      uint8_t _i2caddr;

      //activeLEDs is the number of channels turned on, and can be 1 to 3. 2 is common for Red+IR.
      byte activeLEDs; //Gets set during setup. Allows check() to calculate how many bytes to read from FIFO
     
      uint8_t revisionID;

      void readRevisionID();

      void bitMask(uint8_t reg, uint8_t mask, uint8_t thing);
     
       #define STORAGE_SIZE 4 //Each long is 4 bytes so limit this to fit on your micro
      typedef struct Record
      {
        uint32_t red[STORAGE_SIZE];
        uint32_t IR[STORAGE_SIZE];
        uint32_t green[STORAGE_SIZE];
        byte head;
        byte tail;
      } sense_struct; //This is our circular buffer of readings from the sensor

      sense_struct sense;

    };
    This is the C code
    /*
      Optical SP02 Detection (SPK Algorithm) using the MAX30105 Breakout
      By: Nathan Seidle @ SparkFun Electronics
      Date: October 19th, 2016

      This demo shows heart rate and SPO2 levels.

      It is best to attach the sensor to your finger using a rubber band or other tightening
      device. Humans are generally bad at applying constant pressure to a thing. When you
      press your finger against the sensor it varies enough to cause the blood in your
      finger to flow differently which causes the sensor readings to go wonky.

      This example is based on MAXREFDES117 and RD117_LILYPAD.ino from Maxim. Their example
      was modified to work with the SparkFun MAX30105 library and to compile under Arduino 1.6.11
      Please see license file for more info.

      Hardware Connections (Breakoutboard to Arduino):
      -5V = 5V (3.3V is allowed)
      -GND = GND
      -SDA = A4 (or SDA)
      -SCL = A5 (or SCL)
      -INT = Not connected
     
      The MAX30105 Breakout can handle 5V or 3.3V I2C logic. We recommend powering the board with 5V
      but it will also run at 3.3V.
    */

    #include <Wire.h>
    #include "MAX30105.h"
    #include "spo2_algorithm.h"

    MAX30105 particleSensor;

    #define MAX_BRIGHTNESS 255

    #if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__)
    //Arduino Uno doesn't have enough SRAM to store 100 samples of IR led data and red led data in 32-bit format
    //To solve this problem, 16-bit MSB of the sampled data will be truncated. Samples become 16-bit data.
    uint16_t irBuffer[100]; //infrared LED sensor data
    uint16_t redBuffer[100];  //red LED sensor data
    #else
    uint32_t irBuffer[100]; //infrared LED sensor data
    uint32_t redBuffer[100];  //red LED sensor data
    #endif

    int32_t bufferLength; //data length
    int32_t spo2; //SPO2 value
    int8_t validSPO2; //indicator to show if the SPO2 calculation is valid
    int32_t heartRate; //heart rate value
    int8_t validHeartRate; //indicator to show if the heart rate calculation is valid

    byte pulseLED = 22; //Must be on PWM pin
    byte readLED = 21; //Blinks with each data read

    void setup()
    {
      Serial.begin(115200); // initialize serial communication at 115200 bits per second:

      pinMode(pulseLED, OUTPUT);
      pinMode(readLED, OUTPUT);

      // Initialize sensor
      if (!particleSensor.begin(Wire, 400000)) //Use default I2C port, 400kHz speed
      {
        Serial.println(F("MAX30105 was not found. Please check wiring/power."));
        while (1);
      }

      Serial.println(F("Attach sensor to finger with rubber band. Press any key to start conversion"));
      while (Serial.available() == 0) ; //wait until user presses a key
      Serial.read();

      byte ledBrightness = 60; //Options: 0=Off to 255=50mA
      byte sampleAverage = 8; //Options: 1, 2, 4, 8, 16, 32
      byte ledMode = 2; //Options: 1 = Red only, 2 = Red + IR, 3 = Red + IR + Green
      byte sampleRate = 100; //Options: 50, 100, 200, 400, 800, 1000, 1600, 3200
      int pulseWidth = 411; //Options: 69, 118, 215, 411
      int adcRange = 4096; //Options: 2048, 4096, 8192, 16384

      particleSensor.setup(ledBrightness, sampleAverage, ledMode, sampleRate, pulseWidth, adcRange); //Configure sensor with these settings
    }

    void loop()
    {
      bufferLength = 100; //buffer length of 100 stores 4 seconds of samples running at 25sps

      //read the first 100 samples, and determine the signal range
      for (byte i = 0 ; i < bufferLength ; i++)
      {
        while (particleSensor.available() == false) //do we have new data?
          particleSensor.check(); //Check the sensor for new data

        redBuffer[i] = particleSensor.getRed();
        irBuffer[i] = particleSensor.getIR();
        particleSensor.nextSample(); //We're finished with this sample so move to next sample

        Serial.print(F("red="));
        Serial.print(redBuffer[i], DEC);
        Serial.print(F(", ir="));
        Serial.println(irBuffer[i], DEC);
      }

      //calculate heart rate and SpO2 after first 100 samples (first 4 seconds of samples)
      maxim_heart_rate_and_oxygen_saturation(irBuffer, bufferLength, redBuffer, &spo2, &validSPO2, &heartRate, &validHeartRate);

      //Continuously taking samples from MAX30102.  Heart rate and SpO2 are calculated every 1 second
      while (1)
      {
        //dumping the first 25 sets of samples in the memory and shift the last 75 sets of samples to the top
        for (byte i = 25; i < 100; i++)
        {
          redBuffer[i - 25] = redBuffer[i];
          irBuffer[i - 25] = irBuffer[i];
        }

        //take 25 sets of samples before calculating the heart rate.
        for (byte i = 75; i < 100; i++)
        {
          while (particleSensor.available() == false) //do we have new data?
            particleSensor.check(); //Check the sensor for new data

          digitalWrite(readLED, !digitalRead(readLED)); //Blink onboard LED with every data read

          redBuffer[i] = particleSensor.getRed();
          irBuffer[i] = particleSensor.getIR();
          particleSensor.nextSample(); //We're finished with this sample so move to next sample

          //send samples and calculation result to terminal program through UART
          Serial.print(F("red="));
          Serial.print(redBuffer[i], DEC);
          Serial.print(F(", ir="));
          Serial.print(irBuffer[i], DEC);

          Serial.print(F(", HR="));
          Serial.print(heartRate, DEC);

          Serial.print(F(", HRvalid="));
          Serial.print(validHeartRate, DEC);

          Serial.print(F(", SPO2="));
          Serial.print(spo2, DEC);

          Serial.print(F(", SPO2Valid="));
          Serial.println(validSPO2, DEC);
        }

        //After gathering 25 new samples recalculate HR and SP02
        maxim_heart_rate_and_oxygen_saturation(irBuffer, bufferLength, redBuffer, &spo2, &validSPO2, &heartRate, &validHeartRate);
      }
    }

    If you know what's wrong then please tell me
Children
No Data