IoT Based Health Monitoring system on ESP32 Web Server

IoT Based Health Monitoring system on ESP32 Web Server IoT Based Health Monitoring system on ESP32 Web Server

Overview:

In this project, we are going to learn how to create an IoT based health monitoring system using ESP32 Microcontroller with built in WiFi and Bluetooth to display health data such as:

  • Patient body Temperature,
  • Patient Blood Oxygen(SPo2),
  • Patient Heart rate,
  • Room Temperature
  • Room Humidity
  • and more (optional).

As the technology in the IoT industry improving every day with new inventions of health monitoring devices, It is becoming easy to monitor few health parameters easily at our home itself, So if any abnormal things happens we can immediately take some action against it by visiting a nearest clinic or doctor.

IoT based health monitoring system on webserver mutidevice

It is important to monitor some important health parameters like body temperature, heart rate and Blood Oxygen levels as they may indicate a precaution before any illness. Specially old age people health should be monitored regularly as their immunity weakens with the increase in age.

Due to work and busy schedules many people don’t have time to visit a clinic to track health status, so taking this scenario into consideration let’s build a patient health monitoring system using IoT which can sense and monitor few important health parameters at home or work.

So, in our IoT project we are interfacing few sensors with ESP32 Microcontroller such as DS18B20 waterproof temperature sensor to measure body temperature, MAX30100/MAX30102 heart rate and Pulse Oximeter sensor module to measure Blood SpO2 and Heart rate, BME280 temperature and humidity sensor to measure the room temperature and humidity as these parameters sometimes makes a person feel uncomfortable.

Before getting started with the project lets learn what are the required components and also learn about: Sensors we are using, why we are using them, what are their advantages over the other sensors.

Required components

Product NameQuantityamazon logoamazon logo india
ESP32 microcontroller with built in WiFi and Bluetooth1https://amzn.to/3s0Sut6https://amzn.to/3Kw2np2
MAX30100 or MAX30102 Pulse Oximeter sensor1https://amzn.to/3pxTUcKhttps://amzn.to/3vT1Byq
DS18B20 Waterproof temperature sensor1https://amzn.to/3C7lmmRhttps://amzn.to/3pUglJl
BME280 temperature and humidity sensor1https://amzn.to/3Mka2s7https://amzn.to/37hlqFg
Few Connecting Wireshttps://amzn.to/3H2BV4ehttps://amzn.to/3J0WVu2
Here are the required components along with Amazon buying links at best prices.

MAX30100 or MAX30102 Pulse Oximeter and Heart rate sensor

In this Project we are using MAX30102 instead of old model MAX30100 as the old model has a design issue between I2C pull up resistors as they are connected to 1.8V which is too low for a microcontroller to detect the signal. If you still want to use the old model MAX30100 this issue can be rectified by removing resistors and adding external resistors which we explained in detail in our previous article or you can buy GY-MAX30100 which has corrected hardware circuits.

MAX30102 has better hardware design and software support. This module has emitting Red LED, emitting InfraRed LED and a Photodetector to absorb the emitted light. It is built with low noise analog signal processing circuits with ambient light cancellation for better accuracy.

When the place our finger on the sensor the red light coming from the LED is passed through the finger, According to the biology when heart pumps blood has more oxygen when compared with the heart relaxed state. The Oxygenated blood absorb more Red and IR light than the deoxygenated blood, the Photodetector absorb the remaining light from the finger and analyze it to give the SpO2 results, and the time gap between the low light and high light is calculated which is nothing but Pulse rate or Heart rate. Which is sent to the microcontroller using I2C communication.

This sensor operates between 3.3v to 5v.

For more details refer: MAX30102 datasheet here

MAX30102 Pinout Diagram:

max30102 pulse oximeter heart rate sensor pinout diagramFrom the above image you can see the MAX30102 has 8 pins but in this project we use only 4 pins on the left side for I2C communication with ESP32.

DS18B20 waterproof temperature sensor

DS18B20 temperature sensor is a Onewire sensor which means it can send the data only through single data wire(and GND) to microcontrollers. A 64-bit unique serial code is given to each sensor to differentiate every sensor when more than one DS18B20 sensors are connected. This allows us to get multiple sensor data through single data line through single GPIO pin. By default it is configured with 12 bits and 0.0625°C sensitivity.

