IoTSimulator

Arduino Fire Alarm & Gas Leak Detector with Siren and Relay

Build a dual-threat hazard monitor that spots flames and gas leaks simultaneously using an Arduino, flame sensor, gas sensor, emergency relay exhaust, and loud audio alarm.
Muhammad Ichsanul Fadhil
IoTSimulator Team
October 25, 2026
Arduino Fire Alarm & Gas Leak Detector with Siren and Relay

Live project track

Interactive hardware & logic preview

Imagine walking into a workshop, a bakery kitchen, or a home garage. In a busy room, danger can arrive quietly in two completely different ways. An unlit stove burner can leak invisible gas into the air without any sound. Or, a stray spark can jump onto dry cardboard and create an open flame in a split second.

If you only have a smoke detector, a dangerous gas leak might fill the room completely before anyone notices. If you only have a gas sniffer, an electrical fire can spread before the gas sensor even warms up. That is why real industrial workshops use dual-threat safety monitors that watch for both hazards at the exact same time.

In this project, you will build an automated safety station using an Arduino Uno, an optical flame sensor, an MQ gas sensor, an LCD screen, an emergency relay exhaust fan, and an audible warning siren. The core concept you will master is: parallel environmental monitoring — reading two distinct physical sensors in real time and triggering instant hardware safety actions before danger spreads.

Before examining individual circuit connections, study the complete safety station architecture below. It shows how the optical flame detector, combustible gas sensor, isolation relay, and dual-tone alert sirens combine into an industrial protection node:

Two human senses analogy comparing eyes and nose to optical and gas sensors
Two human senses analogy comparing eyes and nose to optical and gas sensors

As depicted in the overview, detecting either smoke or flame triggers an immediate, multi-stage containment sequence. In the next section, we analyze how optical infrared photodiodes and electrochemical gas sensors translate environmental hazards into millivolt electrical signals.

Part 1 — Understand the Core Idea: Eyes and Nose Working Together

To understand how this system works, think about how your own body stays safe. You do not just rely on one sense. You use your eyes to spot a burning candle, and you use your nose to smell escaping cooking gas or burning toast in another room.

Our Arduino safety station does the exact same thing with two electronic components:

  • The Optical Flame Sensor acts as the station's eyes: Open flames produce a very specific type of invisible light called infrared light (specifically around 760 to 1100 nanometers). The black phototransistor bulb on the flame sensor acts like a dedicated eye that only sees this exact fire wavelength. Because light travels instantly, this sensor detects a fire in less than 15 milliseconds.
  • The MQ Gas Sensor acts as the station's nose: Combustible gases like butane, propane, methane, and thick smoke do not always emit bright light right away. The MQ sensor contains a tiny ceramic heating tube coated with a metal-oxide chemical layer. When combustible gas molecules float into the sensor chamber, they react with the heated surface and make it easier for electric current to flow through.

The comparison diagram below details how our dual hazard sensors operate simultaneously to identify fire and gas leaks before catastrophic ignition occurs:

Dual sensor detection mechanics showing flame infrared receiver and heated gas chamber
Dual sensor detection mechanics showing flame infrared receiver and heated gas chamber

Because fire radiates distinctive infrared wavelengths while gas leaks lower the internal electrical resistance of the heated SnO2 tin-dioxide sensor surface, the Arduino detects distinct hazard signatures within milliseconds.

Because fire and gas present different types of danger, our system responds differently depending on what it detects:

Environmental StateFlame Sensor (A1)Gas Sensor (A0)Exhaust Relay (Pin 8)Buzzer Siren (Pin 9)LCD Display Message
Normal StandbyHigh Voltage (> 500)Low PPM (< 300)OFF (De-energized)SilentENVIRONMENT SAFE / GAS: xxx PPM
Gas Leak WarningHigh Voltage (> 500)High PPM (> 300)ON (Ventilating Air)1000 Hz Pulsed BeepGAS LEAK DETECT! / [VENT ON]
Fire EmergencyLow Voltage (< 350)Any ReadingON (Clearing Smoke)2200 Hz Urgent SirenFIRE DETECTED!! / EXHAUST & SIREN
Open flames drop the flame sensor voltage instantly because light moves at top speed, while gas sensors require 1 to 2 seconds for gas molecules to drift across the heated sensing surface.

