#include <WiFi.h>
#include <PubSubClient.h>
#include <HTTPClient.h>
#include <Wire.h>
#include <Adafruit_SSD1306.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <HX711.h>
#include <SD.h>
#include <SPI.h>
// OLED
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
// Sensor pins
#define ECG_PIN 36
#define ONE_WIRE_BUS 4
#define DOUT 25
#define CLK 26
#define HR_PIN 35
#define SPO2_PIN 32
#define SYS_PIN 33
#define DIA_PIN 34
#define MOTION_PIN 14
// Buzzer & LED
#define BUZZER_PIN 13
#define LED_PIN 12
// SD card
#define SD_CS 5
// WiFi / MQTT / ThingSpeak
const char* ssid = "Wokwi-GUEST";
const char* password = "";
const char* mqttServer = "broker.hivemq.com";
const int mqttPort = 1883;
const char* patientID = "PT-001";
const char* thingspeakServer = "http://api.thingspeak.com/update";
String apiKey = "J3WIA5NRCOU54Q9I";
//object initialization
WiFiClient espClient;
PubSubClient client(espClient);
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
HX711 scale;
// Helper functions(Timestamp Funtion)
String getTimestamp() {
char buf[20];
sprintf(buf, "%04d-%02d-%02d %02d:%02d:%02d", 2025,8,20,22,15,0);
return String(buf);
}
//Log to SD
void logToSD(String line) {
File f = SD.open("/data.csv", FILE_APPEND);
if (f) { f.println(line); f.close(); Serial.println("Logged to SD"); }
else Serial.println("SD write error");
}
//MQTT Reconnect
void reconnectMQTT() {
while (!client.connected()) {
Serial.print("Connecting to MQTT...");
if (client.connect(patientID)) Serial.println("Connected");
else { Serial.print("Failed, rc="); Serial.print(client.state()); Serial.println(" try again in 2s"); delay(2000); }
}
}
//WiFi Init(WiFi connect to ESP32)
void initWiFi() {
WiFi.begin(ssid, password);
Serial.print("Connecting to WiFi");
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(500);
}
Serial.println("\nWiFi connected");
}
//ThingSpeak Funtion (Patient data send to ThingSpeak)
void sendToThingSpeak(int hr, int spo2, int sys, int dia, float temp, float weight, int motion, String condition) {
if (WiFi.status() == WL_CONNECTED) {
HTTPClient http;
http.begin(thingspeakServer);
http.addHeader("Content-Type", "application/x-www-form-urlencoded");
String post = "api_key=" + apiKey +
"&field1=" + String(hr) +
"&field2=" + String(spo2) +
"&field3=" + String(sys) +
"&field4=" + String(dia) +
"&field5=" + String(temp, 2) +
"&field6=" + String(weight, 2) +
"&field7=" + String(motion) +
"&field8=" + condition;
int code = http.POST(post);
if (code > 0) Serial.println("Data sent to ThingSpeak successfully");
else Serial.println("Error sending data to ThingSpeak");
http.end();
} else Serial.println("WiFi not connected");
}
void setup() {
Serial.begin(115200); //Serial Monitor on for debugging
display.begin(SSD1306_SWITCHCAPVCC, 0x3C); //OLED Displaye initialize
display.clearDisplay(); display.display();
sensors.begin(); //DS18B20 temparature sensor on
scale.begin(DOUT, CLK); //Scale is HX711 Library Object (load cell initialize)
scale.set_scale(2280.f); // set Calibration factor(convert ADC to kg/g)
scale.tare(); //reset scale(measure from 0)
//Set input/output pin mode
pinMode(BUZZER_PIN, OUTPUT);
pinMode(LED_PIN, OUTPUT);
pinMode(MOTION_PIN, INPUT);
SPI.begin();// SD card SPI communication on
if (!SD.begin(SD_CS)) Serial.println("SD init failed!"); //check SD card connection
else if (!SD.exists("/data.csv")) { // check previous data.csv file
File f = SD.open("/data.csv", FILE_WRITE); // open data.csv file in write mode
if (f) { f.println("Timestamp,PatientID,HR,SpO2,Sys,Dia,Temp,Weight,Motions,Status"); f.close(); } //csv header file formate and .close use for save data right properly
}
initWiFi(); //connect ESP32 to Wifi
client.setServer(mqttServer, mqttPort); //set MQTT broker's IP/port (use data publish/subscribe)
}
// check MQTT is connected to ESP32
void loop() {
if (!client.connected()) reconnectMQTT();
client.loop();
//convert Analog sensor value into Digital(0=0v and 4095=3.3v)
int hr = map(analogRead(HR_PIN), 0, 4095, 30, 150); //convert sensor voltage value into bpm
int spo2 = map(analogRead(SPO2_PIN), 0, 4095, 80, 100); //convert Spo2 sensor voltage value into Oxygen Saturation (%)
int sys = map(analogRead(SYS_PIN), 0, 4095, 70, 190); //cnvert Systolic Blood Pressure(mmHg)
int dia = map(analogRead(DIA_PIN), 0, 4095, 40, 120); // convert Diastolic Blood Pressure (mmHg)
int ecg = analogRead(ECG_PIN); // ecg sensor read direct ADC value
sensors.requestTemperatures(); // sensor is DallasTemperature library(request to measure temp)
float temp = sensors.getTempCByIndex(0);// read temp in index 0 (C)
float weight = scale.get_units(5); if (weight < 0) weight = 0; //scale is HX711 library take 5 measurement and calculate the mean,if measure (-) value then set 0
bool motion = digitalRead(MOTION_PIN); // PIR motion sensor. 1 motion detect. 0 no motion.
// check patient condition
String condition = "Stable";
if (hr < 40 || hr > 150 || spo2 < 75 || sys < 60 || dia < 40) condition = "CRITICAL";
else if (hr < 50 || hr > 130 || spo2 < 85 || sys > 180 || dia > 110) condition = "EMERGENCY";
else if (hr < 60 || hr > 100 || spo2 < 92 || sys > 140 || dia > 90 || temp > 37.5) condition = "WARNING";
//Alarm control
if (condition == "CRITICAL") { tone(BUZZER_PIN, 1500); digitalWrite(LED_PIN, HIGH); } // sound in 1500 Hz Frequency
else { noTone(BUZZER_PIN); digitalWrite(LED_PIN, LOW); }
// Show patient data in OLEd display
display.clearDisplay(); // clear OLED Display
display.setCursor(0, 0); // set the writing place
display.printf("HR:%d SpO2:%d\nBP:%d/%d\nT:%.1f W:%.1f\n ECG:%d\nStatus:%s",
hr, spo2, sys, dia, temp, weight, condition.c_str());
display.display();
String payload = "{\"PatientID\":\"" + String(patientID) + "\"," +
"\"HR\":" + String(hr) + "," +
"\"SpO2\":" + String(spo2) + "," +
"\"Sys\":" + String(sys) + "," +
"\"Dia\":" + String(dia) + "," +
"\"ECG\":" + String(ecg) + "," +
"\"Temp\":" + String(temp, 2) + "," +
"\"Weight\":" + String(weight, 2) + "," +
"\"Motion\":" + String(motion) + "," +
"\"Status\":\"" + condition + "\"}";
client.publish(("ICU/patient/" + String(patientID)).c_str(), payload.c_str());
logToSD(getTimestamp() + "," + String(patientID) + "," +
String(hr) + "," + String(spo2) + "," + String(sys) + "," +
String(dia) + "," + String(temp, 2) + "," + String(weight, 2) + "," +
String(motion) + "," + condition);
Serial.println("Logged to SD");
Serial.println("Sent: " + payload);
sendToThingSpeak(hr, spo2, sys, dia, temp, weight, motion, condition);
delay(2000);
}
Loading
ds18b20
ds18b20