DS18B20 temperature sensor pinout diagram

DS18B20 temperature operates between 3v-5.5V, consuming very low power nearly 1mA. It has an accuracy of ±0.5°C. To know more about DS18B20 temperature sensor refer our previous article:

In this IoT health monitoring system project we are using DS18B20 instead of LM35 as DS18B20 comes with waterproofing which makes it easy to be placed anywhere on the body with moisture. DS18B20 has onewire technology where we can connect multiple sensors and measure the temperatures of head, neck, under arms or any place on the body according to the requirement. And finally the accuracy and stability over LM35.

For more details refer: DS18B20 official datasheet

BME280 Temperature and humidity sensor

In this health monitoring system project, we are using BME280 sensor which gives temperature and humidity values of the room. Based on BOSCH piezo-resistive technology BME280 has features like low energy consumption, ultra compact with great precision and stability in output signal.

BME/BMP280 pinout diagram

BME280 is superior to BMP180 and has relative humidity sensing, these sensors performs better than DHT22 and DHT11 in terms of accuracy and long term stability in output. BME280 heats up little bit than other sensors and measurements can vary with increase of 2-3°F, but we still choose BME280 instead of others because it’s output give vary stable results when compared with other sensors in the range.

BME280 works in the voltage range of 1.8v to 3.3v and measures temperatures between -40 to 85°C with an accuracy of 1°C. It also measures relative humidity ranging 0-100% at an accuracy of +-3%. It sends the data signals to microcontroller through both I2C and SPI communication protocols.

For more details refer: BME280 Official datasheet

IoT based health monitoring system circuit diagram interfacing sensors with ESP32

Now lets connect all the required components according to the below schematic diagram.

IoT based health monitoring system circuit diagram interfacing sensors with ESP32 web server

As you can see from the above circuit diagram of IoT based health monitoring system project, we connected 3 sensor which gives 5 health parameters as we discussed in the overview. Let’s see how they are connected.

MAX30102 SpO2 and heart rate sensor to ESP32

This sensor is connected in I2C communication protocol, so SDA and SCL pins from the sensor are connected to D21 and D22 pins of ESP32 respectively. The sensor is powered with 5V power supply from the ESP32 VIN pin to VIN pin of sensor as we are supplying 5V to ESP32, GND pin of sensor is connected to GND of ESP32.

BME280 temperature and relative humidity sensor to ESP32

This sensor also uses I2C communication protocol and connected same as the above sensor. SDA and SCL of sensor to D21 and D22 respectively. The only change is with power supply. As BME280 supports voltages up to 3.3V we are powering VIN pin of sensor with 3.3V pin of ESP32.

DS18B20 water proof temperature sensor to ESP32

We powered this sensor with 5V from the ESP32 and connected to red wire. Black wire is connected to GND. and the yellow wire is connected to digital pin D5(GPIO5) of ESP32. A 4.7 K.Ohm resisitor is connected between the yellow data wire and 5v supply to amplify the data signal.

That’s it for connection, now lets get into the coding section to upload code of IoT based health monitoring system using Arduino IDE to get data over ESP32 web server.

Source Code of health monitoring system using ESP32 web server:

Before getting started with program code. We need install few required libraries of sensors in Arduino IDE listed below. You can either install these libraries through Arduino IDE built in Library manager or just by downloading the latest libraries and paste it into libraries folder through the GitHub links below.

  • DallasTemperature  –Link   by Miles burton
  • Adafruit_BME280  –Link  by Adafruit
  • MAX30105  –Link    by Sparkfun
  • OneWire Library – Link  by Paul Stofforegen
  • WebServer.h Library download- Link

After downloading all the required libraries, connect ESP32 to PC where Arduino IDE is Installed. Next copy the below program code and paste it in the Arduino IDE workspace and change few parameter like WiFi username and Password. Select the board to ESP32 Wrover module and Port where it is connected from the tools menu.

Program Code:

/*********
IOT BASED HEALTH MONITORING SYSTEM USING ESP32 WEBSERVER
COPYRIGHTS AND CREDITS:CIRCUITSCHOOLS.COM
*********/

#include <WiFi.h>
#include <WebServer.h>
#include <Wire.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include "MAX30105.h"
#include "spo2_algorithm.h"

Adafruit_BME280 bme; // I2C

#define DS18B20 5
OneWire oneWire(DS18B20);
DallasTemperature sensors(&oneWire);