Notice the priority in the table above: if an open flame is spotted, fire takes top priority immediately. The system switches on the exhaust fan to remove toxic smoke and blasts a high-pitched 2200 Hz siren so everyone knows to evacuate.

Part 2 — Build the Circuit: Wiring Power, Sensors, and Actuators

Before connecting individual signal pins, let us understand how electricity flows through our safety station. Every electronic circuit requires two fundamental power lines to work:

  • 5V (Positive Power Line): Think of this like water flowing from a pressurized main pipe. The Arduino Uno 5V pin supplies steady electrical energy to power the internal heating element of the gas sensor, the optical comparator on the flame sensor, the LCD backlight, and the relay coil.
  • GND (Ground Line): Think of this like the drainage pipe that lets water return home. Without a connected ground wire, electricity has nowhere to go, no current flows, and no sensor can take a reading. All components must share this common ground reference.

To safely switch high-power ventilation fans or emergency exhaust solenoids without exposing the delicate Arduino logic pins to dangerous voltage spikes, examine the relay isolation circuit below:

Emergency exhaust relay and siren interlock wiring diagram
Emergency exhaust relay and siren interlock wiring diagram

Now follow the step-by-step wiring tables below to connect each module cleanly to your Arduino Uno:

Pin Connection Map
Flame Infrared Sensor
VCC
→
Arduino Uno
5V
Explanation
Provides 5V electrical power to the phototransistor comparator.
Flame Infrared Sensor
GND
→
Arduino Uno
GND.1
Explanation
Connects to common ground return line.
Flame Infrared Sensor
A0 (Analog Out)
→
Arduino Uno
A1
Explanation
Sends analog brightness voltage. Lower voltage means brighter flame.
Pin Connection Map
MQ Gas Sensor
VCC
→
Arduino Uno
5V
Explanation
Powers internal heating coil and chemical sensing element.
MQ Gas Sensor
GND
→
Arduino Uno
GND.1
Explanation
Returns sensor ground current.
MQ Gas Sensor
A0 (Analog Out)
→
Arduino Uno
A0
Explanation
Delivers 0V to 5V analog voltage proportional to gas concentration.
Pin Connection Map
LCD 1602 Display (I2C)
VCC
→
Arduino Uno
5V
Explanation
Powers LCD character driver chip and LED backlight.
LCD 1602 Display (I2C)
GND
→
Arduino Uno
GND.1
Explanation
Display ground connection.
LCD 1602 Display (I2C)
SDA (Serial Data)
→
Arduino Uno
A4
Explanation
Sends text characters and commands over the I2C data bus.
LCD 1602 Display (I2C)
SCL (Serial Clock)
→
Arduino Uno
A5
Explanation
Synchronizes data timing between Arduino and LCD.
Pin Connection Map
KS2E Relay Module (Exhaust Fan)
COIL1
→
Arduino Uno
5V
Explanation
Powers the internal electromagnetic coil.
KS2E Relay Module (Exhaust Fan)
COIL2
→
Arduino Uno
D8
Explanation
Digital output pin 8 drives the relay coil to turn the exhaust fan ON or OFF.
Pin Connection Map
Piezo Siren Buzzer
Pin 1 (+)
→
Arduino Uno
D9
Explanation
PWM-capable digital pin 9 sends audio frequencies via tone().
Piezo Siren Buzzer
Pin 2 (-)
→
Arduino Uno
GND.2
Explanation
Completes buzzer audio circuit back to Arduino ground.

Why Did We Choose These Specific Pins?

