Serial monitor read wrong values of an heart rate sensor

Hi! I'm using an Arduino Uno R4 Wifi with a heart rate sensor (DAOKAI MAX30102), but the serial monitor suddenly decided to write wrong values. When there's no finger on the sensor, it writes -1 (which is correct), but when there's the finger it writes 0 or a wrong value (like 20). Can anyone help me?

giusto_range_di_valori.ino (2,0 KB)

Please post your full sketch here, using code tags when you do. This prevents parts of it being interpreted as HTML coding and makes it easier to copy for examination

In my experience the easiest way to tidy up the code and add the code tags is as follows
Start by tidying up your code by using Tools/Auto Format in the IDE to make it easier to read. Then use Edit/Copy for Forum and paste what was copied in a new reply. Code tags will have been added to the code to make it easy to read in the forum thus making it easier to provide help.

Why did you delete the code while I was looking at it?

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

MAX30105 particleSensor;

const byte RATE_SIZE = 4;  //Increase this for more averaging. 4 is good.
byte rates[RATE_SIZE];     //Array of heart rates
byte rateSpot = 0;
long lastBeat = 0;  //Time at which the last beat occurred

float beatsPerMinute;
int beatAvg;

unsigned long int last_beat = 0;

void setup() {
  Serial.begin(115200);
  Serial.println("Initializing...");

  // Initialize sensor
  if (!particleSensor.begin(Wire, I2C_SPEED_FAST)) {
    Serial.println("MAX30102 was not found. Please check wiring/power. ");
    while (1)
      ;
  }
  Serial.println("Place your index finger on the sensor with steady pressure.");

  particleSensor.setup();                     //Configure sensor with default settings
  particleSensor.setPulseAmplitudeRed(0x0A);  //Turn Red LED to low to indicate sensor is running
  particleSensor.setPulseAmplitudeGreen(0);   //Turn off Green LED
}

void loop() {
  long irValue = particleSensor.getIR();

  if (checkForBeat(irValue) == true) {
    //We sensed a beat!
    long delta = millis() - lastBeat;
    lastBeat = millis();

    beatsPerMinute = 60 / (delta / 1000.0);

    if (beatsPerMinute < 255 && beatsPerMinute > 20) {
      rates[rateSpot++] = (byte)beatsPerMinute;  //Store this reading in the array
      rateSpot %= RATE_SIZE;                     //Wrap variable

      //Take average of readings
      beatAvg = 0;
      for (byte x = 0; x < RATE_SIZE; x++)
        beatAvg += rates[x];
      beatAvg /= RATE_SIZE;
    }
  }

  //  Serial.print("IR=");
  //  Serial.print(irValue);
  //  Serial.print(", BPM=");
  //  Serial.print(beatsPerMinute);
  //  Serial.print(", Avg BPM=");
  if (irValue >= 50000)
    Serial.println(beatAvg);

  //  if (millis() - last_beat >= (60000/beatAvg))
  //    {
  //      Serial.println(1);
  //      last_beat = millis();
  //    }
  //Serial.print(beatAvg);

  if (irValue < 50000) {
    Serial.println(-1);
    //beatAvg = 0;
    //Serial.println(0);
  }


  //Serial.println();
}

Sorry. I just re-posted it.

add more Serial.prints and traceback where 0 come from

Ok, I've modified the script in this way

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

MAX30105 particleSensor;

const byte RATE_SIZE = 4; // Increase this for more averaging. 4 is good.
byte rates[RATE_SIZE];    // Array of heart rates
byte rateSpot = 0;
long lastBeat = 0;        // Time at which the last beat occurred

float beatsPerMinute;
int beatAvg;

unsigned long int last_beat = 0;

void setup() {
  Serial.begin(115200);
  Serial.println("Initializing...");

  // Initialize sensor
  if (!particleSensor.begin(Wire, I2C_SPEED_FAST)) {
    Serial.println("MAX30102 was not found. Please check wiring/power.");
    while (1);
  }
  Serial.println("Place your index finger on the sensor with steady pressure.");

  particleSensor.setup(); // Configure sensor with default settings
  particleSensor.setPulseAmplitudeRed(0x0A);  // Turn Red LED to low to indicate sensor is running
  particleSensor.setPulseAmplitudeGreen(0);   // Turn off Green LED
}