#define REPORTING_PERIOD_MS     1000
uint32_t tsLastReport = 0;

MAX30105 particleSensor;
#define MAX_BRIGHTNESS 255 
uint32_t irBuffer[100]; //infrared LED sensor data
uint32_t redBuffer[100];  //red LED sensor data
int32_t bufferLength; //data length
int32_t spo2; //SPO2 value
int8_t validSPO2; //indicator to show if the SPO2 calculation is valid
int32_t heartRate; //heart rate value
int8_t validHeartRate; //indicator to show if the heart rate calculation is valid
byte pulseLED = 11; //Must be on PWM pin
byte readLED = 13; //Blinks with each data read 

float temperature, humidity, BPM, SpO2, bodytemperature;
 
/*Put your SSID & Password*/
const char* ssid = "circuitschools";  // Enter SSID here
const char* password = "password";  //Enter Password here
 
WebServer server(80);             
 
void setup() {
  Serial.begin(9600);  
 
  Serial.println("Connecting to ");
  Serial.println(ssid);
 
  //connect to your local wi-fi network
  WiFi.begin(ssid, password);
 
  //check wi-fi is connected to wi-fi network
  while (WiFi.status() != WL_CONNECTED) {
  delay(1000);
  Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected..!");
  Serial.print("Got IP: ");  Serial.println(WiFi.localIP());
 
  server.on("/", handle_OnConnect);
  server.onNotFound(handle_NotFound);
 
  server.begin();
  Serial.println("HTTP server started");
  
  sensors.begin();  //initialize DS18B20 sensor
  
  if (!bme.begin(0x76)) {   //if still not found try another address or scan through I2C scanner from our prevoius posts
    Serial.println(F("Could not find a valid BME280 sensor, check wiring!"));
    //while (1);
  }
 
  Serial.print("Initializing pulse oximeter..");
 
  pinMode(pulseLED, OUTPUT);
  pinMode(readLED, OUTPUT);

  // Initialize max30102 sensor
  if (!particleSensor.begin(Wire, I2C_SPEED_FAST)) //Use default I2C port, 400kHz speed
  {
    Serial.println(F("MAX30102 was not found. Please check wiring/power."));
    //while (1);
  }

  Serial.println(F("Attach sensor to finger with rubber band. Press any key to start conversion"));
  while (Serial.available() == 0) ; //wait until user presses a key
  Serial.read();

  byte ledBrightness = 60; //Options: 0=Off to 255=50mA
  byte sampleAverage = 4; //Options: 1, 2, 4, 8, 16, 32
  byte ledMode = 2; //Options: 1 = Red only, 2 = Red + IR, 3 = Red + IR + Green
  byte sampleRate = 100; //Options: 50, 100, 200, 400, 800, 1000, 1600, 3200
  int pulseWidth = 411; //Options: 69, 118, 215, 411
  int adcRange = 4096; //Options: 2048, 4096, 8192, 16384

  particleSensor.setup(ledBrightness, sampleAverage, ledMode, sampleRate, pulseWidth, adcRange); //Configure sensor with these settings
 
}
void loop() {
  server.handleClient();
  }
void handle_OnConnect() { 
  sensors.requestTemperatures();
  
  
  bufferLength = 100; //buffer length of 100 stores 4 seconds of samples running at 25sps

  //read the first 100 samples, and determine the signal range
  for (byte i = 0 ; i < bufferLength ; i++)
  {
    while (particleSensor.available() == false) //do we have new data?
      particleSensor.check(); //Check the sensor for new data

    redBuffer[i] = particleSensor.getRed();
    irBuffer[i] = particleSensor.getIR();
    particleSensor.nextSample(); //We're finished with this sample so move to next sample

    Serial.print(F("red="));
    Serial.print(redBuffer[i], DEC);
    Serial.print(F(", ir="));
    Serial.println(irBuffer[i], DEC);
  }

  //calculate heart rate and SpO2 after first 100 samples (first 4 seconds of samples)
  maxim_heart_rate_and_oxygen_saturation(irBuffer, bufferLength, redBuffer, &spo2, &validSPO2, &heartRate, &validHeartRate);

  //Continuously taking samples from MAX30102.  Heart rate and SpO2 are calculated every 1 second
  while (1)
  {
    //dumping the first 25 sets of samples in the memory and shift the last 75 sets of samples to the top
    for (byte i = 25; i < 100; i++)
    {
      redBuffer[i - 25] = redBuffer[i];
      irBuffer[i - 25] = irBuffer[i];
    }

    //take 25 sets of samples before calculating the heart rate.
    for (byte i = 75; i < 100; i++)
    {
      while (particleSensor.available() == false) //do we have new data?
        particleSensor.check(); //Check the sensor for new data

      digitalWrite(readLED, !digitalRead(readLED)); //Blink onboard LED with every data read

      redBuffer[i] = particleSensor.getRed();
      irBuffer[i] = particleSensor.getIR();
      particleSensor.nextSample(); //We're finished with this sample so move to next sample

      //send samples and calculation result to terminal program through UART
      Serial.print(F("red="));
      Serial.print(redBuffer[i], DEC);
      Serial.print(F(", ir="));
      Serial.print(irBuffer[i], DEC);

      Serial.print(F(", HR="));
      Serial.print(heartRate, DEC);

      Serial.print(F(", HRvalid="));
      Serial.print(validHeartRate, DEC);

      Serial.print(F(", SPO2="));
      Serial.print(spo2, DEC);

      Serial.print(F(", SPO2Valid="));
      Serial.println(validSPO2, DEC);
    }

    //After gathering 25 new samples recalculate HR and SP02
    maxim_heart_rate_and_oxygen_saturation(irBuffer, bufferLength, redBuffer, &spo2, &validSPO2, &heartRate, &validHeartRate);
  }
  
  
  temperature = bme.readTemperature();
  humidity = bme.readHumidity()/100; 
  BPM = heartRate;
  SpO2 = spo2;
  bodytemperature = (sensors.getTempCByIndex(0)*9.0)/5.0+32.0; //Converting into Farenheit
 
  
  if (millis() - tsLastReport > REPORTING_PERIOD_MS) 
  {
    Serial.print("Room Temperature: ");
    Serial.print(bme.readTemperature());
    Serial.println("°C");
    
    Serial.print("Room Humidity: ");
    Serial.print(bme.readPressure()/100);
    Serial.println("%");
    
    Serial.print("BPM: ");
    Serial.println(heartRate);
    
    Serial.print("SpO2: ");
    Serial.print(spo2);
    Serial.println("%");
 
    Serial.print("Body Temperature: ");
    Serial.print(bodytemperature);
    Serial.println("°C");
    
    Serial.println("*********************************");
    Serial.println();//for more details visit circuitschools.com
 
    tsLastReport = millis();
  }
  
  server.send(200, "text/html", SendHTML(temperature, humidity, BPM, SpO2, bodytemperature)); 
}
 
void handle_NotFound(){
  server.send(404, "text/plain", "Not found");
}
 
  String SendHTML(float temperature,float humidity,float BPM,float SpO2, float bodytemperature){
  String ptr = "<!DOCTYPE html>";
  ptr +="<html>";
  ptr +="<head>";
  ptr +="<title>IoT based Patient Health Monitoring system</title>";
  ptr +="<meta name='viewport' content='width=device-width, initial-scale=1.0'>";
  ptr +="<link href='https://fonts.googleapis.com/css?family=Open+Sans:300,400,600' rel='stylesheet'>";
  ptr +="<style>";
  ptr +="html { font-family: 'Open Sans', sans-serif; display: block; margin: 0px auto; text-align: center;color: #444444;}";
  ptr +="body{margin: 0px;} ";
  ptr +="h1 {margin: 50px auto 30px;} ";
  ptr +=".side-by-side{display: table-cell;vertical-align: middle;position: relative;}";
  ptr +=".text{font-weight: 600;font-size: 19px;width: 200px;}";
  ptr +=".reading{font-weight: 300;font-size: 50px;padding-right: 25px;}";
  ptr +=".temperature .reading{color: #F29C1F;}";
  ptr +=".humidity .reading{color: #3B97D3;}";
  ptr +=".BPM .reading{color: #FF0000;}";
  ptr +=".SpO2 .reading{color: #955BA5;}";
  ptr +=".bodytemperature .reading{color: #F29C1F;}";
  ptr +=".superscript{font-size: 17px;font-weight: 600;position: absolute;top: 10px;}";
  ptr +=".data{padding: 10px;}";
  ptr +=".container{display: table;margin: 0 auto;}";
  ptr +=".icon{width:65px}";
  ptr +="</style>";
  ptr +="</head>";
  ptr +="<body>";
  ptr +="<h1>ESP32 Patient Health Monitoring</h1>";
  ptr +="<h3>For more details visit www.circuitschools.com</h3>";
  ptr +="<div class='container'>";
  
  ptr +="<div class='data bodytemperature'>";
  ptr +="<div class='side-by-side icon'>";
  ptr +="<svg enable-background='new 0 0 19.438 54.003'height=54.003px id=Layer_1 version=1.1 viewBox='0 0 19.438 54.003'width=19.438px x=0px xml:space=preserve xmlns=http://www.w3.org/2000/svg xmlns:xlink=http://www.w3.org/1999/xlink y=0px><g><path d='M11.976,8.82v-2h4.084V6.063C16.06,2.715,13.345,0,9.996,0H9.313C5.965,0,3.252,2.715,3.252,6.063v30.982";
  ptr +="C1.261,38.825,0,41.403,0,44.286c0,5.367,4.351,9.718,9.719,9.718c5.368,0,9.719-4.351,9.719-9.718";
  ptr +="c0-2.943-1.312-5.574-3.378-7.355V18.436h-3.914v-2h3.914v-2.808h-4.084v-2h4.084V8.82H11.976z M15.302,44.833";
  ptr +="c0,3.083-2.5,5.583-5.583,5.583s-5.583-2.5-5.583-5.583c0-2.279,1.368-4.236,3.326-5.104V24.257C7.462,23.01,8.472,22,9.719,22";
  ptr +="s2.257,1.01,2.257,2.257V39.73C13.934,40.597,15.302,42.554,15.302,44.833z'fill=#F29C21 /></g></svg>";
  ptr +="</div>";
  ptr +="<div class='side-by-side text'>Body Temperature</div>";
  ptr +="<div class='side-by-side reading'>";
  ptr +=(int)bodytemperature;
  ptr +="<span class='superscript'>&deg;F</span></div>";
  ptr +="</div>";
  
  ptr +="<div class='data Heartrate'>";
  ptr +="<div class='side-by-side icon'>";
  ptr +="<svg enable-background='new 0 0 40.542 40.64'height=49.079px id=Layer_1 version=1.1 viewBox=0 0 49.079 49.079 width=49.079px x=0px xml:space=preserve xmlns=http://www.w3.org/2000/svg xmlns:xlink=http://www.w3.org/1999/xlink y=0px><path d='M35.811,2.632c0.694,0,1.433,0.039,2.223,0.113C42.84,3.218,48.4,7.62,49.079,16.054v2.807";
  ptr +="c-0.542,6.923-5.099,15.231-17.612,25.333c-3.722,3.004-10.135,3.004-13.856,0C5.097,34.092,0.541,25.784,0,18.861v-2.807";
  ptr +="C0.676,7.62,6.236,3.218,11.046,2.745c0.79-0.074,1.528-0.113,2.222-0.113c2.682,0,4.691,0.561,6.395,1.549";
  ptr +="c3.181,1.846,6.569,1.846,9.752,0C31.119,3.193,33.128,2.632,35.811,2.632'";
  ptr +="fill=#FF0000 /></svg>";
  ptr +="</div>";
  ptr +="<div class='side-by-side text'>Heart Rate(BPM)</div>";
  ptr +="<div class='side-by-side reading'>";
  ptr +=(int)BPM;
  ptr +="<span class='superscript'>BPM</span></div>";
  ptr +="</div>";
  
  ptr +="<div class='data Blood Oxygen'>";
  ptr +="<div class='side-by-side icon'>";
  ptr +="<svg enable-background='new 0 0 40.542 40.541'height=40.541px id=Layer_1 version=1.1 viewBox='0 0 40.542 40.541'width=40.542px x=0px xml:space=preserve xmlns=http://www.w3.org/2000/svg xmlns:xlink=http://www.w3.org/1999/xlink y=0px><g><path d='M16.458.584A1.3957 1.3957 0 0 0 15.323 0c-.451 0-.874.217-1.137.584-2.808 3.919-9.843 14.227-9.843 19.082 ";
  ptr +="0 6.064 4.915 10.98 10.979 10.98 6.065 0 10.981-4.916 10.981-10.98.001-4.855-7.037-15.163-9.845-19.082zm-4.991 25.297c-.3.357-.732.542-1.167.542-.345 0-.695-.118-.981-.358-4.329-3.646-2.835-9.031-2.769-9.26.234-.809 1.073-1.273 1.886-1.042.808.231 1.274 1.075 1.045 1.881-.047.175-.982 3.743 1.804 6.089.642.542.725 1.503.182 2.148zm2.997 3.029c-.893 ";
  ptr +="0-1.62-.727-1.62-1.62 0-.896.727-1.621 1.62-1.621.896 0 1.62.726 1.62 1.621s-.725 1.62-1.62 1.62z'";
  ptr +="fill=#FF0000 /></g></svg>";
  ptr +="</div>";
  ptr +="<div class='side-by-side text'>Blood Oxygen</div>";
  ptr +="<div class='side-by-side reading'>";
  ptr +=(int)SpO2;
  ptr +="<span class='superscript'>%</span></div>";
  ptr +="</div>";
  
  ptr +="<div class='data Room Temperature'>";
  ptr +="<div class='side-by-side icon'>";
  ptr +="<svg enable-background='new 0 0 19.438 54.003'height=54.003px id=Layer_1 version=1.1 viewBox='0 0 19.438 54.003'width=19.438px x=0px xml:space=preserve xmlns=http://www.w3.org/2000/svg xmlns:xlink=http://www.w3.org/1999/xlink y=0px><g><path d='M11.976,8.82v-2h4.084V6.063C16.06,2.715,13.345,0,9.996,0H9.313C5.965,0,3.252,2.715,3.252,6.063v30.982";
  ptr +="C1.261,38.825,0,41.403,0,44.286c0,5.367,4.351,9.718,9.719,9.718c5.368,0,9.719-4.351,9.719-9.718";
  ptr +="c0-2.943-1.312-5.574-3.378-7.355V18.436h-3.914v-2h3.914v-2.808h-4.084v-2h4.084V8.82H11.976z M15.302,44.833";
  ptr +="c0,3.083-2.5,5.583-5.583,5.583s-5.583-2.5-5.583-5.583c0-2.279,1.368-4.236,3.326-5.104V24.257C7.462,23.01,8.472,22,9.719,22";
  ptr +="s2.257,1.01,2.257,2.257V39.73C13.934,40.597,15.302,42.554,15.302,44.833z'fill=#F29C21 /></g></svg>";
  ptr +="</div>";
  ptr +="<div class='side-by-side text'>Room Temperature</div>";
  ptr +="<div class='side-by-side reading'>";
  ptr +=(int)temperature;
  ptr +="<span class='superscript'>&deg;C</span></div>";
  ptr +="</div>";
 
  ptr +="<div class='data Room Humidity'>";
  ptr +="<div class='side-by-side icon'>";
  ptr +="<svg enable-background='new 0 0 29.235 40.64'height=40.64px id=Layer_1 version=1.1 viewBox='0 0 29.235 40.64'width=29.235px x=0px xml:space=preserve xmlns=http://www.w3.org/2000/svg xmlns:xlink=http://www.w3.org/1999/xlink y=0px><path d='M14.618,0C14.618,0,0,17.95,0,26.022C0,34.096,6.544,40.64,14.618,40.64s14.617-6.544,14.617-14.617";
  ptr +="C29.235,17.95,14.618,0,14.618,0z M13.667,37.135c-5.604,0-10.162-4.56-10.162-10.162c0-0.787,0.638-1.426,1.426-1.426";
  ptr +="c0.787,0,1.425,0.639,1.425,1.426c0,4.031,3.28,7.312,7.311,7.312c0.787,0,1.425,0.638,1.425,1.425";
  ptr +="C15.093,36.497,14.455,37.135,13.667,37.135z'fill=#3C97D3 /></svg>";
  ptr +="</div>";
  ptr +="<div class='side-by-side text'>Room Humidity</div>";
  ptr +="<div class='side-by-side reading'>";
  ptr +=(int)humidity;
  ptr +="<span class='superscript'>%</span></div>";
  ptr +="</div>";
  
  ptr +="</div>";
  ptr +="</body>";
  ptr +="</html>";
  return ptr; 
}//for more details visit circuitschools.com

Now hit upload button to upload the code to ESP32. After uploading open the serial monitor of specified baud rate to get the network connection status and IP address and few values as below output image.

IoT based health monitoring system output on ESP32 serial monitorHere I made buffer sample to 5 so all parameters are visible in the output. Here you can see all the patient health parameters like Body temperature, Blood Oxygen, Heart rate, Room temperature and humidity.

As you can see from the above output from serial monitor an IP address 192.168.1.166 was generated, which you can type on any device browser (mobile or PC) connected to same network to check on the web server interface as shown in the below image.

IoT based health monitoring system output on ESP32 webserverWe are going to make a IoT based remote patient health monitoring system in our next article, where you can monitor patient health parameters remotely from anywhere in the world. So, please stay tuned with Circuitschools.

Tips, Notes and Error with solutions

Tips: You can interface other sensors like ECG sensor, Air Quality monitoring sensors and other latest sensors with the same ESP32 to get more parameters but limit till the maximum memory limit of the ESP32 code. ESP32 has Bluetooth and WiFi built in so you can monitor the data over Bluetooth also.

Notes: This sensors are just for prototyping and cannot be replaced with the certified medical devices. You can still use them by comparing the results with standard devices and modify the code.

For MAX30102 Attach finger with sensor using rubber band as humans cannot apply constant pressure on it.

Errors and Solutions:

Could not find a valid BME280 sensor, check wiring!

  • Use BME280 only as BMP280 cannot measure relative humidity.
  • Check wiring and mainly the I2C address, you can check the I2C address with I2C scanner from our previous articles.
  • If you got same error use example code of BME280 from the library.
  • If still not found maybe the sensor is damaged.

MAX30102 was not found. Please check wiring/power

  • Connect the sensor with 5v supply as sometimes 3.3v are not sufficient for the LEDs to perform correctly.
  • Check wiring
  • check whether LEDs are glowing if not remove lines 89 and 90 as they wait for you to click any key on serial monitor

If any other errors appear other than the above listed ones check with the sensor libraries are they installed from the mentioned creators. And also feel free to post it below in the comment section. And please share this article with your friends if you like them and follow us on Facebook page.

Video Tutorial:

IOT based Health monitoring system on ESP32 Webserver

8 comments
  1. hi

    i was verrifying the sketch and got the following error message :

    In file included from C:\Users\andy\AppData\Local\Temp\arduino_modified_sketch_753243\sketch_may08a.ino:8:
    C:\Users\andy\Desktop\Arduino\libraries\SparkFun_MAX3010x_Sensor_Library-master\src/MAX30105.h:42: warning: “I2C_BUFFER_LENGTH” redefined
    #define I2C_BUFFER_LENGTH 32

    In file included from C:\Users\andy\AppData\Local\Temp\arduino_modified_sketch_753243\sketch_may08a.ino:3:
    C:\Users\andy\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.3\libraries\Wire\src/Wire.h:38: note: this is the location of the previous definition
    #define I2C_BUFFER_LENGTH 128

    C:\Users\andy\AppData\Local\Temp\arduino_modified_sketch_753243\sketch_may08a.ino: In function ‘void setup()’:
    sketch_may08a:58:18: error: ‘handle_OnConnect’ was not declared in this scope
    server.on(“/”, handle_OnConnect);
    ^~~~~~~~~~~~~~~~
    sketch_may08a:59:21: error: ‘handle_NotFound’ was not declared in this scope
    server.onNotFound(handle_NotFound);
    ^~~~~~~~~~~~~~~
    sketch_may08a:81:3: error: expected ‘}’ at end of input
    }
    ^
    C:\Users\andy\AppData\Local\Temp\arduino_modified_sketch_753243\sketch_may08a.ino:40:14: note: to match this ‘{‘
    void setup() {
    ^
    exit status 1
    ‘handle_OnConnect’ was not declared in this scope

    any solution for this ?

    1. Hi Andy,
      I think this error is due to the mismatch in libraries or their versions. Please install the libraries given above the code.
      If still error occurs for you, add void handle_OnConnect(); this before the void setup().
      For us the code is working perfectly well.
      Thanks.

  2. Hi Sir,
    I’m using max30100 but when I upload the code it’s initialised successfully but not giving the BPM and SPO2 it’s shows 0 why?

Leave a Reply

Your email address will not be published. Required fields are marked *