/*
ESP32 Enhanced Fire Alarm System
- Multi-sensor fire detection (MQ-2, DHT22, Flame sensor)
- WiFi connectivity for remote monitoring
- MQTT for IoT integration
- Mobile notifications
- Data logging
- Self-diagnostics
- Manual controls
*/
#include <WiFi.h>
#include <PubSubClient.h>
#include <DHT.h>
#include <WiFiClient.h>
#include <LiquidCrystal_I2C.h>
#include <SD.h>
#include <SPI.h>
#include <esp_wifi.h>
// WiFi credentials
const char* ssid = "YOUR_WIFI_SSID";
const char* password = "YOUR_WIFI_PASSWORD";
// MQTT broker details
const char* mqtt_server = "broker.hivemq.com";
const int mqtt_port = 1883;
const char* mqtt_topic = "firealarm/alerts";
const char* mqtt_status = "firealarm/status";
// Pin definitions
#define MQ2_PIN A0 // MQ-2 smoke sensor
#define FLAME_PIN 4 // Flame sensor
#define DHT_PIN 15 // DHT22 temperature sensor
#define BUZZER_PIN 25 // Active buzzer
#define LED_RED 26 // Red LED
#define LED_GREEN 27 // Green LED
#define LED_BLUE 14 // Blue LED
#define RESET_BUTTON 12 // Reset/silence button
#define TEST_BUTTON 13 // Test button
#define RELAY_PIN 23 // Relay for external devices
#define SD_CS 5 // SD card chip select
// Sensor objects
DHT dht(DHT_PIN, DHT22);
LiquidCrystal_I2C lcd(0x27, 16, 2);
// WiFi and MQTT clients
WiFiClient espClient;
PubSubClient client(espClient);
// Threshold values
const int SMOKE_THRESHOLD = 400; // Adjust based on calibration
const int FLAME_THRESHOLD = 500; // Flame sensor threshold
const float TEMP_THRESHOLD = 60.0; // Temperature threshold in Celsius
// System variables
bool fireDetected = false;
bool systemArmed = true;
bool alarmSilenced = false;
unsigned long lastAlertTime = 0;
unsigned long lastSensorRead = 0;
unsigned long lastWiFiAttempt = 0;
unsigned long lastMQTTAttempt = 0;
int alertCount = 0;
float temperature = 0.0;
int smokeLevel = 0;
int flameLevel = 0;
String systemStatus = "Normal";
// Timing constants
const unsigned long SENSOR_INTERVAL = 2000; // Read sensors every 2 seconds
const unsigned long WIFI_RETRY_INTERVAL = 30000; // Retry WiFi every 30 seconds
const unsigned long MQTT_RETRY_INTERVAL = 15000; // Retry MQTT every 15 seconds
const unsigned long ALERT_COOLDOWN = 60000; // 1 minute between alerts
// Function prototypes
void setupWiFi();
void reconnectMQTT();
void readSensors();
bool detectFire();
void triggerAlarm(String type);
void resetAlarm();
void testSystem();
void updateLCD();
void logData();
void sendNotification(String message);
void setupMQTT();
void callback(char* topic, byte* payload, unsigned int length);
void setup() {
Serial.begin(115200);
// Initialize pins
pinMode(BUZZER_PIN, OUTPUT);
pinMode(LED_RED, OUTPUT);
pinMode(LED_GREEN, OUTPUT);
pinMode(LED_BLUE, OUTPUT);
pinMode(RELAY_PIN, OUTPUT);
pinMode(RESET_BUTTON, INPUT_PULLUP);
pinMode(TEST_BUTTON, INPUT_PULLUP);
pinMode(FLAME_PIN, INPUT);
// Initialize sensors
dht.begin();
// Initialize LCD
lcd.init();
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print("ESP32 Fire Alarm");
lcd.setCursor(0, 1);
lcd.print("Initializing...");
// Initialize SD card
if (!SD.begin(SD_CS)) {
Serial.println("SD Card initialization failed!");
} else {
Serial.println("SD Card initialized successfully");
}
// Setup WiFi
setupWiFi();
// Setup MQTT
setupMQTT();
// Initial LED state
digitalWrite(LED_GREEN, HIGH);
digitalWrite(LED_RED, LOW);
digitalWrite(LED_BLUE, LOW);
delay(2000);
Serial.println("ESP32 Fire Alarm System Ready!");
}
void loop() {
unsigned long currentMillis = millis();
// Maintain WiFi connection
if (WiFi.status() != WL_CONNECTED) {
if (currentMillis - lastWiFiAttempt > WIFI_RETRY_INTERVAL) {
setupWiFi();
lastWiFiAttempt = currentMillis;
}
}
// Maintain MQTT connection
if (!client.connected()) {
if (currentMillis - lastMQTTAttempt > MQTT_RETRY_INTERVAL) {
reconnectMQTT();
lastMQTTAttempt = currentMillis;
}
}
client.loop();
// Read sensors periodically
if (currentMillis - lastSensorRead > SENSOR_INTERVAL) {
readSensors();
updateLCD();
logData();
if (detectFire() && systemArmed && !alarmSilenced) {
if (currentMillis - lastAlertTime > ALERT_COOLDOWN) {
triggerAlarm("FIRE_DETECTED");
lastAlertTime = currentMillis;
}
}
lastSensorRead = currentMillis;
}
// Check reset button
if (digitalRead(RESET_BUTTON) == LOW) {
delay(50); // Debounce
if (digitalRead(RESET_BUTTON) == LOW) {
resetAlarm();
while (digitalRead(RESET_BUTTON) == LOW); // Wait for release
}
}
// Check test button
if (digitalRead(TEST_BUTTON) == LOW) {
delay(50); // Debounce
if (digitalRead(TEST_BUTTON) == LOW) {
testSystem();
while (digitalRead(TEST_BUTTON) == LOW); // Wait for release
}
}
}
void setupWiFi() {
Serial.print("Connecting to WiFi");
WiFi.begin(ssid, password);
int attempts = 0;
while (WiFi.status() != WL_CONNECTED && attempts < 20) {
delay(500);
Serial.print(".");
attempts++;
}
if (WiFi.status() == WL_CONNECTED) {
Serial.println();
Serial.print("Connected! IP address: ");
Serial.println(WiFi.localIP());
digitalWrite(LED_BLUE, HIGH);
} else {
Serial.println("WiFi connection failed!");
digitalWrite(LED_BLUE, LOW);
}
}
void setupMQTT() {
client.setServer(mqtt_server, mqtt_port);
client.setCallback(callback);
}
void reconnectMQTT() {
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
String clientId = "ESP32FireAlarm-" + String(random(0xffff), HEX);
if (client.connect(clientId.c_str())) {
Serial.println("connected");
client.publish(mqtt_status, "ESP32 Fire Alarm Online");
client.subscribe("firealarm/control");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
delay(5000);
}
}
}
void callback(char* topic, byte* payload, unsigned int length) {
String message = "";
for (int i = 0; i < length; i++) {
message += (char)payload[i];
}
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
Serial.println(message);
if (message == "reset") {
resetAlarm();
} else if (message == "test") {
testSystem();
} else if (message == "arm") {
systemArmed = true;
sendNotification("System armed via MQTT");
} else if (message == "disarm") {
systemArmed = false;
sendNotification("System disarmed via MQTT");
}
}
void readSensors() {
smokeLevel = analogRead(MQ2_PIN);
flameLevel = analogRead(FLAME_PIN);
temperature = dht.readTemperature();
Serial.print("Smoke: ");
Serial.print(smokeLevel);
Serial.print(" | Flame: ");
Serial.print(flameLevel);
Serial.print(" | Temp: ");
Serial.print(temperature);
Serial.println("°C");
}
bool detectFire() {
bool smokeAlert = smokeLevel > SMOKE_THRESHOLD;
bool flameAlert = flameLevel > FLAME_THRESHOLD;
bool tempAlert = temperature > TEMP_THRESHOLD;
if (smokeAlert || flameAlert || tempAlert) {
String alertType = "";
if (smokeAlert) alertType += "SMOKE ";
if (flameAlert) alertType += "FLAME ";
if (tempAlert) alertType += "HIGH_TEMP";
systemStatus = alertType;
return true;
}
systemStatus = "Normal";
return false;
}
void triggerAlarm(String type) {
fireDetected = true;
alertCount++;
// Activate outputs
digitalWrite(BUZZER_PIN, HIGH);
digitalWrite(LED_RED, HIGH);
digitalWrite(LED_GREEN, LOW);
digitalWrite(RELAY_PIN, HIGH);
// Update display
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("FIRE DETECTED!");
lcd.setCursor(0, 1);
lcd.print(systemStatus);
// Send notifications
String alertMsg = "FIRE ALERT! Smoke:" + String(smokeLevel) +
" Flame:" + String(flameLevel) +
" Temp:" + String(temperature) + "C";
sendNotification(alertMsg);
// Log to SD card
logData();
Serial.println("FIRE DETECTED - ALARM TRIGGERED!");
}
void resetAlarm() {
fireDetected = false;
alarmSilenced = false;
// Deactivate outputs
digitalWrite(BUZZER_PIN, LOW);
digitalWrite(LED_RED, LOW);
digitalWrite(LED_GREEN, HIGH);
digitalWrite(RELAY_PIN, LOW);
// Update display
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("System Reset");
lcd.setCursor(0, 1);
lcd.print("Monitoring...");
sendNotification("Fire alarm reset");
Serial.println("Alarm reset");
}
void testSystem() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Testing...");
// Test sequence
digitalWrite(LED_RED, HIGH);
digitalWrite(BUZZER_PIN, HIGH);
delay(1000);
digitalWrite(LED_RED, LOW);
digitalWrite(LED_GREEN, HIGH);
delay(500);
digitalWrite(LED_GREEN, LOW);
digitalWrite(LED_BLUE, HIGH);
delay(500);
// Reset all
digitalWrite(BUZZER_PIN, LOW);
digitalWrite(LED_RED, LOW);
digitalWrite(LED_GREEN, HIGH);
digitalWrite(LED_BLUE, LOW);
sendNotification("Fire alarm system test completed");
Serial.println("System test completed");
}
void updateLCD() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("T:" + String(temperature, 1) + " S:" + String(smokeLevel) + " F:" + String(flameLevel));
lcd.setCursor(0, 1);
lcd.print(systemStatus);
}
void logData() {
if (!SD.begin(SD_CS)) return;
File dataFile = SD.open("/firelog.txt", FILE_APPEND);
if (dataFile) {
dataFile.print(millis());
dataFile.print(",");
dataFile.print(temperature);
dataFile.print(",");
dataFile.print(smokeLevel);
dataFile.print(",");
dataFile.print(flameLevel);
dataFile.print(",");
dataFile.println(systemStatus);
dataFile.close();
}
}
void sendNotification(String message) {
// MQTT notification
if (client.connected()) {
client.publish(mqtt_topic, message.c_str());
}
// Serial notification
Serial.println("ALERT: " + message);
// Here you can add Blynk, Pushover, or other notification services
// Example: Blynk.email("[email protected]", "Fire Alert", message);
}