/*************************************************
* SMART HOSPITAL EMERGENCY &
* PATIENT HEALTH MONITORING SYSTEM V3.0
*
* Developer : Neev Prajapati
* Platform : ESP32
*************************************************/
//======================
// LIBRARIES
//======================
#define BLYNK_TEMPLATE_ID "TMPL3dhSv7N7q"
#define BLYNK_TEMPLATE_NAME "Smart Hospital"
#define BLYNK_AUTH_TOKEN "bhCsXH8Xuv8fdshYmmRc2zGJjeVHwBBf"
#include <WiFi.h>
#include <BlynkSimpleEsp32.h>
#include <Wire.h>
#include <DHT.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <HTTPClient.h>
const unsigned char hospitalLogo[] PROGMEM = {
0x03,0xC0,
0x03,0xC0,
0x03,0xC0,
0xFF,0xFF,
0xFF,0xFF,
0x03,0xC0,
0x03,0xC0,
0x03,0xC0,
0x03,0xC0,
0x03,0xC0,
0x03,0xC0,
0x00,0x00,
0x00,0x00,
0x00,0x00,
0x00,0x00,
0x00,0x00
};
//======================
// WIFI
//======================
char ssid[] = "Wokwi-GUEST";
char pass[] = "";
//======================
// PIN DEFINITIONS
//======================
#define DHTPIN 15
#define DHTTYPE DHT22
#define BUTTON_PIN 4
#define BUZZER_PIN 18
#define RED_LED 25
#define GREEN_LED 26
#define HEART_PIN 34
#define SPO2_PIN 35
//======================
// LIMITS
//======================
#define TEMP_LIMIT 38.0
#define BPM_LOW 60
#define BPM_HIGH 100
#define SPO2_LIMIT 95
//======================
// OLED
//======================
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(
SCREEN_WIDTH,
SCREEN_HEIGHT,
&Wire,
OLED_RESET
);
DHT dht(DHTPIN,DHTTYPE);
//======================
// VARIABLES
//======================
float temperature;
float humidity;
int heartRate;
int spo2;
bool emergency=false;
bool buttonPressed=false;
String alertReason="NORMAL";
String patientName = "Neev.P";
String bedNumber = "ICU-01";
bool heartBlink = false;
unsigned long blinkTimer = 0;
//======================
// BLYNK TIMER
//======================
BlynkTimer timer;
//====================================
// FUNCTIONS
//====================================
void startupScreen() {
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
// Hospital Name
display.setTextSize(2);
display.setCursor(10,0);
display.println("SMART");
display.setCursor(5,18);
display.println("HOSPITAL");
// Version
display.setTextSize(1);
display.setCursor(42,42);
display.println("V6.0");
display.setCursor(12,54);
display.println("Loading...");
display.display();
// Loading Animation
for(int i=0;i<=100;i+=10){
display.fillRect(12,58,i,4,SSD1306_WHITE);
display.display();
delay(120);
}
delay(700);
display.clearDisplay();
display.setTextSize(1);
display.setCursor(18,8);
display.println("Developed By");
display.setCursor(8,24);
display.println("Neev Prajapati");
display.setCursor(20,48);
display.println("Patient Monitor");
display.drawBitmap(0, 0, hospitalLogo, 16, 16, SSD1306_WHITE);
display.display();
delay(2000);
}
void setup() {
Serial.begin(115200);
pinMode(RED_LED,OUTPUT);
pinMode(GREEN_LED,OUTPUT);
pinMode(BUZZER_PIN,OUTPUT);
pinMode(BUTTON_PIN,INPUT_PULLUP);
digitalWrite(RED_LED,LOW);
digitalWrite(GREEN_LED,HIGH);
digitalWrite(BUZZER_PIN,LOW);
dht.begin();
Wire.begin();
if(!display.begin(SSD1306_SWITCHCAPVCC,0x3C)){
Serial.println("OLED ERROR");
while(true);
}
startupScreen();
WiFi.begin(ssid, pass);
Serial.print("Connecting WiFi");
int retry = 0;
while (WiFi.status() != WL_CONNECTED && retry < 20) {
delay(500);
Serial.print(".");
retry++;
}
if (WiFi.status() == WL_CONNECTED) {
Serial.println("\nWiFi Connected");
Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass);
} else {
Serial.println("\nWiFi Connection Failed!");
}
Serial.println("Blynk Connected");
display.clearDisplay();
display.setTextSize(1);
display.setCursor(10,20);
display.println("SYSTEM READY");
display.display();
delay(2000);
delay(5000);
Blynk.logEvent("emergency_alert", "Test Notification from ESP32");
startTimer();
}
//====================================
// SENSOR READING
//====================================
void readSensors() {
temperature = dht.readTemperature();
humidity = dht.readHumidity();
// Heart Rate Simulation (40 - 140 BPM)
int heartRaw = analogRead(HEART_PIN);
heartRate = map(heartRaw, 0, 4095, 40, 140);
// SpO2 Simulation (85 - 100 %)
int spo2Raw = analogRead(SPO2_PIN);
spo2 = map(spo2Raw, 0, 4095, 85, 100);
buttonPressed = (digitalRead(BUTTON_PIN) == LOW);
emergency = false;
alertReason = "NORMAL";
// DHT Error
if (isnan(temperature) || isnan(humidity)) {
emergency = true;
alertReason = "DHT ERROR";
return;
}
// Temperature
if (temperature >= TEMP_LIMIT) {
emergency = true;
alertReason = "HIGH TEMP";
}
// Heart Rate
if (heartRate < BPM_LOW) {
emergency = true;
alertReason = "LOW BPM";
}
if (heartRate > BPM_HIGH) {
emergency = true;
alertReason = "HIGH BPM";
}
// SpO2
if (spo2 < SPO2_LIMIT) {
emergency = true;
alertReason = "LOW SPO2";
}
// Emergency Button
if (buttonPressed) {
emergency = true;
alertReason = "BUTTON PRESSED";
}
}
//====================================
// LED + BUZZER
//====================================
void updateAlarm() {
if (emergency) {
digitalWrite(RED_LED, HIGH);
digitalWrite(GREEN_LED, LOW);
tone(BUZZER_PIN, 1000);
} else {
digitalWrite(RED_LED, LOW);
digitalWrite(GREEN_LED, HIGH);
noTone(BUZZER_PIN);
}
}
//====================================
// OLED DISPLAY
//====================================
void updateOLED() {
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
display.setTextSize(1);
// Header
display.setCursor(0,0);
if (heartBlink)
display.print((char)3); // Heart Symbol
else
display.print(" ");
display.setCursor(12,0);
display.print("SMART");
display.setCursor(82,0);
if (WiFi.status() == WL_CONNECTED)
display.print("WiFi");
else
display.print("OFF");
// Patient
display.setCursor(0,12);
display.print("Name:");
display.println(patientName);
display.setCursor(0,22);
display.print("Bed :");
display.println(bedNumber);
// Temperature
display.setCursor(0,34);
display.print("T:");
display.print(temperature,1);
display.print("C");
// Heart Rate
display.setCursor(70,34);
display.print("HR:");
display.print(heartRate);
// SpO2
display.setCursor(0,46);
display.print("O2:");
display.print(spo2);
display.print("%");
// Humidity
display.setCursor(70,46);
display.print("H:");
display.print(humidity,0);
display.print("%");
// Status
display.setCursor(0,58);
if (emergency) {
if (alertReason == "LOW SPO2")
display.print("ALERT: LOW O2");
else if (alertReason == "HIGH TEMP")
display.print("ALERT: HI TEMP");
else if (alertReason == "LOW BPM")
display.print("ALERT: LOW BPM");
else if (alertReason == "HIGH BPM")
display.print("ALERT: HI BPM");
else if (alertReason == "BUTTON PRESSED")
display.print("EMERGENCY!");
else
display.print(alertReason);
} else {
display.print("STATUS:NORMAL");
}
display.display();
}
//====================================
// SERIAL MONITOR
//====================================
void serialReport(){
Serial.println("--------------------------------");
Serial.print("Temperature : ");
Serial.println(temperature);
Serial.print("Humidity : ");
Serial.println(humidity);
Serial.print("Heart Rate : ");
Serial.println(heartRate);
Serial.print("SpO2 : ");
Serial.println(spo2);
Serial.print("Status : ");
Serial.println(alertReason);
}
//====================================
// BLYNK UPDATE
//====================================
void sendToBlynk(){
Blynk.virtualWrite(V0,temperature);
Blynk.virtualWrite(V1,humidity);
Blynk.virtualWrite(V2,heartRate);
Blynk.virtualWrite(V3,spo2);
Blynk.virtualWrite(V4,alertReason);
}
//====================================
// PUSH NOTIFICATION
//====================================
void sendEmergencyNotification(){
static bool alreadySent=false;
if(emergency && !alreadySent){
Blynk.logEvent(
"emergency_alert",
String("Patient P001 | ")+alertReason+
" | Temp:"+String(temperature,1)+
"C | BPM:"+String(heartRate)+
" | SpO2:"+String(spo2)+"%"
);
sendEmailAlert();
alreadySent=true;
}
if(!emergency){
alreadySent=false;
}
}
void updateAnimation() {
if (millis() - blinkTimer > 500) {
blinkTimer = millis();
heartBlink = !heartBlink;
}
}
//====================================
// TIMER TASK
//====================================
void hospitalTask() {
updateAnimation();
readSensors();
updateAlarm();
updateOLED();
serialReport();
sendToBlynk();
sendEmergencyNotification();
}
//====================================
// LOOP
//====================================
void loop() {
Blynk.run();
timer.run();
}
//====================================
// START TIMER
//====================================
void startTimer(){
timer.setInterval(
1000L,
hospitalTask
);
}
void sendEmailAlert() {
if (WiFi.status() != WL_CONNECTED) return;
HTTPClient http;
String url = "https://script.google.com/macros/s/AKfycbwdkXwpym1hbin0KRpZTqnG_FNeJCd2m5ihvYJmDIVXIZ6Y7fsOA-uPPgl_5H3TG3JQ/exec";
url += "?patient=P001";
url += "&temp=" + String(temperature, 1);
url += "&bpm=" + String(heartRate);
url += "&spo2=" + String(spo2);
url += "&reason=" + alertReason;
http.begin(url);
int code = http.GET();
Serial.print("Email HTTP Code: ");
Serial.println(code);
http.end();
}