ESP32 IoT Health Monitor Arduino IoT Cloud Open Source Live Dashboard
// IoT Health Monitoring System

VitalSync

Real-time SPO₂ · Heart Rate · Temperature → Cloud

A wall-powered IoT health station built on ESP32 that measures blood oxygen saturation, heart rate, and body temperature — displayed locally on an OLED and synchronized live to Arduino IoT Cloud.

Language C++ / Arduino
Platform ESP32
License MIT
Cloud Arduino IoT
Author Prince Jha
Heart Rate
72
BPM
Blood Oxygen
98
SpO₂ %
Temperature
98.4
°F

What VitalSync Does

Real-Time Heart Rate
Custom peak-detection algorithm using exponential moving average baseline. Accurate on low-amplitude PPG signals where standard libraries fail.
SpO₂ Measurement
Maxim's official ratio-of-ratios SpO₂ algorithm over 100-sample rolling buffer with real-time validation.
Body Temperature
DS18B20 non-blocking temperature read every 3s. Displays simultaneously in °F and °C with clinical status text.
OLED Display
Two auto-rotating pages every 4 seconds. Page 1: BPM + SpO₂ with live waveform. Page 2: Temperature in both units.
Arduino IoT Cloud
4 variables pushed via MQTT/TLS every 5 seconds. Throttled cloud polling (100ms) prevents sensor loop interference.
Wall-Powered Hardware
12V DC → LM2596 Buck → 5V → AMS1117 → 3.3V. Clean regulated power for all components on a 6×4 perfboard.
Non-Blocking Architecture
Zero delay() calls. All timing via millis() timers. MAX30102 FIFO serviced every loop iteration without stalls.
Mobile App Ready
Live sensor data accessible from anywhere via the Arduino IoT Cloud mobile app — no server setup required.

Components

Component 01
ESP32 Dev Module
Main Microcontroller
Dual-core 240MHz Xtensa LX6. Built-in WiFi 802.11 b/g/n + Bluetooth. 12-bit ADC, hardware I2C/SPI. 3.3V logic.
Component 02
MAX30102 (Black PCB)
Pulse Oximeter + Heart Rate
Integrated red (660nm) + IR (880nm) LED with photodetector. 18-bit ADC. I2C address 0x57. PPG-based SpO₂ and BPM.
Component 03
DS18B20 (Black Wire)
Digital Temperature Sensor
Silicon bandgap thermometer. ±0.5°C accuracy. 11-bit resolution (0.125°C). 1-Wire protocol. −55°C to +125°C range.
Component 04
SSD1306 OLED 0.96"
Local Display
128×64 pixel OLED. No backlight needed — each pixel self-illuminates. I2C address 0x3C. High contrast, low power.
Component 05
LM2596 Buck Converter
12V → 5V Step-Down
Switching DC-DC converter. 75–90% efficiency. Handles up to 3A. Eliminates heat dissipation of a direct linear drop.
Component 06
AMS1117 3.3V LDO
5V → 3.3V Regulator
Low dropout linear regulator. Provides clean 3.3V for ESP32, OLED, MAX30102, and DS18B20 from the buck's 5V rail.
Component 07
4.7kΩ Resistor (¼W)
1-Wire Pull-up
Mandatory pull-up for DS18B20 1-Wire data line. Provides high logic level on open-drain bus. Between DATA and 3.3V.
Component 08
6×4 Perfboard
Custom PCB Assembly
Single-sided brown perfboard. All components soldered point-to-point. Compact and permanent assembly without a PCB fab.

Pin Connections

Component Signal ESP32 Pin Note
MAX30102 SDA GPIO 21 Shared I2C bus
MAX30102 SCL GPIO 22 Shared I2C bus
MAX30102 VIN 3.3V From AMS1117
OLED SSD1306 SDA GPIO 21 Shared I2C bus (addr 0x3C)
OLED SSD1306 SCL GPIO 22 Shared I2C bus
OLED SSD1306 VCC 3.3V From AMS1117
DS18B20 DATA GPIO 4 4.7kΩ pull-up to 3.3V
DS18B20 VCC 3.3V From AMS1117
All GND GND GND Common ground rail

How Components Talk

