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