Gy MAX30102 Pulse rate sensor's readings don't show up

Hello, for a school project, I am making a device that helps asthma patients by taking readings from 4 sensors and displaying them on an app on the patient's phone and alert them in case of an incoming attack. I am using the ESP32 DevKit V1, and the sensors I'm using are the DHT11, GP2Y10 Dust Sensor, MQ-9, and MAX30102. When I assembled the final prototype, all the sensors seemed to function as intended, with the exception of the gy MAX30102 sensor, which detected whether my finger was on it or not but produced BPM and AvgBPM readings that remained constant. I spoke with an experienced person, and they explained that the delay was the source of the error. They then separated the code for each sensor in the void loop into a separate void function in a different tab of the Arduino IDE and put each void function in a millis function. They advised me to experiment with different delay values. The new code caused the other four sensors' readings to change if I changed the delay in one of the sensors. The deadline for the project is near, so I need to finish this project quickly.

#include <DHT.h>
#include <MQUnifiedsensor.h>
#include <Wire.h>
#include "BluetoothSerial.h"
#include "MAX30105.h"
#include "heartRate.h"

#define Voltage_Resolution 5 //voltage to power MQ-9 sensor
#define operating_voltage 3.3 

#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
#error Bluetooth is not enabled! please run 'make menuconfig' to enable it
#endif

int Dust_measure = 35; // assign pin 35 to Dust sensor's analog pin
int Dust_LED = 32;   // assign pin 32 to Dust sensor's LED's digital pin  
constexpr uint8_t DHT_PIN = 33; // assign pin 33 to DHT11
constexpr uint8_t MQ_PIN = 25; // assign pin 25 to MQ-9 

Resetting the Values measured by Dust sensor
float voMeasured = 0;
float calcVoltage = 0;
float dustDensity = 0;

int sensorADC;
float sensorVoltage;
float sensorDustDensity;
float zeroSensorDustDensity = 0.6; 

int counter = 0; //Counts the number of times the patient recieved an alarm

DHT dht(DHT_PIN, DHT11);
MQUnifiedsensor MQ9("ESP32", Voltage_Resolution, 12, MQ_PIN, "MQ-9");
MAX30105 particleSensor;
BluetoothSerial SerialBT;

float temp = dht.readTemperature();
float humidity = dht.readHumidity();
float CO = MQ9.readSensor();

const byte RATE_SIZE = 4;
byte rates[RATE_SIZE];
byte rateSpot = 0;
long lastBeat = 0;

Variables used by MAX30102
float beatsPerMinute;
int beatAvg;  

// Timer variable to track elapsed time
unsigned long timer = 0;
unsigned long time1 = 0;
unsigned long time2 = 0;
unsigned long time3 = 0;
unsigned long time4 = 0;

