The circuit in question is designed to monitor environmental parameters such as temperature, humidity, gas levels, and also includes health monitoring features like heart rate and blood oxygen saturation (SpO2) measurement. The central component of the circuit is an ESP8266 NodeMCU microcontroller, which interfaces with various sensors and modules to collect data and potentially alert the user through a buzzer or vibration motor. The ESP8266 NodeMCU is also equipped with Wi-Fi capabilities, allowing it to connect to the internet and use the Blynk platform for data visualization and remote monitoring.
// Blynk and WiFi credentials
#define BLYNK_TEMPLATE_ID "TMPL308E2KguH"
#define BLYNK_TEMPLATE_NAME "Tempruture and Humidity"
#define BLYNK_AUTH_TOKEN "Lt4kGTEKtDbmMKvszIJ2ACijS7lG3LpN"
#define BLYNK_PRINT Serial
#include <DHT.h>
#include <Wire.h>
#include <Blynk.h>
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <MAX3010x.h>
#include "filters.h"
char auth[] = BLYNK_AUTH_TOKEN;
char ssid[] = "Ananda"; // Change your Wifi/ Hotspot Name
char pass[] = "123456789"; // Change your Wifi/ Hotspot Password
BlynkTimer timer;
// DHT sensor configuration
#define DHTPIN D5
#define DHTTYPE DHT11
int motorPin = D6; // vibration Motor
DHT dht(DHTPIN, DHTTYPE);
#define MQ5 A0
#define buzzer D7
int MQ5_Val = 0;
WidgetLED led(V8);
// MAX30102 sensor configuration
MAX30102 sensor;
const auto kSamplingRate = sensor.SAMPLING_RATE_400SPS;
const float kSamplingFrequency = 400.0;
// Heartbeat detection parameters
const unsigned long kFingerThreshold = 10000;
const unsigned int kFingerCooldownMs = 500;
const float kEdgeThreshold = -2000.0;
// Filters configuration
const float kLowPassCutoff = 5.0;
const float kHighPassCutoff = 0.5;
// Averaging configuration
const bool kEnableAveraging = false;
const int kAveragingSamples = 5;
const int kSampleThreshold = 5;
void setup() {
Serial.begin(9600);
Blynk.begin(auth, ssid, pass);
pinMode(motorPin, OUTPUT);
pinMode(buzzer, OUTPUT);
if(sensor.begin() && sensor.setSamplingRate(kSamplingRate)) {
Serial.println("Sensor initialized");
} else {
Serial.println("Sensor not found");
while(1);
}
dht.begin();
timer.setInterval(1000L, sendSensor);
delay(2000);
timer.setInterval(1000L, mySensor);
}
// Filter Instances
LowPassFilter low_pass_filter_red(kLowPassCutoff, kSamplingFrequency);
LowPassFilter low_pass_filter_ir(kLowPassCutoff, kSamplingFrequency);
HighPassFilter high_pass_filter(kHighPassCutoff, kSamplingFrequency);
Differentiator differentiator(kSamplingFrequency);
MovingAverageFilter<kAveragingSamples> averager_bpm;
MovingAverageFilter<kAveragingSamples> averager_r;
MovingAverageFilter<kAveragingSamples> averager_spo2;
// Statistic for pulse oximetry
MinMaxAvgStatistic stat_red;
MinMaxAvgStatistic stat_ir;
// R value to SpO2 calibration factors
float kSpO2_A = 1.5958422;
float kSpO2_B = -34.6596622;
float kSpO2_C = 112.6898759;
// Timestamps for heartbeat and finger detection
long last_heartbeat = 0;
long finger_timestamp = 0;
bool finger_detected = false;
// Last diff to detect zero crossing
float last_diff = NAN;
bool crossed = false;
long crossed_time = 0;
void loop() {
auto sample = sensor.readSample(1000);
float current_value_red = sample.red;
float current_value_ir = sample.ir;
// Detect Finger using raw sensor value
if(sample.red > kFingerThreshold) {
if(millis() - finger_timestamp > kFingerCooldownMs) {
finger_detected = true;
}
} else {
// Reset values if the finger is removed
differentiator.reset();
averager_bpm.reset();
averager_r.reset();
averager_spo2.reset();
low_pass_filter_red.reset();
low_pass_filter_ir.reset();
high_pass_filter.reset();
stat_red.reset();
stat_ir.reset();
finger_detected = false;
finger_timestamp = millis();
}
if(finger_detected) {
current_value_red = low_pass_filter_red.process(current_value_red);
current_value_ir = low_pass_filter_ir.process(current_value_ir);
// Statistics for pulse oximetry
stat_red.process(current_value_red);
stat_ir.process(current_value_ir);
// Heart beat detection using value for red LED
float current_value = high_pass_filter.process(current_value_red);
float current_diff = differentiator.process(current_value);
// Valid values?
if(!isnan(current_diff) && !isnan(last_diff)) {
// Detect Heartbeat - Zero-Crossing
if(last_diff > 0 && current_diff < 0) {
crossed = true;
crossed_time = millis();
}
if(current_diff > 0) {
crossed = false;
}
// Detect Heartbeat - Falling Edge Threshold
if(crossed && current_diff < kEdgeThreshold) {
if(last_heartbeat != 0 && crossed_time - last_heartbeat > 300) {
// Show Results
int bpm = 60000/(crossed_time - last_heartbeat);
float rred = (stat_red.maximum()-stat_red.minimum())/stat_red.average();
float rir = (stat_ir.maximum()-stat_ir.minimum())/stat_ir.average();
float r = rred/rir;
float spo2 = kSpO2_A * r * r + kSpO2_B * r + kSpO2_C;
if(bpm > 50 && bpm < 250) {
// Average?
if(kEnableAveraging) {
int average_bpm = averager_bpm.process(bpm);
int average_r = averager_r.process(r);