This project implements a simple, low-cost smoke and gas detection system using an ESP32 microcontroller, an MQ-2 gas sensor, and an active buzzer. The system reads analog gas/smoke concentration values via the MQ-2 sensor and sends this data periodically to a Firebase Realtime Database.
When dangerous gas levels are detected (above a configurable threshold — 300 in this project), the system triggers an audible alarm using a connected buzzer and sends an immediate alert email via IFTTT Webhooks integration.
A web-based frontend fetches data from Firebase and visualizes it using a graph, with gas/smoke values on the Y-axis and timestamps (converted from UNIX time) on the X-axis, displayed at regular 3-minute intervals.
🧩 Components
🖥️ Frontend
☁️ Backend
📟 Embedded Software (ESP32)
Developed using the Arduino Framework, with the following libraries:
📝 Code snippet
#include <Arduino.h>
#include <WiFi.h>
#include <Firebase_ESP_Client.h>
#include "addons/TokenHelper.h"
#include "addons/RTDBHelper.h"
#include <HTTPClient.h>
#define IFTTT_URL ""
#define WIFI_SSID ""
#define WIFI_PASSWORD ""
#define API_KEY ""
#define DATABASE_URL ""
#define MQ2_PIN 23
#define BUZZER_PIN 22
// Firebase objects
FirebaseData fbdo;
FirebaseAuth auth;
FirebaseConfig config;
unsigned long sendDataPrevMillis = 0;
bool signupOK = false;
void triggerIFTTT() {
if (WiFi.status() == WL_CONNECTED) {
HTTPClient http;
http.begin(IFTTT_URL);
int httpResponseCode = http.GET();
if (httpResponseCode > 0) {
Serial.print("IFTTT triggered, code: ");
Serial.println(httpResponseCode);
} else {
Serial.print("IFTTT trigger failed: ");
Serial.println(http.errorToString(httpResponseCode).c_str());
}
http.end();
}
}
void setup() {
Serial.begin(115200);
pinMode(MQ2_PIN, INPUT);
pinMode(BUZZER_PIN, OUTPUT);
digitalWrite(BUZZER_PIN, LOW);
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
Serial.print("Connecting to Wi-Fi");
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(300);
}
Serial.println();
Serial.print("Connected with IP: ");
Serial.println(WiFi.localIP());
config.api_key = API_KEY;
config.database_url = DATABASE_URL;
if (Firebase.signUp(&config, &auth, "", "")) {
Serial.println("Firebase signup OK");
signupOK = true;
} else {
Serial.printf("Signup failed: %s\n", config.signer.signupError.message.c_str());
}
config.token_status_callback = tokenStatusCallback;
Firebase.begin(&config, &auth);
Firebase.reconnectWiFi(true);
}
void loop() {
if (Firebase.ready() && signupOK && (millis() - sendDataPrevMillis > 5000)) {
sendDataPrevMillis = millis();
int smokeValue = analogRead(MQ2_PIN);
Serial.print("MQ-2 Sensor value: ");
Serial.println(smokeValue);
// Control buzzer
if (smokeValue > 300) {
digitalWrite(BUZZER_PIN, HIGH);
triggerIFTTT();
} else {
digitalWrite(BUZZER_PIN, LOW);
}
unsigned long currentTimestamp = Firebase.getCurrentTime();
String path = "/logs/" + String(currentTimestamp) + "/value";
if (Firebase.RTDB.setInt(&fbdo, path.c_str(), smokeValue)) {
Serial.print("Data sent: ");
Serial.print(smokeValue);
Serial.print(" at ");
Serial.println(currentTimestamp);
} else {
Serial.print("Send failed: ");
Serial.println(fbdo.errorReason());
}
}
}
📱 Web