Max30100 Refuses to provide data when using blynk with other sensors

Hi everyone,
I am trying to make a project to monitor ECG, Heart Rate and Temperature at the same time and for that I am using DS18B20 Temperature sensor along with ad8232 ECG sensor and MAX30100 Heart rate and SpO2 Monitoring sensor.

The Code works as intended if I print all data to serial but MAX30100 bugs out if I use Blynk, if I comment the lines which call Blynk functions in the loop, MAX30100 prints to serial along with data from other sensors but refuses to do the same with Blynk, I have tried creating a separate function outside loop for updating values on Blynk but the sensor refuses to work that way too, the other two sensors both print data to both serial and send it to the dashboard either way.

It does work if I use only the MAX30100_Minimal example code and add my Blynk code to send only max30100 data to it, there it will send data to both Serial and Blynk.

#define BLYNK_TEMPLATE_ID ""
#define BLYNK_TEMPLATE_NAME ""
#define BLYNK_AUTH_TOKEN ""

#define BLYNK_PRINT Serial

#include <OneWire.h>
#include <DallasTemperature.h>
#include <Wire.h>
#include "MAX30100_PulseOximeter.h"
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>

#define REPORTING_PERIOD_MS 1000
#define ONE_WIRE_BUS 0

char auth[] = "";
char ssid[] = "";
char pass[] = "";

PulseOximeter pox;
uint32_t tsLastReport = 0;


OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
DeviceAddress tempDeviceAddress;

//For Temperature Probe
int resolution = 10;
unsigned long lastTempRequest = 0;
int delayInMillis = 0;
double temperature = 0.0;
int idle = 0;

//Filter For ECG
const int numReadings = 10;  // Number of readings to average
int readings[numReadings];    // Array to store readings
int j = 0;
int total = 0;


void configureMax30100() {
  pox.setIRLedCurrent(MAX30100_LED_CURR_7_6MA);
}

void setup() {
  Serial.begin(115200);

  Blynk.begin(auth, ssid, pass);

  sensors.begin();
  sensors.getAddress(tempDeviceAddress, 0);
  sensors.setResolution(tempDeviceAddress, resolution);

  sensors.setWaitForConversion(false);
  sensors.requestTemperatures();
  delayInMillis = 750 / (1 << (12 - resolution));
  lastTempRequest = millis();

  Serial.print("Initializing pulse oximeter...");

  // Initialize sensor
  if (!pox.begin()) {
    Serial.println("FAILED");
    for (;;);
  } else {
    Serial.println("SUCCESS");
  }

  configureMax30100();
  

  for (int i = 0; i < numReadings; i++) {
    readings[i] = 0;
  }

}

void loop() {
  pox.update();

  int ecgValue = analogRead(A0);
  total -= readings[j];
  readings[j] = ecgValue;
  total += readings[j];
  j = (j + 1) % numReadings;
  int filteredValue = total / numReadings;
  Serial.println(filteredValue);
  Blynk.virtualWrite(V4, temperature);

  if (millis() - lastTempRequest >= 2000) {
    Serial.print("Temperature: ");
    temperature = sensors.getTempCByIndex(0);
    Serial.println(temperature, resolution - 8);
    Blynk.virtualWrite(V3, temperature);

    idle = 0;

    sensors.setResolution(tempDeviceAddress, resolution);
    sensors.requestTemperatures();
    delayInMillis = 750 / (1 << (12 - resolution));
    lastTempRequest = millis();
  }

  idle++;
  
  if (millis() - tsLastReport > REPORTING_PERIOD_MS) {

    Serial.print("Heart rate:");
    Serial.print(pox.getHeartRate());
    Serial.print("bpm / SpO2:");
    Serial.print(pox.getSpO2());
    Serial.println("%");   
    
    Blynk.virtualWrite(V1, pox.getHeartRate());
    Blynk.virtualWrite(V2, pox.getSpO2());

    tsLastReport = millis();
  }
  
  delay(100);
}

Serial output With Blynk code in loop