void loop() {
  long irValue = particleSensor.getIR();

  // Debug print for IR value
  Serial.print("IR Value: ");
  Serial.println(irValue);

  if (checkForBeat(irValue) == true) {
    // We sensed a beat!
    long delta = millis() - lastBeat;
    lastBeat = millis();

    beatsPerMinute = 60 / (delta / 1000.0);

    // Debug print for beats per minute
    Serial.print("Beats per minute: ");
    Serial.println(beatsPerMinute);

    if (beatsPerMinute < 255 && beatsPerMinute > 20) {
      rates[rateSpot++] = (byte)beatsPerMinute;  // Store this reading in the array
      rateSpot %= RATE_SIZE;  // Wrap variable

      // Take average of readings
      beatAvg = 0;
      Serial.println("Calculating average BPM...");
      for (byte x = 0; x < RATE_SIZE; x++) {
        beatAvg += rates[x];
        // Debug print for each rate value
        Serial.print("Rate ");
        Serial.print(x);
        Serial.print(": ");
        Serial.println(rates[x]);
      }
      beatAvg /= RATE_SIZE;

      // Debug print for average BPM
      Serial.print("Average BPM: ");
      Serial.println(beatAvg);
    }
  }

  if (irValue >= 50000) {
    // Print the average BPM when the IR value is valid
    Serial.print("Valid IR detected, Average BPM: ");
    Serial.println(beatAvg);
  }

  if (irValue < 50000) {
    // When IR value is too low, print -1 and trace back
    Serial.println("Low IR value, printing -1.");
    Serial.println(-1);

    // Debug print to trace if beatAvg might have become 0
    if (beatAvg == 0) {
      Serial.println("Traceback: beatAvg is 0.");
    } else {
      Serial.println("Traceback: beatAvg is not 0.");
    }
  }

  // Optional: Print beatAvg at every iteration for traceability
  Serial.print("Loop end, current beatAvg: ");
  Serial.println(beatAvg);

  delay(1000); // Delay to make output readable
}

When I put the finger on the sensor, the serial monitor prints:

Traceback: beatAvg is 0.
Loop end, current beatAvg: 0
IR Value: 111087
Valid IR detected, Average BPM: 0

I don't know why I have this problem. I tried this script yesterday and it was ok. I tried to change the wires and the sensor, but with no results.

what is checkForBeat(irValue) and where it defined?

It's a function that checks if a heartbeat is detected by analyzing the IR signal's periodic peaks. When a beat is detected, it returns true, allowing the program to proceed with heart rate calculation. It's defined in the "heartRate.h".

ok, try so

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

MAX30105 particleSensor;

const byte RATE_SIZE = 4; // Increase this for more averaging. 4 is good.
byte rates[RATE_SIZE];    // Array of heart rates
byte rateSpot = 0;
long lastBeat = 0;        // Time at which the last beat occurred

float beatsPerMinute;
int beatAvg;

unsigned long int last_beat = 0;

void setup() {
  Serial.begin(115200);
  Serial.println("Initializing...");

  // Initialize sensor
  if (!particleSensor.begin(Wire, I2C_SPEED_FAST)) {
    Serial.println("MAX30102 was not found. Please check wiring/power.");
    while (1);
  }
  Serial.println("Place your index finger on the sensor with steady pressure.");

  particleSensor.setup(); // Configure sensor with default settings
  particleSensor.setPulseAmplitudeRed(0x0A);  // Turn Red LED to low to indicate sensor is running
  particleSensor.setPulseAmplitudeGreen(0);   // Turn off Green LED
}

void loop() {
  long irValue = particleSensor.getIR();

  // Debug print for IR value
  Serial.print("IR Value: ");
  Serial.println(irValue);
  bool Check = checkForBeat(irValue);
  Serial.print("Check: ");
  Serial.println(Check);
  if (Check) {
    // We sensed a beat!
    long delta = millis() - lastBeat;
    lastBeat = millis();
    Serial.print("delta: ");
    Serial.println(delta);
    beatsPerMinute = 60 / (delta / 1000.0);

    // Debug print for beats per minute
    Serial.print("Beats per minute: ");
    Serial.println(beatsPerMinute);

    if (beatsPerMinute < 255 && beatsPerMinute > 20) {
      rates[rateSpot++] = (byte)beatsPerMinute;  // Store this reading in the array
      rateSpot %= RATE_SIZE;  // Wrap variable

      // Take average of readings
      beatAvg = 0;
      Serial.println("Calculating average BPM...");
      for (byte x = 0; x < RATE_SIZE; x++) {
        beatAvg += rates[x];
        // Debug print for each rate value
        Serial.print("Rate ");
        Serial.print(x);
        Serial.print(": ");
        Serial.println(rates[x]);
      }
      beatAvg /= RATE_SIZE;

      // Debug print for average BPM
      Serial.print("Average BPM: ");
      Serial.println(beatAvg);
      if (irValue >= 50000) {
        Serial.print("Valid IR detected");
      }  else {
        Serial.println("Low IR value, printing -1.");
        Serial.println(-1);
      }
    }
  }
  delay(1000); // Delay to make output readable
}

Unfortunately it doesn't solve the problem.

An example of the print with the finger on the sensor:

IR Value: 102442
Check: 0

i said not that it solves the problem, i said "Serial.print guide you to source of 0". you found now

checkForBeat(irValue)

returns always 0. or not always. idk. you need more investigation.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.