Understanding why pins are selected helps you design your own projects with confidence:

  • Analog Pins A0 and A1: Both the gas sensor and flame sensor provide continuous, variable analog signals. Using analog pins allows the Arduino analog-to-digital converter (ADC) to read 1,024 distinct voltage levels (from 0 to 1023). This lets us see exactly how much gas is in the room or how intense a flame is, rather than just a simple yes-or-no switch.
  • I2C Bus on A4 (SDA) and A5 (SCL): The Arduino Uno has dedicated hardware for two-wire serial communication located on pins A4 and A5. By using the I2C protocol, we can control all 32 characters on the 16x2 LCD screen using only two wires, leaving our digital pins free for sirens and relays.
  • Digital Pin 8 for Relay Control: Relays only need a binary command: HIGH (5V) to energize the internal coil and turn the fan ON, or LOW (0V) to turn it OFF. Standard digital pin 8 is ideal for this clean switching task.
  • Digital Pin 9 for Piezo Siren: Pin 9 supports high-speed hardware timers. This enables the Arduino tone() function to generate clean, rapid square waves at specific audio frequencies without slowing down sensor measurements.

Part 3 — Program the Behavior: Complete Arduino Sketch

Here is the full, tested firmware for the dual-threat hazard safety station. You can copy this code directly into your sketch or run it straight inside the IoTSimulator workspace:

C++ Source
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

// Pin definitions matching our exact circuit
const int gasPin = A0;       // MQ Gas Sensor analog output
const int flamePin = A1;     // Flame Sensor analog output
const int relayPin = 8;      // Exhaust fan relay control
const int buzzerPin = 9;     // Emergency piezo siren

// Initialize 16x2 LCD at standard I2C address 0x27
LiquidCrystal_I2C lcd(0x27, 16, 2);

// Timing variable for periodic telemetry logging
unsigned long lastTelemetryTime = 0;

void setup() {
  Serial.begin(9600);
  Serial.println("[HAZARD]: Safety Monitoring Station Booting...");

  // Configure output control lines
  pinMode(relayPin, OUTPUT);
  pinMode(buzzerPin, OUTPUT);
  digitalWrite(relayPin, LOW); // Start with exhaust fan turned OFF

  // Initialize LCD display
  lcd.init();
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print(" HAZARD MONITOR ");
  lcd.setCursor(0, 1);
  lcd.print(" SYSTEM ONLINE  ");
  delay(80);
  lcd.clear();

  Serial.println("[HAZARD]: Ready. Scanning Gas & Flame Sensors.");
}

void loop() {
  unsigned long currentMillis = millis();

  // Step 1: Read raw sensor voltages
  int gasRaw = analogRead(gasPin);
  int flameRaw = analogRead(flamePin);

  // Step 2: Convert raw gas reading into estimated PPM
  int ppm = map(gasRaw, 0, 1023, 50, 1000);

  // Step 3: Evaluate threat conditions
  bool isFire = (flameRaw < 350);     // Low reading indicates flame detected
  bool isGasLeak = (ppm > 300);       // Concentration above safety threshold

  // Step 4: Act on highest priority threat
  if (isFire) {
    digitalWrite(relayPin, HIGH);     // Turn exhaust fan ON
    tone(buzzerPin, 2200, 150);       // High-pitch fire evacuation siren
    
    lcd.setCursor(0, 0);
    lcd.print("FIRE DETECTED!! ");
    lcd.setCursor(0, 1);
    lcd.print("EXHAUST & SIREN ");
  } else if (isGasLeak) {
    digitalWrite(relayPin, HIGH);     // Turn exhaust fan ON to clear fumes
    tone(buzzerPin, 1000, 100);       // Medium-pitch gas warning beep
    
    lcd.setCursor(0, 0);
    lcd.print("GAS LEAK DETECT!");
    lcd.setCursor(0, 1);
    lcd.print("PPM: ");
    lcd.print(ppm);
    lcd.print(" [VENT ON] ");
  } else {
    digitalWrite(relayPin, LOW);      // Exhaust fan stays OFF
    noTone(buzzerPin);                // Silence the buzzer
    
    lcd.setCursor(0, 0);
    lcd.print("ENVIRONMENT SAFE");
    lcd.setCursor(0, 1);
    lcd.print("GAS: ");
    lcd.print(ppm);
    lcd.print("PPM | OK ");
  }

  // Step 5: Send diagnostic telemetry to Serial Monitor once every second
  if (currentMillis - lastTelemetryTime >= 1000) {
    lastTelemetryTime = currentMillis;
    Serial.print("[Telemetry]: Gas=");
    Serial.print(ppm);
    Serial.print("PPM | FlameRaw=");
    Serial.print(flameRaw);
    Serial.print(" | Fire=");
    Serial.print(isFire ? "ALERT" : "SAFE");
    Serial.print(" | Exhaust=");
    Serial.println(digitalRead(relayPin) ? "ON" : "OFF");
  }

  delay(50); // Small pause for stable analog sampling
}

