/*
* IoT Health Monitor - WOKWI SIMULATION VERSION
* MAX30100 is replaced by 2 potentiometers:
* POT1 (GPIO 34) = Simulated Heart Rate (BPM)
* POT2 (GPIO 35) = Simulated SpO2 (%)
* DS18B20 = Real temperature simulation (click sensor to change temp)
* OLED + Buzzer = Fully simulated
*/
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <OneWire.h>
#include <DallasTemperature.h>
// --- OLED Setup ---
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// --- DS18B20 Setup ---
#define DS18B20_PIN 4
OneWire oneWire(DS18B20_PIN);
DallasTemperature tempSensor(&oneWire);
// --- Potentiometer Pins (simulate BPM & SpO2) ---
#define POT_BPM_PIN 34
#define POT_SPO2_PIN 35
// --- Buzzer ---
#define BUZZER_PIN 15
// --- Thresholds ---
#define MIN_BPM 50
#define MAX_BPM 120
#define MIN_SPO2 90
#define MAX_TEMP 38.5
unsigned long lastUpdate = 0;
void setup() {
Serial.begin(115200);
pinMode(BUZZER_PIN, OUTPUT);
digitalWrite(BUZZER_PIN, LOW);
Wire.begin(21, 22);
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println("OLED failed!");
while (true);
}
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
display.setTextSize(1);
display.setCursor(15, 20);
display.println("Health Monitor");
display.setCursor(20, 35);
display.println("Initializing...");
display.display();
delay(2000);
tempSensor.begin();
Serial.println("System Ready!");
}
void loop() {
if (millis() - lastUpdate > 1000) {
lastUpdate = millis();
// --- Read BPM from Potentiometer 1 (maps 0-4095 → 30-200 BPM) ---
int rawBPM = analogRead(POT_BPM_PIN);
float heartRate = map(rawBPM, 0, 4095, 30, 200);
// --- Read SpO2 from Potentiometer 2 (maps 0-4095 → 80-100 %) ---
int rawSpO2 = analogRead(POT_SPO2_PIN);
float spO2 = map(rawSpO2, 0, 4095, 80, 100);
// --- Read Temperature from DS18B20 ---
tempSensor.requestTemperatures();
float tempC = tempSensor.getTempCByIndex(0);
// --- Print to Serial Monitor ---
Serial.print("BPM: "); Serial.print(heartRate);
Serial.print(" | SpO2: "); Serial.print(spO2);
Serial.print("% | Temp: "); Serial.print(tempC);
Serial.println(" C");
// --- Check Thresholds ---
bool alert = false;
String alertMsg = "Status: NORMAL";
if (heartRate < MIN_BPM || heartRate > MAX_BPM) {
alert = true;
alertMsg = "!! Abnormal BPM !!";
}
if (spO2 < MIN_SPO2) {
alert = true;
alertMsg = "!! Low SpO2 !!";
}
if (tempC > MAX_TEMP && tempC < 85) { // 85 = DS18B20 error value
alert = true;
alertMsg = "!! High Temp !!";
}
// --- Buzzer Control ---
digitalWrite(BUZZER_PIN, alert ? HIGH : LOW);
// --- Update OLED ---
display.clearDisplay();
display.setTextSize(1);
display.setCursor(0, 0);
display.println("== Health Monitor ==");
display.drawLine(0, 9, 127, 9, WHITE);
display.setCursor(0, 13);
display.print("Heart Rate: ");
display.print((int)heartRate);
display.println(" BPM");
display.setCursor(0, 27);
display.print("SpO2 : ");
display.print((int)spO2);
display.println(" %");
display.setCursor(0, 41);
display.print("Temp : ");
display.print(tempC, 1);
display.println(" C");
display.drawLine(0, 54, 127, 54, WHITE);
display.setCursor(0, 57);
if (alert) {
display.setTextColor(SSD1306_BLACK, SSD1306_WHITE); // inverted = highlight
display.println(alertMsg);
display.setTextColor(SSD1306_WHITE);
} else {
display.println(alertMsg);
}
display.display();
}
}