[6407] Connected to WiFi
[6407] IP: 192.168.211.37
[6407] 
    ___  __          __
   / _ )/ /_ _____  / /__
  / _  / / // / _ \/  '_/
 /____/_/\_, /_//_/_/\_\
        /___/ v1.3.2 on ESP8266

 #StandWithUkraine    https://bit.ly/swua


[6418] Connecting to blynk.cloud:80
[7537] Ready (ping: 69ms).
Initializing pulse oximeter..SUCCESS
Heart rate:0.00bpm / SpO2:0%
[6406] Connected to WiFi
[6406] IP: 192.168.211.37
[6406] 
    ___  __          __
   / _ )/ /_ _____  / /__
  / _  / / // / _ \/  '_/
 /____/_/\_, /_//_/_/\_\
        /___/ v1.3.2 on ESP8266

 #StandWithUkraine    https://bit.ly/swua


[6417] Connecting to blynk.cloud:80
[6581] Ready (ping: 71ms).
Initializing pulse oximeter...SUCCESS
0
Heart rate:0.00bpm / SpO2:0%
0
0
0
0
1
2
4
4
5
4
Heart rate:0.00bpm / SpO2:0%
4
4
4
5
4
3
3
Temperature: 33.75
3
3
Heart rate:0.00bpm / SpO2:0%

Serial output with Blynk code commented in loop

[6406] Connected to WiFi
[6406] IP: 192.168.211.37
[6406] 
    ___  __          __
   / _ )/ /_ _____  / /__
  / _  / / // / _ \/  '_/
 /____/_/\_, /_//_/_/\_\
        /___/ v1.3.2 on ESP8266

 #StandWithUkraine    https://bit.ly/swua


[6417] Connecting to blynk.cloud:80
[6614] Ready (ping: 79ms).
Initializing pulse oximeter...SUCCESS
0
Heart rate:0.00bpm / SpO2:0%
0
0
0
0
1
1
1
2
2
2
Heart rate:0.00bpm / SpO2:0%
2
2
1
1
2
2
1
1
1
2
Temperature: 33.50
Heart rate:12.07bpm / SpO2:0%
2
2
2
2
1
1
2
2
2
2
Heart rate:41.88bpm / SpO2:36%

MAX30100 prints garbage for the first few times and then gets used to it and then provides Good enough data afterwards

You can’t use blocking delays with Blynk, and you should be using BlynkTimer rather than millis() comparisons.
You also can’t have Blynk.virtualWrites in your void loop, and your current code is reading your pox sensor twice as frequently as needed.

You say that you’ve…

but you haven’t shared that code.

Have you looked at other sketches that have been shared on this forum to get some inspiration about how to do this correctly?

Pete.

