#define BLYNK_TEMPLATE_ID "TMPL5gSEQ64Uf"
#define BLYNK_TEMPLATE_NAME "Smart Fire Detector"
#define BLYNK_AUTH_TOKEN "9Cj5smxpz9WfT6pvI38KKxlz3FtoQyiN"
#include <WiFi.h>
#include <BlynkSimpleEsp32.h>
#include <DHTesp.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// Firebase Includes
#include <FirebaseESP32.h>
#include <WiFiClientSecure.h>
#include "addons/TokenHelper.h"
#include "addons/RTDBHelper.h"
// Firebase Configuration
#define DATABASE_URL "https://smartfiredetection-10df0-default-rtdb.firebaseio.com"
#define DATABASE_SECRET "3L2oFshye7sggdAHUTtZ03hAzQ3iGutGD4TJjVwJ"
FirebaseData fbdo;
FirebaseAuth auth;
FirebaseConfig config;
char ssid[] = "Wokwi-GUEST";
char pass[] = "";
// Pin Definitions
#define DHTPIN 21
#define GAS_SENSOR_PIN 34
#define FLAME_SENSOR_PIN 33
#define BUZZER_PIN 5
#define LED_ANODE_PIN 18
#define LED_CATHODE_PIN 19
#define POWER_SENSOR_PIN 35
#define TEMP_THRESHOLD 57.0
#define GAS_THRESHOLD 3000
#define HUMIDITY_THRESHOLD 80.0
#define FLAME_THRESHOLD 2000
#define POWER_THRESHOLD 1000
DHTesp dht;
LiquidCrystal_I2C lcd(0x27, 16, 2);
bool manualOverride = false;
float simTemperature = 24.0;
float simHumidity = 40.0;
int simGasValue = 1500;
int simFlameValue = LOW;
bool gasInitialized = false;
unsigned long previousBlinkTime = 0;
bool alarmState = LOW;
const unsigned long blinkInterval = 500;
String zoneStatus[3] = {"Safe", "Safe", "Safe"};
unsigned long dangerStartTime = 0;
const unsigned long dangerHoldDuration = 10000;
bool previousFireDetected = false;
int lastDangerZone = -1;
BLYNK_WRITE(V4) {
manualOverride = param.asInt();
Serial.println(manualOverride ? "โ
Manual override ENABLED from app" : "๐ Manual override DISABLED from app");
}
void setup() {
Serial.begin(115200);
dht.setup(DHTPIN, DHTesp::DHT22);
pinMode(BUZZER_PIN, OUTPUT);
pinMode(LED_ANODE_PIN, OUTPUT);
pinMode(LED_CATHODE_PIN, OUTPUT);
pinMode(POWER_SENSOR_PIN, INPUT);
digitalWrite(BUZZER_PIN, LOW);
digitalWrite(LED_ANODE_PIN, LOW);
digitalWrite(LED_CATHODE_PIN, LOW);
Wire.begin(23, 22);
lcd.init();
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print("Fire Detector");
delay(1500);
lcd.clear();
Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass);
Serial.println("๐ฅ Fire Detection System with Blynk Started");
// Firebase Config
config.database_url = DATABASE_URL;
config.signer.tokens.legacy_token = DATABASE_SECRET;
Firebase.begin(&config, &auth);
Firebase.reconnectWiFi(true);
Serial.println("โ
Firebase Initialized");
}
void assignStableDangerZone(bool fireDetected) {
if (!fireDetected) {
if (previousFireDetected) {
for (int i = 0; i < 3; i++) zoneStatus[i] = "Safe";
lastDangerZone = -1;
}
previousFireDetected = false;
return;
}
if (previousFireDetected && (millis() - dangerStartTime < dangerHoldDuration)) {
for (int i = 0; i < 3; i++) {
zoneStatus[i] = (i == lastDangerZone) ? "Danger" : "Safe";
}
return;
}
lastDangerZone = random(0, 3);
dangerStartTime = millis();
previousFireDetected = true;
for (int i = 0; i < 3; i++) {
zoneStatus[i] = (i == lastDangerZone) ? "Danger" : "Safe";
}
Serial.println("โ ๏ธ Fire hazard in Zone " + String(char('A' + lastDangerZone)));
}
void sendZoneStatusToBlynk() {
for (int i = 0; i < 3; i++) {
String zoneLabel = "Zone " + String(char('A' + i)) + ": " + zoneStatus[i];
Blynk.virtualWrite(V6 + i, zoneLabel);
Blynk.virtualWrite(V10 + i, zoneStatus[i] == "Safe" ? 0 : 1);
}
}
void recommendEvacuationPath(bool fireDetected) {
if (!fireDetected) {
Blynk.virtualWrite(V9, "โ
All Zones Safe");
return;
}
String safeZones = "";
for (int i = 0; i < 3; i++) {
if (zoneStatus[i] == "Safe") {
safeZones += String(char('A' + i)) + " ";
}
}
if (safeZones.length() > 0) {
Blynk.virtualWrite(V9, "๐ Evacuate to Zone(s): " + safeZones);
} else {
Blynk.virtualWrite(V9, "โ All zones unsafe! Stay put & wait for help");
}
}
void updateLCD() {
lcd.clear();
if (lastDangerZone != -1) {
lcd.setCursor(0, 0);
lcd.print("Danger: Zone ");
lcd.print((char)('A' + lastDangerZone));
lcd.setCursor(0, 1);
lcd.print("Safe: ");
for (int i = 0; i < 3; i++) {
if (i != lastDangerZone) {
lcd.print((char)('A' + i));
lcd.print(" ");
}
}
} else {
lcd.setCursor(0, 0);
lcd.print("System Normal");
lcd.setCursor(0, 1);
lcd.print("All Zones Safe");
}
}
void checkPowerLoss() {
int powerValue = analogRead(POWER_SENSOR_PIN);
bool powerLoss = powerValue < POWER_THRESHOLD;
Serial.print("๐ Power level: ");
Serial.println(powerValue);
if (powerLoss) {
Blynk.virtualWrite(V4, "โ ๏ธ Power Loss Detected!");
} else {
Blynk.virtualWrite(V4, "๐ Power OK");
}
}
void reconnectWiFi() {
if (WiFi.status() != WL_CONNECTED) {
Serial.println("๐ WiFi disconnected, trying to reconnect...");
WiFi.disconnect();
WiFi.begin(ssid, pass);
}
}
void uploadToFirebase(float temp, float hum, int gas, int flame, bool fireDetected) {
Firebase.setFloat(fbdo, "/temperature", temp);
Firebase.setFloat(fbdo, "/humidity", hum);
Firebase.setInt(fbdo, "/gasValue", gas);
Firebase.setInt(fbdo, "/flameDetected", flame);
Firebase.setBool(fbdo, "/fireDetected", fireDetected);
Firebase.setString(fbdo, "/zoneA", zoneStatus[0]);
Firebase.setString(fbdo, "/zoneB", zoneStatus[1]);
Firebase.setString(fbdo, "/zoneC", zoneStatus[2]);
}
void loop() {
Blynk.run();
reconnectWiFi();
float temperature, humidity;
int gasValue, flameDetected;
if (manualOverride) {
temperature = simTemperature;
humidity = simHumidity;
gasValue = simGasValue;
flameDetected = simFlameValue;
} else {
TempAndHumidity data = dht.getTempAndHumidity();
temperature = isnan(data.temperature) ? 25.0 : data.temperature;
humidity = isnan(data.humidity) ? 50.0 : data.humidity;
int rawGas = analogRead(GAS_SENSOR_PIN);
if (!gasInitialized) {
gasValue = 1500;
gasInitialized = true;
} else {
gasValue = rawGas;
}
int flameAnalog = analogRead(FLAME_SENSOR_PIN);
flameDetected = (flameAnalog > FLAME_THRESHOLD) ? HIGH : LOW;
}
Serial.printf("๐ก Temp: %.2fยฐC | ๐ง Humidity: %.2f%% | ๐งช Gas: %d | ๐ฅ Flame: %s\n",
temperature, humidity, gasValue, flameDetected == HIGH ? "Yes" : "No");
Blynk.virtualWrite(V0, temperature);
Blynk.virtualWrite(V1, humidity);
Blynk.virtualWrite(V2, gasValue);
Blynk.virtualWrite(V3, flameDetected == HIGH ? 1 : 0);
bool fireDetected = (temperature > TEMP_THRESHOLD) || (gasValue > GAS_THRESHOLD) ||
(flameDetected == HIGH) || (humidity > HUMIDITY_THRESHOLD);
assignStableDangerZone(fireDetected);
sendZoneStatusToBlynk();
recommendEvacuationPath(fireDetected);
updateLCD();
checkPowerLoss();
// Firebase upload
uploadToFirebase(temperature, humidity, gasValue, flameDetected, fireDetected);
if (fireDetected) {
Blynk.virtualWrite(V5, "๐จ FIRE DETECTED! Please check immediately!");
unsigned long currentMillis = millis();
if (currentMillis - previousBlinkTime >= blinkInterval) {
previousBlinkTime = currentMillis;
alarmState = !alarmState;
if (alarmState) {
tone(BUZZER_PIN, 1000);
digitalWrite(LED_ANODE_PIN, HIGH);
digitalWrite(LED_CATHODE_PIN, LOW);
} else {
noTone(BUZZER_PIN);
digitalWrite(LED_ANODE_PIN, LOW);
digitalWrite(LED_CATHODE_PIN, LOW);
}
}
} else {
noTone(BUZZER_PIN);
digitalWrite(LED_ANODE_PIN, LOW);
digitalWrite(LED_CATHODE_PIN, LOW);
alarmState = LOW;
Blynk.virtualWrite(V5, "Safe");
}
delay(500);
}