I²C
Inter-Integrated Circuit
Used by MAX30102 (0x57) and OLED (0x3C) on the same 2-wire bus. SDA = GPIO 21, SCL = GPIO 22. Running at 400kHz Fast Mode. Master (ESP32) initiates all transfers. Open-drain with pull-ups.
1-Wire
Dallas 1-Wire
Used by DS18B20 on GPIO 4 with 4.7kΩ pull-up. Single bidirectional data line. Each DS18B20 has a unique 64-bit ROM address. Non-blocking mode: requestTemperatures() then read 3s later.
MQTT / TLS
Message Queue Telemetry Transport
Publish-subscribe IoT protocol over TCP/IP port 8884. Broker: iot.arduino.cc. TLS encrypted. Persistent connection. 4 variables published ON_CHANGE, polled every 100ms to avoid blocking.
WiFi 802.11
Wireless LAN
ESP32 connects to 2.4GHz hotspot. ConnectionHandler manages automatic reconnection. NTP (time.google.com) synchronizes clock required for Arduino IoT Cloud TLS authentication.

System Data Flow

MAX30102 ──I²C──▶ ESP32 ──▶ Peak Detector ──▶ BPM
MAX30102 ──I²C──▶ ESP32 ──▶ SpO₂ Algorithm ──▶ SpO₂%
DS18B20 ──1W──▶ ESP32 ──▶ F = C×9/5+32 ──▶ °F / °C
BPM + SpO₂ + Temp ──▶ OLED Display & WiFi → MQTT → Arduino IoT Cloud

Non-Blocking Loop Architecture

// Loop runs at full speed — no delay() anywhere void loop() { // Cloud poll — throttled to 100ms if (now - lastCloudPoll >= 100) ArduinoCloud.update(); // DS18B20 — every 3000ms, non-blocking if (now - lastTempRead >= 3000) readTemperature(); // MAX30102 — service FIFO every iteration while (!particleSensor.available()) particleSensor.check(); irVal = particleSensor.getIR(); redVal = particleSensor.getRed(); particleSensor.nextSample(); // Custom peak detector → BPM detectBeat(irVal); // SpO2 buffer → recalculate at 100 samples accumulateSpO2(irVal, redVal); // OLED refresh — every 150ms if (now - lastDisplay >= 150) updateDisplay(); // Cloud push — every 5000ms if (now - lastCloudUpd >= 5000) pushToCloud(); }

Arduino IoT Cloud Variables

Define these four variables in your Thing on create.arduino.cc/iot before uploading.

heartRate
int
READ · ON_CHANGE
spo2Level
int
READ · ON_CHANGE
temperatureF
float
READ · ON_CHANGE
temperatureC
float
READ · ON_CHANGE
// thingProperties.h — fill in your credentials const char DEVICE_LOGIN_NAME[] = "YOUR_DEVICE_ID"; const char SSID[] = "YOUR_WIFI_SSID"; const char PASS[] = "YOUR_WIFI_PASSWORD"; const char DEVICE_KEY[] = "YOUR_SECRET_KEY";

Getting Started

Clone the Repository

git clone https://github.com/iprince10/VitalSync_HealthMonitoringSystem.git and open the .ino file in Arduino IDE.

Install ESP32 Board Package

In Arduino IDE → Board Manager → search esp32 by Espressif → Install.

Install Required Libraries

Via Library Manager install: SparkFun MAX3010x, DallasTemperature, OneWire, Adafruit SSD1306, Adafruit GFX, ArduinoIoTCloud, Arduino_ConnectionHandler.

Create Arduino IoT Cloud Thing

Go to create.arduino.cc/iot, create a Thing named HealthMonitor, add the 4 cloud variables above, register an ESP32 device, and save the Device ID + Secret Key.

Configure Credentials

Edit thingProperties.h — fill in your Device ID, Secret Key, WiFi SSID, and WiFi password. Never commit this file publicly.

Upload and Monitor

Select board ESP32 Dev Module, select your COM port, upload. Open Serial Monitor at 115200 baud to observe connection logs and sensor values.

Built By

PJ
Prince Jha
B.Tech Electronics & Communication Engineering — Jamia Hamdard, New Delhi
Aspiring Embedded Engineer

GitHub: github.com/iprince10  ·  Project: VitalSync Repository