void setup() {
  Serial.begin(115200);
  SerialBT.begin("ESP32-Bluetooth");

  pinMode(Dust_LED, OUTPUT);
  digitalWrite(Dust_LED, LOW);

  dht.begin();
  MQ9.setRegressionMethod(1); //_PPM =  a*ratio^b
  MQ9.init();
  
  Serial.print("Calibrating please wait.");
  float calcR0 = 0;
  for (int i = 1; i <= 10; i++) {
    MQ9.update();
    calcR0 += MQ9.calibrate(9.6); // Using RatioMQ9CleanAir value
    Serial.print(".");
  }
  MQ9.setR0(calcR0 / 10);
  Serial.println("  done!.");

  if (isinf(calcR0)) {
    Serial.println("Warning: Connection issue, R0 is infinite (Open circuit detected); please check your wiring and supply");
    while (1);  //Infinite loop to halt the program
  }
  if (calcR0 == 0) {
    Serial.println("Warning: Connection issue found, R0 is zero (Analog pin shorts to ground); please check your wiring and supply");
    while (1);   //Infinite loop to halt the program
  }

  Serial.println("** Values from MQ-9 ****");
  Serial.println("CO  | ");

  // Initialize sensor
  if (!particleSensor.begin(Wire, I2C_SPEED_FAST)) // Use default I2C port, 400kHz speed
  {
    Serial.println("MAX30105 was not found. Please check wiring/power. ");
    while (1);  //Infinite loop to halt the program
  }
  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() {
  unsigned long currentTime = millis() / 1000; //Covert from milliseconds to seconds
  unsigned long currentMillis = millis();

  //Settings the conditions for the prototype
  if(sensorDustDensity >= 35.00){
    SerialBT.print(sensorDustDensity);
    counter++;

  }

  if(temp < 10){
    SerialBT.print(temp);
    counter++;

  }
  else if (temp > 40){
    SerialBT.print(temp);
    counter++;
  }

  if(humidity > 41){
    SerialBT.print(humidity);
    counter++;

  }

  if(beatAvg > 100){
    SerialBT.print(beatAvg);
    counter++;

  }

  if(CO < 100){
    SerialBT.print(CO);
    counter++;
  }

  if (currentTime - timer >= 604800) {

    // Reset the timer
    timer = currentTime;
    // Reset the counter
    counter = 0;

    if (currentMillis - time4 > 10){
      max();
      time4 = currentMillis;
    }
    if (currentMillis - time1 > 500){
      dust();
      time1 = currentMillis;
    }
    if (currentMillis - time2 > 100){
      dht11();
      time2 = currentMillis;
    }
    if (currentMillis - time3 > 100){
      mq9();
      time3 = currentMillis;
    }
  }  
}

the code of each sensor in the separate tab:

void dust ()
{
   for (int i = 0 ; i < 30 ; i++){
    digitalWrite(Dust_LED, HIGH);
    delayMicroseconds(280);
    sensorADC += analogRead(Dust_measure);
    digitalWrite(Dust_LED, LOW);
    delay(10);
  }
  sensorADC = sensorADC / 10;
  sensorVoltage = (operating_voltage / 1024.0) * sensorADC * 11;

  if (sensorVoltage < zeroSensorDustDensity){
    sensorDustDensity = 0;
  }
  else {
    sensorDustDensity = 0.17 * sensorVoltage - 0.1;
  }

  Serial.print(sensorVoltage);
  Serial.print(" ");
  Serial.print(sensorDustDensity);
  Serial.print(" μg/m3 | ");
  SerialBT.print(sensorDustDensity);
}


void mq9 ()
{
  MQ9.update();
  MQ9.setA(599.65);
  MQ9.setB(-2.244);
  float CO = MQ9.readSensor();

  Serial.print("CO: ");
  Serial.print(CO);
  Serial.print(" PPM |");
  SerialBT.print(CO);
}

void dht11 () 
{
    // DHT sensor part
    
  Serial.print(" Temp: ");
  Serial.print(temp);
  Serial.print(" C | ");
  Serial.print("Humidity: ");
  Serial.print(humidity);
  Serial.print(" %  | ");
  SerialBT.print(temp);
  SerialBT.print(humidity);
}


void max () 
{
  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 and 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=" );
  Serial.print(beatAvg);

  if (irValue < 50000 )
    Serial.print( " No finger?" );

  Serial.println();
  SerialBT.print(beatAvg);

}

I suspect that the code has multiple errors because it is not finished yet. I am just waiting to solve this problem first.

It seems you're reading the sensors only once every 604800 seconds - that's once a week. Why is that?

Also why are you changing milliseconds down to seconds? No need for that, just do everything in milliseconds. Otherwise you will also run into issues with rollover of millis(), this is prevented by doing everything in milliseconds.

Then I don't see you call the sensor reading functions in loop(), ever.

Did you test the sensors individually? Do those pieces of code give you the results as expected, when run individually in a simple test setup?

It counts the number of times the user has received alert messages and resets the counter at the end of each week.

Just now realized the error in this part of the code, thank you.

I did test each sensor separately, and they were all fine. I then had ChatGPT combine the code of each sensor into one sketch.

Again, don't use seconds.

Millis() overflows at just over 4 bln counts.
After that happens currentTime becomes smaller than timer, while timer will be at about 3.6 mln. Unsigned integer maths magic will then ensure that currentTime - timer becomes a huge number... and it triggers all the time.
Using millis() all around, you prevent that problem.

How it works - in 8-bit integers for smaller numbers, t1 and t2 each increasing in increments of 60:

t1    t2    result
60  -   0 = 60
120 -  60 = 60
...
240 - 180 = 60
44  - 240 = 60 (!)
104 -  44 = 60 

What happened: 240 + 60 = 300, but the byte can store a maximum value of 255, at 256 it rolls over to 0. Therefore 300 - 256 = 44
44 - 240 = -196, which due to integer representation (the sign bit is lost) becomes 60.

Likewise for the 32-bit millis() counter. As you can see, this breaks if you derive a number divided by 1000.

1 Like

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