Cirkit Designer LogoCirkit DesignerYour all-in-one circuit design IDE Launch Cirkit Designer App

ESP32-Based Health Monitoring System with Wi-Fi Connectivity

View and Edit Project In Cirkit DesignerImage of ESP32-Based Health Monitoring System with Wi-Fi Connectivity

Health Monitoring System Documentation

Summary

This document provides a detailed overview of a health monitoring system circuit. The system utilizes an ESP32 microcontroller to read data from various sensors, including a pulse sensor, an LM35 temperature sensor, a DHT22 temperature and humidity sensor, and a MAX30102 heart rate and SpO2 sensor. The collected data is printed to the Serial Monitor.

Component List

  1. ESP32-WROOM-32UE

    • Description: A powerful microcontroller with Wi-Fi and Bluetooth capabilities.
    • Pins: 3v3, EN, VP, VN, 34, 35, 32, 33, 25, 26, 27, 14, 12, GND, 13, D2, D3, 5V, 23, 22, TX, RX, 21, 19, 18, 5, 17, 16, 4, 0, 2, 15, D1, D0, CKL
  2. DHT22

    • Description: A digital temperature and humidity sensor.
    • Pins: +, Out, -
  3. Temperature Sensor (LM35)

    • Description: An analog temperature sensor.
    • Pins: +Vs, Vout, GND
  4. Heartbeat Sensor

    • Description: A sensor to measure heartbeats.
    • Pins: S, VCC, GND
  5. MAX30102 HR + SpO2 Sensor

    • Description: A sensor to measure heart rate and SpO2 levels.
    • Pins: INT, IRD, RD, GND, SCL, SDA, VIN

Wiring Details

ESP32-WROOM-32UE

DHT22

Temperature Sensor (LM35)

Heartbeat Sensor

MAX30102 HR + SpO2 Sensor

Code Documentation

/*
 * Health Monitoring System
 * This Arduino sketch reads data from various sensors connected to an ESP32.
 * Sensors include: Pulse Sensor, LM35 Temperature Sensor, DHT22 Temp & Humidity
 * Sensor, and MAX30102 Heart Rate & SpO2 Sensor.
 * Data is printed to the Serial Monitor.
 */

#define BLYNK_TEMPLATE_ID "TMP75fhjk4WcJ0G"
#define BLYNK_TEMPLATE_NAME "Health Monitoring System"
#define BLYNK_AUTH_TOKEN "2u_OY_ix532dYnEujhgfYE-I7w_HnwtZ"
char ssid[] = "Anil Gupta";
char pass[] = "dhklklk1";

#define USE_ARDUINO_INTERRUPTS true
#include <PulseSensorPlayground.h>
#include <Adafruit_Sensor.h>
#include <DHT.h>
#include <DHT_U.h>
#include <Wire.h>
#include "MAX30105.h"
#include "spo2_algorithm.h"

const int PulseWire = 36;
int Threshold = 550;
PulseSensorPlayground pulseSensor;

#define ADC_VREF_mV 3300.0
#define ADC_RESOLUTION 4096.0
#define PIN_LM35 34

#define DHTPIN 19
#define DHTTYPE DHT22
DHT_Unified dht(DHTPIN, DHTTYPE);
uint32_t delayMS;

MAX30105 particleSensor;
uint32_t irBuffer[100];
uint32_t redBuffer[100];
int32_t bufferLength;
int32_t spo2;
int8_t validSPO2;
int32_t heartRate;
int8_t validHeartRate;
byte readLED = 13;

unsigned long previousDHTTime = 0;
unsigned long previousMAX30102Time = 0;
unsigned long previousPulseTime = 0;
unsigned long previousLM35Time = 0;

unsigned long dhtInterval = 2000;
unsigned long max30102Interval = 1000;
unsigned long pulseInterval = 100;
unsigned long lm35Interval = 400;

void setup() {
  Serial.begin(9600);
  dht.begin();
  analogSetAttenuation(ADC_11db);
  if (!particleSensor.begin(Wire, I2C_SPEED_FAST)) {
    Serial.println(F("MAX30105 not found. Check wiring/power."));
    while (1);
  }
  particleSensor.setup();
  particleSensor.setPulseAmplitudeRed(0x0A);
  particleSensor.setPulseAmplitudeIR(0x0A);
  particleSensor.setPulseAmplitudeGreen(0);
  pinMode(readLED, OUTPUT);
  pulseSensor.analogInput(PulseWire);
  pulseSensor.setThreshold(Threshold);
  if (pulseSensor.begin()) {
    Serial.println("PulseSensor ready!");
  } else {
    Serial.println("PulseSensor not detected!");
    while (1);
  }
}

void loop() {
  unsigned long currentMillis = millis();

  if (currentMillis - previousDHTTime >= dhtInterval) {
    previousDHTTime = currentMillis;
    sensors_event_t event;
    dht.temperature().getEvent(&event);
    if (isnan(event.temperature)) {
      Serial.println(F("Error reading temperature!"));
    } else {
      Serial.print(F("Temperature: "));
      Serial.print(event.temperature);
      Serial.println(F("°C"));
    }
    dht.humidity().getEvent(&event);
    if (isnan(event.relative_humidity)) {
      Serial.println(F("Error reading humidity!"));
    } else {
      Serial.print(F("Humidity: "));
      Serial.print(event.relative_humidity);
      Serial.println(F("%"));
    }
  }

  if (currentMillis - previousMAX30102Time >= max30102Interval) {
    previousMAX30102Time = currentMillis;
    bufferLength = 100;
    for (byte i = 0; i < bufferLength; i++) {
      while (particleSensor.available() == false) {
        particleSensor.check();
      }
      redBuffer[i] = particleSensor.getRed();
      irBuffer[i] = particleSensor.getIR();
      particleSensor.nextSample();
    }
    maxim_heart_rate_and_oxygen_saturation(irBuffer, bufferLength, redBuffer, &spo2, &validSPO2, &heartRate, &validHeartRate);
    if (validHeartRate && validSPO2) {
      Serial.print(F("Heart Rate: "));
      Serial.print(heartRate);
      Serial.print(F(" bpm, SpO2: "));
      Serial.print(spo2);
      Serial.println(F(" %"));
    }
  }

  if (currentMillis - previousPulseTime >= pulseInterval) {
    previousPulseTime = currentMillis;
    int myBPM = pulseSensor.getBeatsPerMinute();
    if (pulseSensor.sawStartOfBeat()) {
      Serial.println("♥ A HeartBeat Happened!");
      Serial.print("BPM: ");
      Serial.println(myBPM);
    } else {
      Serial.println("Please Touch the Sensor..!");
      Serial.println("BPM: 0");
    }
  }

  if (currentMillis - previousLM35Time >= lm35Interval) {
    previousLM35Time = currentMillis;
    int adcVal = analogRead(PIN_LM35);
    float milliVolt = adcVal * (ADC_VREF_mV / ADC_RESOLUTION);
    float tempC = milliVolt / 10;
    float tempF = tempC * 9 / 5 + 32;
    Serial.print("LM35 Temperature: ");
    Serial.print(tempC);
    Serial.print("°C");
    Serial.print(" ~ ");
    Serial.print(tempF);
    Serial.println("°F");
  }
  Serial.println("----------------------");
  delay(10);
}

This code initializes the sensors and reads data from them at specified intervals. The data is then printed to the Serial Monitor. The code includes error handling for sensor readings and ensures that the sensors are properly initialized before starting the main loop.