To visualize the state machine logic that coordinates optical warnings, rapid siren frequencies, and emergency relay cutoffs during each loop cycle, inspect the threat escalation matrix below:

Three tier environmental safety matrix infographic showing logic states
Three tier environmental safety matrix infographic showing logic states

By prioritizing simultaneous flame and gas conditions as critical emergencies while handling standalone gas accumulation with active ventilation, the controller guarantees deterministic protection. Now let us walk through the complete source code line by line.

How the Code Works, Step by Step

Let us walk through each section of the code so you understand exactly what the microcontroller is doing at every moment.

1. Libraries and Pin Setup

At the top of the file, we include Wire.h and LiquidCrystal_I2C.h. These helper libraries handle all the background communication timing required by the I2C display protocol.

Next, we give clear names to our connection pins: gasPin = A0, flamePin = A1, relayPin = 8, and buzzerPin = 9. Naming your pins at the top makes your code easy to read and simple to rewire later if needed.

2. The Setup Function

Inside setup(), we open a serial communication channel at 9600 baud. This allows your computer to receive live telemetry messages through the Arduino Serial Monitor window.

We set pinMode(relayPin, OUTPUT) and pinMode(buzzerPin, OUTPUT) because the Arduino will send electrical commands out to these devices. We immediately write digitalWrite(relayPin, LOW) so the exhaust fan starts in a safe, unpowered state.

Finally, we initialize the LCD, turn on its LED backlight, and show a brief welcome message for 80 milliseconds before clearing the screen for live data.

3. Reading Sensors and Calculating Gas PPM

Inside the repeating loop() function, the microcontroller takes two fresh analog voltage readings every cycle:

int gasRaw = analogRead(gasPin); reads the voltage from the MQ sensor (a number between 0 and 1023). We use the Arduino map() function to scale this raw reading into an approximate parts-per-million (PPM) concentration from 50 to 1000 PPM.

int flameRaw = analogRead(flamePin); reads the light sensor. When no fire is present, this reading stays high (typically between 700 and 1023). When infrared light from a flame strikes the phototransistor, the sensor pulls the voltage down. If the reading drops below 350, the variable isFire becomes true.

4. Prioritizing Threats with if-else Logic

Real safety systems must handle emergencies in order of immediate danger to human life:

  • First Priority (Fire): If isFire is true, the code executes the first if block. It energizes the relay to turn on the exhaust fan (digitalWrite(relayPin, HIGH)), sounds an urgent 2200 Hz tone on the buzzer, and displays FIRE DETECTED!! on the LCD screen.
  • Second Priority (Gas Leak): If there is no fire but isGasLeak is true (PPM exceeds 300), the code enters the else if block. It turns on the exhaust fan to clear accumulating fumes, plays a distinct 1000 Hz warning beep, and prints the exact PPM level on the LCD.
  • Normal State: If neither danger is present, the final else block runs. The exhaust fan is turned off, the buzzer is silenced with noTone(buzzerPin), and the screen displays ENVIRONMENT SAFE along with the live ambient air PPM.

5. Clean Telemetry without Freezing the Processor