Thanks for the reply Pete!
I have used BlynkTimer before by Following an older post from different forums but to no avail :(, here’s the code with Serial output, it is pretty much the same as without BlynkTimer

#define BLYNK_TEMPLATE_ID ""
#define BLYNK_TEMPLATE_NAME ""
#define BLYNK_AUTH_TOKEN ""

#define BLYNK_PRINT Serial

#include <OneWire.h>
#include <DallasTemperature.h>
#include <Wire.h>
#include "MAX30100_PulseOximeter.h"
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>

#define REPORTING_PERIOD_MS 1000

char auth[] = "";
char ssid[] = "";
char pass[] = "";

PulseOximeter pox;

#define ONE_WIRE_BUS 0
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

DeviceAddress tempDeviceAddress;

int resolution = 10;
float temperature = 0.0;
int idle = 0;

const int numReadings = 10;  
int readings[numReadings];    
int j = 0;                
int total = 0; 

BlynkTimer timer;

void configureMax30100() {
  pox.setIRLedCurrent(MAX30100_LED_CURR_7_6MA);
}

void setup() {
  Serial.begin(115200);
  sensors.begin();
  sensors.getAddress(tempDeviceAddress, 0);
  sensors.setResolution(tempDeviceAddress, resolution);

  sensors.setWaitForConversion(false);
  sensors.requestTemperatures();

  Serial.print("Initializing pulse oximeter...");

  // Initialize sensor
  if (!pox.begin()) {
    Serial.println("FAILED");
    for (;;);
  } else {
    Serial.println("SUCCESS");
  }

  configureMax30100();

  for (int i = 0; i < numReadings; i++) {
    readings[i] = 0;
  }
  
  Blynk.begin(auth, ssid, pass);
  
  timer.setInterval(2000L, readTemperature);
  
  timer.setInterval(REPORTING_PERIOD_MS, updateMax30100);
}

void loop() {
  Blynk.run();
  pox.update();
  timer.run();

  int ecgValue = analogRead(A0);
  total -= readings[j];
  readings[j] = ecgValue;
  total += readings[j];
  j = (j + 1) % numReadings;
  int filteredValue = total / numReadings;

  Serial.print("ECG Value: ");
  Serial.println(filteredValue);

  Blynk.virtualWrite(V4, filteredValue);
}

void readTemperature() {
  Serial.print("Temperature: ");
  temperature = sensors.getTempCByIndex(0);
  Serial.println(temperature, resolution - 8);

  
  Blynk.virtualWrite(V3, temperature);

  sensors.setResolution(tempDeviceAddress, resolution);
  sensors.requestTemperatures();
}

void updateMax30100() {
  float heartRate = pox.getHeartRate();
  float spO2 = pox.getSpO2();
  Serial.print("Heart rate: ");
  Serial.print(heartRate);
  Serial.print(" bpm / SpO2: ");
  Serial.print(spO2);
  Serial.println(" %");

  Blynk.virtualWrite(V1, heartRate);
  Blynk.virtualWrite(V2, spO2);
}



Serial Console

[6484] Connecting to blynk.cloud:80
[6663] Ready (ping: 79ms).
ECG Value: 0
ECG Value: 1
ECG Value: 1
ECG Value: 1
ECG Value: 1
ECG Value: 1
ECG Value: 2
ECG Value: 3
ECG Value: 3
ECG Value: 3
ECG Value: 3
ECG Value: 2
ECG Value: 3
ECG Value: 3
ECG Value: 3
Heart rate: 0.00 bpm / SpO2: 0.00 %
ECG Value: 3
ECG Value: 6
ECG Value: 6
ECG Value: 5
ECG Value: 6
ECG Value: 6
ECG Value: 5
ECG Value: 5
ECG Value: 5
ECG Value: 5
ECG Value: 5
ECG Value: 1
ECG Value: 2
Temperature: 31.75
Heart rate: 0.00 bpm / SpO2: 0.00 %

You should read this…

And it’s really, really important that you don’t run your latest code without removing this line from your void loop…

Pete.

I created another function to send ECG data only once per second using timer and moved the Blynk.virtualWrite command to it , now the ECG updates slowly (as expected) but MAX30100 still refuses to behave

new loop:

void loop() {
  Blynk.run();
  pox.update();
  timer.run();
}

Serial Output:

[7482] Connecting to blynk.cloud:80
[7760] Ready (ping: 70ms).
Heart rate: 0.00 bpm / SpO2: 0.00 %
ECG Value: 5
Temperature: 31.75
Heart rate: 0.00 bpm / SpO2: 0.00 %
ECG Value: 5
Heart rate: 0.00 bpm / SpO2: 0.00 %
ECG Value: 11

ECG Function

void readECG() {
  
  int ecgValue = analogRead(A0);
  total -= readings[j];
  readings[j] = ecgValue;
  total += readings[j];
  j = (j + 1) % numReadings;
  int filteredValue = total / numReadings;

  Serial.print("ECG Value: ");
  Serial.println(filteredValue);
  Blynk.virtualWrite(V4,filteredValue);
  
}

Timers

  timer.setInterval(2000L, readTemperature);
  timer.setInterval(REPORTING_PERIOD_MS, updateMax30100);
  timer.setInterval(REPORTING_PERIOD_MS, readECG);