At the bottom of the loop, notice how we check currentMillis - lastTelemetryTime >= 1000. Instead of using a clumsy delay(1000) that would freeze the Arduino for a full second and make it blind to sudden fires, we use the internal millisecond clock. Sensor checks run rapidly every 50 milliseconds, while verbose diagnostic text is printed to the Serial Monitor only once per second.

Part 4 — Practical Testing in the Simulator

Follow these quick steps to test every safety state inside the IoTSimulator canvas:

  1. Test Normal Standby: Press the green Run button. Watch the LCD display light up and show ENVIRONMENT SAFE. Check the relay indicator: the exhaust fan remains idle, and the buzzer is completely silent.
  2. Test Gas Leak Detection: Click on the interactive Gas Cloud Actor near the top-middle of the canvas. Drag its concentration slider upward until the PPM reading rises past 300. Notice how the relay snaps ON, the LCD immediately warns GAS LEAK DETECT! [VENT ON], and the buzzer emits a steady 1000 Hz warning chime.
  3. Test Fire Emergency: Click on the interactive Campfire Actor on the top-right of the canvas. Activate the flame or move it closer to the Flame Sensor. Watch the LCD instantly switch to FIRE DETECTED!! / EXHAUST & SIREN, the buzzer shift into a high-urgency 2200 Hz siren tone, and the exhaust fan stay fully energized.
  4. Return to Safe Baseline: Turn off the Campfire Actor and slide the Gas Cloud back down to clean air levels. Within 50 milliseconds, the buzzer silences, the relay clicks off, and the display returns to calm green safety.

Part 5 — Troubleshooting Common Beginner Mistakes

If your physical build or simulation does not behave as expected, check these common pitfalls:

  • Gas sensor reading is constantly high on startup: Real MQ gas sensors have a physical heating coil inside. When you first plug one into power, it takes between 2 and 5 minutes to burn off ambient moisture on the chemical layer. During this preheat phase, readings will read artificially high before settling down to clean room air.
  • Flame sensor triggers even when no fire is present: The phototransistor responds to infrared light. Direct sunlight through a window, hot incandescent light bulbs, or TV remotes point-blank can emit enough infrared light to trigger the sensor. Always test in indirect room light or shield the sensor sides with a small piece of dark heat-shrink tubing.
  • The relay does not click or Arduino resets when relay turns on: Mechanical relay coils consume significant electric current when energized. If your 5V power supply is weak (such as powering everything from an unpowered USB hub), turning on the relay can cause a brief voltage drop that restarts the Arduino Uno. Always make sure your USB port provides a stable 500mA supply.
  • Buzzer makes clicking sounds instead of a clear tone: Make sure your buzzer is connected to digital pin 9 and that you use tone(buzzerPin, frequency). If you accidentally connect a buzzer to a non-PWM pin or write digitalWrite(buzzerPin, HIGH) on a passive piezo element, you will hear a faint click rather than a ringing alarm tone.

Part 6 — Taking It Further: Next Engineering Steps

Once your basic dual-threat safety station is running smoothly, consider expanding its capabilities with these practical additions:

  • Add a Physical Mute Button: Wire a momentary push button to digital pin 2 with an internal pull-up resistor. When an alarm sounds, an operator can press the button to silence the siren for 60 seconds while keeping the exhaust fan actively venting the room.
  • Connect a Gas Shutoff Solenoid Valve: Wire a second relay channel that controls an electric 12V brass solenoid valve on the main fuel line. If gas exceeds 400 PPM, the Arduino can instantly cut off fuel at the source before dangerous vapor reaches an ignition point.
  • Add Remote Cellular / Wi-Fi Alerts: Pair your Arduino Uno with an ESP8266 or GSM cellular module to send instant push notifications or SMS messages to building managers the second a hazard is detected after hours.
Keywords
#Arduino #Fire Alarm #Gas Leak Detector #MQ-2 Gas Sensor #Flame Sensor #Buzzer Siren #Safety Interlock
Total word count: 2335 words

Project discussion

Questions, feedback, and community insights
No discussions yet. Be the first to start!