Siddhant Kumar
Project 056 · Security

Networked Fire & Smoke Alarm.

Interconnected smoke and heat detectors so that when one senses fire, every alarm in the building sounds — and everyone, including a control point, knows exactly where it started.

Advanced 14–20 hours 33 min read SmokeMeshSafety
Jump to source Bill of materials
Networked Fire & Smoke Alarm — reference build illustration MCU VCC · GND · SIG · NC
Difficulty
Advanced
Build time
14–20 hours
Indicative cost
₹3,500 – ₹6,000 (multi-node)
Platform
ESP32 DevKit V1 (ESP-WROOM-32)
Category
Security
Last updated
28 July 2026
Contents — 26 sections

Project Overview

Interconnected smoke and heat detectors so that when one senses fire, every alarm in the building sounds — and everyone, including a control point, knows exactly where it started.

The deadliest gap in home and building fire safety is not detection — it is hearing the alarm in time. A smoke detector in the basement can be screaming while people asleep upstairs hear nothing until the fire has spread. The single most important improvement, proven to save lives, is interconnection: when any one detector senses fire, all of them sound, everywhere, at once. This project builds a networked, interconnected fire and smoke alarm system where detectors in every room talk to each other, so a fire anywhere wakes everyone — and, because it is networked, it also announces where the fire started and can alert a control point or phones.

Each node combines the sensing that catches fire in its different forms: a smoke sensor for the smouldering and flaming smoke that is the earliest and most common sign, and a heat channel that watches both absolute temperature and its rate of rise (a fast-climbing temperature signals a fast-developing fire even before heavy smoke), with an optional flame sensor. Fusing smoke and heat, and watching rate-of-change against each node's baseline, is what lets it alarm early on a real fire while resisting the nuisance trips — cooking steam, shower humidity, dust — that make people disable detectors, which is itself a major cause of fire deaths.

Interconnection is the heart of it: nodes are networked (wired or wireless) so a detection propagates to every node in well under the critical few seconds, and a location-aware control point shows which room originated the alarm — invaluable for occupants deciding an escape route and for responders. The system supports battery backup so a power cut does not blind it, supervises every detector so a dead or removed unit is flagged (a missing detector is a silent risk), and can escalate to phones or a monitoring point. It is emphatic about its limits — a DIY system is not a certified, listed fire-alarm installation, and where codes require listed smoke alarms and professional monitoring you must use them; low-cost sensors are for supplementary awareness, not life-safety certification. But as a demonstration and a supplementary interconnected alarm, it embodies the one lesson that matters most in fire safety: when it detects fire, everyone hears it, everywhere, immediately.

Automated machinery on a factory production line
Interconnected detectors mean a fire anywhere in the building sounds every alarm at once. Photograph sourced from Wikimedia Commons — Factory automation.jpg. Reused under the licence stated on that page; please check it before republishing.

What this project does

  • Detects fire by smoke and by heat (absolute + rate-of-rise), optional flame
  • Interconnects detectors so one detection sounds every alarm in the building
  • Identifies and reports which room the alarm originated in
  • Resists nuisance trips (steam, dust) by fusing smoke and heat and using rate-of-change
  • Supervises every detector so a dead/removed unit is flagged
  • Runs on battery backup so a power cut does not blind it
  • Escalates a location-aware alert to a control point/phones

Real-World Applications

SettingHow it is used
Home fire safety (supplementary)Interconnected detectors so a fire anywhere in the house wakes everyone, with location and phone alerts — alongside listed smoke alarms.
Small building / hostel / officeBuilding-wide interconnected detection with a control point showing the room of origin.
Workshops / labsEarly smoke/heat detection in areas with specific fire risks, networked to a coordinator.
Education / demonstrationTeaching fire-detection sensing, interconnection and rate-of-rise principles.

Deployment contexts where a build of this kind earns its keep.

Features & Capabilities

  • Interconnected sounding — the proven life-saver (all alarm when one detects)
  • Smoke + heat + rate-of-rise fusion for early, robust detection
  • Location-aware alarms (which room started it)
  • Nuisance-resistant logic to stop people disabling detectors
  • Per-detector supervision (a missing detector is a risk)
  • Battery backup and escalation to a control point/phones
  • Explicit: supplementary, not a certified/listed fire-alarm system

Difficulty, Time & Required Skills

AttributeValue
Difficulty levelAdvanced
Estimated completion time14–20 hours
Indicative build cost₹3,500 – ₹6,000 (multi-node)
Primary disciplineSecurity
Reference platformESP32 DevKit V1 (ESP-WROOM-32)

Skills you should have (or will pick up)

  • Smoke and heat sensing (absolute + rate-of-rise) and fusion
  • Interconnecting detectors for all-sound-on-one-detect
  • Nuisance-rejection logic and per-node baselines
  • Detector supervision and battery backup
  • Location-aware alerting and escalation

Bill of Materials

Every part below is commonly available from Indian and international hobby-electronics suppliers. Prices are indicative 2026 retail figures in Indian rupees and will drift — treat them as a budgeting guide, not a quotation.

ComponentKey specificationQtyApprox. cost
ESP32 DevKit V1 (ESP-WROOM-32)
Wi-Fi transmit bursts peak near 500 mA — size the regulator accordingly.
Dual-core Xtensa LX6 @ 240 MHz, 520 KB SRAM, 4 MB flash, Wi-Fi 802.11 b/g/n + BLE 4.2, 34 GPIO, 18× 12-bit ADC, 2× 8-bit DAC1₹450
MQ-2 combustible gas / smoke sensor
Needs 24–48 h burn-in and a stable 5 V; the heater alone draws ~150 mA.
300–10000 ppm LPG, propane, methane, hydrogen, smoke; analogue + digital output1₹150
DHT22 / AM2302 temperature + humidity sensor
Needs a 4.7 kΩ pull-up on the data line and 2 s between reads.
−40 to +80 °C ±0.5 °C, 0–100 %RH ±2 %, 0.5 Hz sample rate, single-wire digital1₹250
IR flame sensor module (YG1006)
Sunlight and incandescent bulbs both trigger it — always confirm with a second sensor type.
760–1100 nm, 60° detection cone, 0.8 m range, analogue + digital out1₹70
Active piezo buzzer 5 V
Active buzzers make tone on DC; passive ones need a PWM carrier.
85 dB at 10 cm, 2.3 kHz resonance, 12 mm diameter1₹25
SX1278 LoRa 433 MHz module (Ra-02)
Never power the radio without an antenna — the PA will destroy itself.
−148 dBm sensitivity, +20 dBm output, up to 10 km line of sight, SF7–SF121₹480
0.96″ SSD1306 OLED display
Static images burn in — invert or scroll the screen periodically.
128 × 64 monochrome, 1.3–3.3 V logic, 100 kHz–400 kHz I²C1₹250
18650 Li-ion cell 3400 mAh + holder
Never charge below 0 °C; always use a protected cell or a BMS.
3.7 V nominal, 4.2 V full, 3400 mAh, ~12.6 Wh, 2 C discharge1₹450
Photoelectric smoke sensor
Photoelectric suits smouldering; combine sensing types for coverage
Photoelectric smoke chamber (good for smouldering fires) per node4₹3,200
Loud interconnected soundersPiezo/horn sounder per node, loud enough to wake sleepers4₹2,400
Backup batteriesPer-node battery so a power cut does not blind detection4₹1,600
Control point / annunciatorPanel showing room-of-origin and building status1₹1,200

Estimated total: ₹10,525, excluding tools, shipping and consumables.

Tools and consumables

  • Soldering iron (temperature controlled, 350 °C) with 0.8 mm 60/40 or lead-free solder
  • Digital multimeter — continuity, DC volts and current ranges
  • Wire strippers, flush cutters and a small set of precision screwdrivers
  • Heat-shrink tubing and a heat gun (or a lighter, carefully)
  • A laptop with a USB port and the toolchain listed above

Hardware Specifications

PartSpecificationSupplyInterfaceReference
ESP32 DevKit V1 (ESP-WROOM-32)Dual-core Xtensa LX6 @ 240 MHz, 520 KB SRAM, 4 MB flash, Wi-Fi 802.11 b/g/n + BLE 4.2, 34 GPIO, 18× 12-bit ADC, 2× 8-bit DAC3.3 V logic / 5 V USBUART, SPI, I²C, I²S, CAN, PWMDatasheet
MQ-2 combustible gas / smoke sensor300–10000 ppm LPG, propane, methane, hydrogen, smoke; analogue + digital output5 V (heater)Analogue + comparator digitalDatasheet
DHT22 / AM2302 temperature + humidity sensor−40 to +80 °C ±0.5 °C, 0–100 %RH ±2 %, 0.5 Hz sample rate, single-wire digital3.3–6 V1-wire proprietaryDatasheet
IR flame sensor module (YG1006)760–1100 nm, 60° detection cone, 0.8 m range, analogue + digital out3.3–5 VAnalogue + digitalDatasheet
Active piezo buzzer 5 V85 dB at 10 cm, 2.3 kHz resonance, 12 mm diameter3–5 VDigital / PWMDatasheet
SX1278 LoRa 433 MHz module (Ra-02)−148 dBm sensitivity, +20 dBm output, up to 10 km line of sight, SF7–SF123.3 VSPIDatasheet
0.96″ SSD1306 OLED display128 × 64 monochrome, 1.3–3.3 V logic, 100 kHz–400 kHz I²C3.3–5 VI²C (0x3C)Datasheet
18650 Li-ion cell 3400 mAh + holder3.7 V nominal, 4.2 V full, 3400 mAh, ~12.6 Wh, 2 C discharge3.0–4.2 VHolder / spot-welded tabsDatasheet

Consolidated electrical and interface specifications for every active part in the build.

Power Budget & Supply Sizing

Add up the typical active current of every part, then size the supply with at least 50 % headroom so transmit bursts and motor inrush never brown out the controller.

LoadSupply railTypical current (mA)Notes
ESP32 DevKit V1 (ESP-WROOM-32)3.3 V logic / 5 V USB160Wi-Fi transmit bursts peak near 500 mA — size the regulator accordingly.
MQ-2 combustible gas / smoke sensor5 V (heater)150Needs 24–48 h burn-in and a stable 5 V; the heater alone draws ~150 mA.
DHT22 / AM2302 temperature + humidity sensor3.3–6 V1.5Needs a 4.7 kΩ pull-up on the data line and 2 s between reads.
IR flame sensor module (YG1006)3.3–5 V15Sunlight and incandescent bulbs both trigger it — always confirm with a second sensor type.
Active piezo buzzer 5 V3–5 V30Active buzzers make tone on DC; passive ones need a PWM carrier.
SX1278 LoRa 433 MHz module (Ra-02)3.3 V120Never power the radio without an antenna — the PA will destroy itself.
0.96″ SSD1306 OLED display3.3–5 V20Static images burn in — invert or scroll the screen periodically.

Summed typical draw is 496.5 mA. With a 1.5× design margin the supply should deliver at least 800 mA continuously at the stated rail voltage.

Software Requirements & Development Environment

Reference toolchain: Arduino IDE 2.3.x with the ESP32 board package 3.x (or PlatformIO on VS Code). Anything newer normally works; anything older may lack the board definitions used here.

  • Install the Arduino IDE 2.3.x (or PlatformIO if you prefer a real editor and dependency locking).
  • Add https://espressif.github.io/arduino-esp32/package_esp32_index.json under File → Preferences → Additional Board Manager URLs, then install esp32 from the Boards Manager.
  • Set the correct port under Tools → Port. On Linux add yourself to the dialout group: sudo usermod -aG dialout $USER and log out and back in.
  • Open the Serial Monitor at 115200 baud — every sketch here logs its state there.
  • Keep File → Preferences → Show verbose output during: compilation switched on while you are debugging build errors.

Required libraries

LibraryWhy it is neededInstall
WiFi (ESP32 core) bundledStation/AP connection management for the ESP32.Bundled with the ESP32 Arduino core
PubSubClient 2.8Lightweight MQTT 3.1.1 client for constrained devices.Library Manager → "PubSubClient" by Nick O'Leary
DHT sensor library 1.4.6Timing-critical driver for DHT11/DHT22.Library Manager → "DHT sensor library" by Adafruit
LoRa (sandeepmistry) 0.8.0SX127x radio configuration, packet TX/RX and callbacks.Library Manager → "LoRa" by Sandeep Mistry
Adafruit SSD1306 + GFX 2.5.xFramebuffer and text/graphics primitives for the OLED.Library Manager → "Adafruit SSD1306"
NTPClient / configTime bundledWall-clock time from an NTP server for timestamping.Bundled (`configTime()` on ESP32)
Preferences (NVS) bundledWear-levelled key/value storage in ESP32 flash for settings.Bundled with the ESP32 core

Block Diagram

The block diagram shows the functional decomposition of the system — what senses, what decides, what acts, and where the data ends up.

Networked Fire & Smoke Alarm — system block diagramFunctional block diagram of the Networked Fire & Smoke Alarm system. Sense fireSmokephotoelectricHeat + ratetemperatureFlameoptionalDecideESP32fuse + nuisance-rejectBaselinerate-of-riseInterconnectAll-soundevery node alarmsOriginwhich roomEscalateControl pointroom of originPhonesalertrightrightnone
Networked Fire & Smoke Alarm — system block diagram

Circuit Diagram & Wiring

Every signal line in the build is shown below, followed by a pin-by-pin connection table you can work through with a multimeter in hand.

Networked Fire & Smoke Alarm — wiring schematicConnection schematic showing which controller pin drives each peripheral. Sensors / InputsControllerActuators / OutputsESP32 DevKit V1(ESP-WROOM-32)3.3 V logic / 5 V USBSmoke sensorGPIO 34Smoke concentrationDHT22 / tempGPIO 4Heat + rate-of-riseFlame sensorGPIO 27Flame (optionalconfirm)SounderGPIO 26Local +interconnected alarmInterconnectbus / SPIAll-soundpropagationOLEDGPIO 21/22Status / originBackup batteryADCPower supervision
Networked Fire & Smoke Alarm — wiring schematic
PeripheralPeripheral pinController pinSignal
Smoke sensorAOUTGPIO 34Smoke concentration
DHT22 / tempDATAGPIO 4Heat + rate-of-rise
Flame sensorDOUTGPIO 27Flame (optional confirm)
SounderINGPIO 26Local + interconnected alarm
Interconnectwired/LoRabus / SPIAll-sound propagation
OLEDSDA/SCLGPIO 21/22Status / origin
Backup batterysenseADCPower supervision

Wire one row at a time and tick it off — most "it does not work" reports trace back to a single swapped pair.

Wiring explanation

  • Interconnect the detectors — a wired interconnect line/bus or a fast wireless (LoRa/ESP-NOW) mesh — so any node's detection makes every node sound within a couple of seconds.
  • Mount smoke sensors per fire-code guidance (ceiling, away from kitchens/bathrooms to reduce nuisance trips) and give each a temperature sensor for heat/rate-of-rise.
  • Power each node with battery backup and sense the supply so power loss is detected and the node stays alive.
  • Make each sounder loud enough to wake a sleeping person through a closed door.
  • Give each node an ID/location so the control point can name the room of origin.
An ESP32 development board with the ESP-WROOM-32 module and USB connector
ESP32 module fusing smoke and heat with rate-of-rise, and broadcasting a located alarm to all nodes. Photograph sourced from Wikimedia Commons — ESP32 Espressif ESP-WROOM-32 Dev Board.jpg. Reused under the licence stated on that page; please check it before republishing.

System Architecture

Read the stack from the bottom up: physical hardware, the firmware that drives it, the transport that moves data off the device, and the software a human actually looks at.

Networked Fire & Smoke Alarm — architecture stackLayered architecture from hardware to user interface. Hardware layerESP32 DevKit V1 (ESP-WROOM-32) · MQ-2 combustible gas / smoke sensor ·DHT22 / AM2302 temperature + humidity sensor · IR flame sensor module(YG1006)Driver layerwifi · pubsub · dhtlib · lorolibApplication logicsampling loop · filtering · thresholds · state machineTransport layerFast interconnect (LoRa/ESP-NOW/wired) + control point/phones · TLS ·retry and backoffPresentation layerdashboard · mobile notifications · historical charts
Networked Fire & Smoke Alarm — architecture stack

Working Principle

Decades of fire-safety research converge on one finding above all: the biggest determinant of surviving a fire is early warning that everyone hears. Detection technology matters, but the fatal failures are usually that the alarm sounded somewhere no one could hear it in time, or that a nuisance-prone detector had been disabled. This system is built around those two lessons. Its defining feature is interconnection — the principle, now required by code for new homes in many places, that when any single detector senses fire, every detector in the building sounds simultaneously. A fire starting in a distant or closed room no longer relies on one local sounder to wake sleeping occupants across the house; the whole building alarms at once. Making that propagation fast and reliable (well under the few seconds that matter, over a wired interconnect or a fast wireless mesh) is the most important engineering goal in the project.

Detecting fire early and robustly means sensing its different signatures and fusing them. Fires present differently: a smouldering couch produces smoke long before heat, while a flaming fire produces heat and flame fast. So each node watches smoke (the earliest sign of most fires, and the primary sensor) and heat — and heat is watched two ways: absolute temperature, and crucially its rate of rise. A rate-of-rise heat detector alarms on a rapid temperature climb even before the absolute temperature is high, catching a fast-developing fire early; it is a classic, powerful complement to a fixed-temperature threshold. An optional flame sensor adds direct confirmation. Fusing these — smoke OR a dangerous heat/rate-of-rise, corroborated where possible — gives both earlier and more reliable detection than any single sensor.

The counter-intuitive but vital design goal is rejecting nuisance alarms, because nuisance trips kill. Detectors that cry wolf on cooking steam, shower humidity or dust get disabled by frustrated occupants — batteries removed, units unplugged — and a disabled detector is the leading contributor to fire deaths in homes that had alarms. So the system works to alarm on real fire while staying quiet on steam and dust: fusing smoke with heat/rate-of-rise (steam raises humidity but not the fire signature; a real fire moves both smoke and heat), using each node's baseline and rate-of-change rather than a bare threshold, and siting sensors away from kitchens and bathrooms. Reducing false alarms is not mere convenience — it is what keeps the detectors enabled, which is a prerequisite for them ever saving a life.

Around these, the system adds the properties that make it dependable and useful: location awareness so the control point (and the alert to phones) names the room the fire started in, helping occupants choose a safe escape route and responders go straight to the seat of the fire; supervision so every detector's presence and health is continuously checked and a dead, removed or low-battery unit is flagged (a missing detector is a silent hole in coverage); and battery backup so a power cut — which can accompany a fire — does not blind the system. It must be said as plainly as possible, though, that this is a supplementary and educational system, not a certified, listed, professionally-monitored fire-alarm installation. Life-safety fire detection is governed by codes and standards for good reason, and where they require listed smoke alarms and monitoring, those must be used. Built with that honesty, this project is a faithful, hands-on realisation of fire safety's central principle: detect early, reject nuisances so it stays enabled, and when it does detect, make sure everyone, everywhere, hears it at once and knows where to run from.

The maths behind it

Rate-of-rise heat detection

plainRate-of-rise heat detection
Watch both the absolute temperature and its rate of change:

  fixed  : alarm if T > T_max        (e.g. 58 °C)
  ROR    : alarm if dT/dt > R_max    (e.g. > 8 °C/min)

ROR catches a fast fire before T is high; fixed catches a
slow one. Use BOTH — many real detectors do.

Smoke + heat fusion (nuisance rejection)

plainSmoke + heat fusion (nuisance rejection)
fire likely if:
  smoke > S_thresh AND (dT/dt > R_max OR T > T_max)
  OR smoke >> S_high (heavy smoke alone)
  OR flame_confirmed

Steam raises humidity, not the smoke+heat signature →
rejected. Baseline/rate-of-change per node adapts to the
room and avoids threshold nuisance trips.

Interconnection propagation

plainInterconnection propagation
On local fire detection at node i:
  broadcast ALARM(origin=i) to all nodes
  every node j: sound_local()  (target < ~2 s)

Receiving an ALARM makes a node sound even with no local
smoke — the all-sound-on-one-detect life-safety behaviour.

Program Flowchart

The firmware is a single cooperative loop. Nothing blocks for long, so networking, sensing and the user interface all stay responsive.

Networked Fire & Smoke Alarm — firmware flowchartControl flow through the main program loop. Read smoke, temp, flameUpdate rate-of-rise + baselineFire confirmed (fused,nuisance-checked)?Sound ALL nodes + report originDetection from another node?Sound ALL nodes + reportoriginDetection from anothernode?Sound this node (interconnect)Monitor + heartbeatSound this node (interconnect)Monitor + heartbeatEscalate to controlpoint/phones
Networked Fire & Smoke Alarm — firmware flowchart

Assembly Instructions

Build on a breadboard first and only commit to solder once the whole system has run for an hour without a fault.

  1. Build interconnected detector nodes

    Give each node a smoke sensor, a temperature sensor (for heat and rate-of-rise), an optional flame sensor, a loud sounder, battery backup and a network interface (wired interconnect or fast wireless), plus an ID/location.

    Site smoke sensors per fire-code guidance, away from kitchens/bathrooms to reduce nuisance trips.

  2. Set up supervision and backup

    Have each node heartbeat its presence and health; power each with battery backup and sense the supply so power loss and low battery are flagged.

  3. Set up the control point and escalation

    Provide a control point/annunciator that shows the room of origin and building status, and configure escalation to phones/a monitoring point.

Step-by-Step Implementation Guide

Work through these in order. Each step ends in something you can observe, so a failure is always localised to the step you just finished.

  1. Detect fire with fusion and rate-of-rise

    Read smoke and temperature, compute the rate of rise, and confirm fire from the fused smoke+heat signature (with nuisance rejection) or heavy smoke or flame.

    cppfire-detect.ino
    float prevTemp = NAN; uint32_t prevMs = 0;
    
    // Rate of rise in deg C per minute, from successive temperature reads.
    float rateOfRise(float t, uint32_t now) {
      if (isnan(prevTemp)) { prevTemp = t; prevMs = now; return 0; }
      float dtMin = (now - prevMs) / 60000.0f;
      float ror = dtMin > 0 ? (t - prevTemp) / dtMin : 0;
      prevTemp = t; prevMs = now;
      return ror;
    }
    
    // Fuse smoke + heat with nuisance rejection.
    bool fireConfirmed(float smoke, float temp, float ror, bool flame) {
      bool heat = (temp > 58.0f) || (ror > 8.0f);         // fixed OR rate-of-rise
      if (smoke > SMOKE_THRESH && heat) return true;      // classic fire signature
      if (smoke > SMOKE_HEAVY)          return true;      // heavy smoke alone
      if (flame)                        return true;      // direct confirmation
      return false;                                       // steam/dust: rejected
    }
    float rateOfRise(float t, uint32_t now)Computes how fast the temperature is climbing, the signal that catches a fast-developing fire before the absolute temperature is dangerous.
    bool heat = (temp > 58.0f) || (ror > 8.0f)Heat is flagged either by a fixed high temperature or by a rapid rate of rise, combining the two classic heat-detection methods.
    if (smoke > SMOKE_THRESH && heat) return trueThe primary confirmation requires smoke together with a heat signature — a real fire moves both, while steam raises humidity without the heat signature, so nuisance trips are rejected.
    if (smoke > SMOKE_HEAVY) return trueOverwhelming smoke alone is enough to alarm, since heavy smoke is unambiguous even before heat builds.
  2. Interconnect and escalate

    On local confirmation, broadcast an alarm with this node's origin so every node sounds, sound locally on receiving any node's alarm, and escalate a located alert to the control point/phones; heartbeat health continuously.

Complete Source Code

The listing below is complete and compiles as written — there are no elided sections. Read the annotations under each block before you upload it.

cppnetworked-fire-alarm.ino
/* ═══════════════════════════════════════════════════════════════
   Networked Fire & Smoke Alarm — ESP32, interconnected detectors

   Smoke + heat (fixed + rate-of-rise) + optional flame, fused with
   nuisance rejection. Any node's detection sounds EVERY node and
   reports the room of origin. Supervised, battery-backed.
   SUPPLEMENTARY / EDUCATIONAL — not a certified fire-alarm system.
   ══════════════════════════════════════════════════════════════════ */

#include <WiFi.h>
#include <PubSubClient.h>
#include <DHT.h>
#include <LoRa.h>
#include <SPI.h>
#include <Preferences.h>
#include <math.h>

#define PIN_SMOKE 34
#define PIN_DHT    4
#define PIN_FLAME 27
#define PIN_SOUNDER 26
#define SMOKE_THRESH 1500
#define SMOKE_HEAVY  3000
#define HEARTBEAT_MS 60000UL

DHT dht(PIN_DHT, DHT22);
WiFiClient net; PubSubClient mqtt(net);
Preferences prefs;

const uint8_t NODE_ID = 1;
const char *ROOM = "Kitchen";
float prevTemp = NAN; uint32_t prevMs = 0, lastBeat = 0;
bool localFire = false;

float rateOfRise(float t, uint32_t now) {
  if (isnan(prevTemp)) { prevTemp = t; prevMs = now; return 0; }
  float dtMin = (now - prevMs) / 60000.0f;
  float ror = dtMin > 0 ? (t - prevTemp) / dtMin : 0;
  prevTemp = t; prevMs = now; return ror;
}

bool fireConfirmed(float smoke, float temp, float ror, bool flame) {
  bool heat = (temp > 58.0f) || (ror > 8.0f);
  return (smoke > SMOKE_THRESH && heat) || (smoke > SMOKE_HEAVY) || flame;
}

void soundLocal(bool on) { digitalWrite(PIN_SOUNDER, on ? HIGH : LOW); }

// Broadcast to interconnect (LoRa here; a wired bus works too).
void broadcastAlarm() {
  LoRa.beginPacket();
  LoRa.printf("{\"t\":\"FIRE\",\"origin\":%u,\"room\":\"%s\"}",
              NODE_ID, ROOM);
  LoRa.endPacket();
  mqtt.publish("fire/alarm", "");        // escalate to control point/phones
}

// Sound when ANY node reports fire (all-sound-on-one-detect).
void checkInterconnect() {
  if (LoRa.parsePacket()) {
    String p; while (LoRa.available()) p += (char)LoRa.read();
    if (p.indexOf("FIRE") >= 0) {
      soundLocal(true);                  // sound even without local smoke
      // relay origin to the control point / OLED for room-of-origin
      mqtt.publish("fire/echo", p.c_str());
    }
  }
}

void setup() {
  Serial.begin(115200);
  pinMode(PIN_FLAME, INPUT);
  pinMode(PIN_SOUNDER, OUTPUT);
  analogSetPinAttenuation(PIN_SMOKE, ADC_11db);
  dht.begin();
  SPI.begin();
  LoRa.setPins(5,14,2); LoRa.begin(433E6); LoRa.setSpreadingFactor(9);
  WiFi.begin(WIFI_SSID, WIFI_PASS);
  mqtt.setServer(MQTT_HOST, 1883);
}

void loop() {
  if (!mqtt.connected() && WiFi.status()==WL_CONNECTED) mqtt.connect("fire-1");
  mqtt.loop();
  checkInterconnect();                   // sound on any node's alarm

  uint32_t now = millis();
  float smoke = analogRead(PIN_SMOKE);
  float temp  = dht.readTemperature();
  float ror   = rateOfRise(temp, now);
  bool flame  = digitalRead(PIN_FLAME) == LOW;

  if (fireConfirmed(smoke, temp, ror, flame)) {
    if (!localFire) {
      localFire = true;
      soundLocal(true);
      broadcastAlarm();                  // make EVERY node sound + report origin
    }
  }

  if (now - lastBeat > HEARTBEAT_MS) {   // supervision heartbeat
    char m[80];
    snprintf(m,sizeof m,"{\"id\":%u,\"room\":\"%s\",\"ok\":1}",NODE_ID,ROOM);
    mqtt.publish("fire/heartbeat", m);
    lastBeat = now;
  }
  delay(200);
}
void checkInterconnect()Every loop the node listens for any other node's FIRE broadcast and sounds locally on receipt — even with no smoke of its own — which is the all-sound-on-one-detect behaviour that saves lives.
bool heat = (temp > 58.0f) || (ror > 8.0f)Heat is confirmed by a fixed threshold or a rapid rate of rise, so both fast and slow fires are caught by the heat channel.
broadcastAlarm(); // make EVERY node sound + report originA local detection is broadcast with this node's room, so the whole building sounds and the control point learns where the fire began.
return (smoke > SMOKE_THRESH && heat) || (smoke > SMOKE_HEAVY) || flameThe fused logic requires smoke plus heat for the common case, rejecting steam/dust, while heavy smoke or flame alone still alarm.
mqtt.publish("fire/heartbeat", m)Regular heartbeats let a control point supervise every detector, so a dead or removed unit is flagged rather than silently leaving a gap.

Configuration & Calibration

Configuration steps

  • Set each node's ID/room, the smoke/heat/rate-of-rise thresholds, and the interconnect medium (wired/wireless).
  • Tune nuisance-rejection (fusion, baselines) for each room's conditions and siting.
  • Configure the control point, escalation to phones, and per-node supervision/heartbeat.
  • Ensure battery backup and low-battery/power-loss alerts on every node.

Calibration procedure

An uncalibrated sensor produces confident, precise, wrong numbers. Do this once per physical unit and record the constants.

  1. Detection thresholds

    With test smoke/heat sources (safely), confirm early detection while cooking steam/shower humidity and dust do not trip the fused logic.

  2. Rate-of-rise

    Verify a rapid temperature climb triggers the ROR path before the absolute threshold, and that slow ambient changes do not.

  3. Interconnect timing

    Measure the time from one node detecting to all nodes sounding; ensure it is within a couple of seconds across the building.

Network Architecture & Connectivity

Networked Fire & Smoke Alarm — network topologyPath taken by telemetry from field node to end user. Edge nodesGatewayCloudClientsDetector nodeESP32Other detectorsinterconnectedLoRa/ESP-NOW/wiredControl pointroom of originMQTTMonitor / phoneslocated alarmControl pointorigin + statusPhonesalerts
Networked Fire & Smoke Alarm — network topology

Communication protocol

A detection broadcasts to all nodes so every sounder fires within ~2 s, and escalates a located alert; heartbeats supervise every detector. The all-sound behaviour and local sounders do not depend on the internet.

Topic / endpointDirectionPayload
fire/alarmnode → all/controlFIRE with origin node/room
fire/heartbeatnode → controldetector present/healthy (supervision)
fire/statusnode → controlbattery, power, sensor health

Message contract between the device and the broker.

Cloud platform configuration

A control point shows the room of origin and building status and escalates to phones/a monitoring point; heartbeats surface any missing or low-battery detector.

Dashboard setup

A building/floor plan with detector health and, on alarm, the origin room highlighted, plus an event and supervision log.

Mobile app integration

Immediate located fire alerts and maintenance alerts for missing/low-battery detectors.

Security considerations

  • Authenticate interconnect/alarm messages so false fire alarms cannot be injected.
  • Keep all-sound and local sounders independent of the internet; supervise continuously.
  • Treat missing heartbeats and power loss as safety-relevant events.

Testing Procedure & Expected Output

Test from the bottom up. Confirm power, then each sensor in isolation, then the integrated loop — the first failing step tells you exactly where to look.

TestWhat you should see
Trigger smoke at one nodeThat node and ALL nodes sound within ~2 s; origin room reported
Rapidly heat a nodeRate-of-rise alarms before the fixed threshold
Create steam/dust near a nodeNo alarm (fused logic rejects the nuisance)
Remove/disable a nodeControl point flags the missing detector via heartbeat loss
Cut mains powerNodes keep detecting on battery; power-loss noted
Check the control point on alarmRoom of origin clearly shown for escape/response

Bench-test checklist. If a row fails, stop and fix it before moving on.

Expected output

The control point shows building status and, on alarm, the room of origin; every node sounds, and a located alert escalates to phones.

jsonfire-alarm.json
{
  "type": "FIRE",
  "origin": 3,
  "room": "Bedroom 2",
  "time": "2026-07-27T03:12:44"
}

A detection in Bedroom 2 sounds every node in the building at once and tells the control point (and phones) the room of origin — the interconnection and location awareness that turn detection into survivable warning.

A city skyline at night
A control point shows the room of origin so occupants escape the right way and responders go to the source. Photograph sourced from Wikimedia Commons — Smart city.jpg. Reused under the licence stated on that page; please check it before republishing.

Troubleshooting: Common Errors & Fixes

Alarm not heard elsewhere

Likely cause. Interconnection slow/unreliable

Fix. Make the interconnect fast and robust; verify all-sound within ~2 s; add redundancy

Frequent nuisance trips

Likely cause. Single-sensor/threshold triggering near kitchen/bath

Fix. Fuse smoke+heat, use rate-of-rise/baselines, re-site sensors

Detectors get disabled by occupants

Likely cause. Too many false alarms

Fix. Reduce nuisance trips (the root cause); never solve it by removing detection

A dead detector goes unnoticed

Likely cause. No supervision

Fix. Heartbeat every node; flag missing/low-battery units at the control point

System blind after power cut

Likely cause. No battery backup

Fix. Add per-node battery backup; alert on power loss

The sketch will not upload — "Failed to connect" or "avrdude: stk500_recv()"

Likely cause. The bootloader is not being reached: wrong port, wrong board, a serial monitor holding the port open, or a USB cable that only carries power.

Fix. Close every serial monitor, confirm Tools → Board and Port, and swap to a known data-capable USB cable. On an ESP32 hold BOOT while the IDE prints "Connecting…", then release. If a peripheral is wired to the UART pins (GPIO 1/3 on ESP32, D0/D1 on Uno) unplug it — it fights the programmer.

The board resets in a loop, or the serial monitor prints "Brownout detector was triggered"

Likely cause. The supply cannot deliver peak current. Wi-Fi transmit bursts, relay coils and servos all pull far more than their average draw.

Fix. Power peripherals from a separate regulated supply with a common ground rather than from the board 5 V pin. Add a 470–1000 µF electrolytic capacitor across the supply near the load, and use a real power adapter rather than a laptop USB port.

Serial monitor shows garbage characters

Likely cause. Baud rate mismatch between Serial.begin() and the monitor, or a floating/shared UART line.

Fix. Set the monitor to 115200 to match the sketch. If it still garbles, the crystal or the USB bridge is being confused by noise — shorten the cable and keep motor wiring away from the USB lead.

An I²C device is not detected

Likely cause. Wrong address, missing pull-ups, swapped SDA/SCL, or a bus too long for the pull-up value.

Fix. Run an I²C scanner sketch first — it should print the device address. Most breakout boards include 4.7 kΩ pull-ups, but if you have chained four of them the parallel resistance is too low; remove the pull-ups from all but one board. Keep the bus under 30 cm at 100 kHz.

Wi-Fi connects but MQTT never does (state -2)

Likely cause. Wrong broker address or port, a firewall in the way, or the broker requiring credentials the sketch is not sending.

Fix. Test from a laptop on the same network first: mosquitto_sub -h <broker> -t "#" -v. If that works, the problem is on the device — check the IP literal, port 1883 (or 8883 for TLS), and that client.setServer() runs before connect(). PubSubClient state codes are documented in its header.

Readings arrive for a while and then stop

Likely cause. The Wi-Fi or MQTT session dropped and the sketch never reconnects, or the broker dropped the client on keep-alive timeout.

Fix. Never assume the link stays up. Check WiFi.status() and client.connected() at the top of every loop and reconnect with exponential backoff. Add a watchdog so a wedged network stack reboots the device instead of going silent.

Performance Optimisation

  • Prioritise interconnect latency — all nodes must sound within a couple of seconds of any detection.
  • Read sensors frequently enough for rate-of-rise to be meaningful without excess power.
  • Keep all-sound and local sounders independent of Wi-Fi/internet; escalation is secondary.
  • Heartbeat continuously so detector presence/health is always known.
  • Replace every delay() with a millis() comparison — blocking delays are the single most common cause of dropped readings.
  • Sample sensors on a fixed cadence and publish on a slower one; you almost never need to transmit at the sampling rate.
  • Move networking into its own FreeRTOS task so a slow DNS lookup cannot stall the control loop.
  • Use uint8_t / uint16_t where the range allows; on an 8-bit AVR a 32-bit add costs four times as much.
  • Batch several samples into one MQTT publish. Radio time, not CPU time, dominates the energy budget.
  • Set the MQTT keep-alive to a value that matches your reporting interval so the broker does not churn reconnections.
  • For battery builds use deep sleep between samples: an ESP32 drops from ~160 mA awake to about 10 µA asleep, which is the difference between days and months of runtime.

Safety Precautions

  • THIS IS SUPPLEMENTARY/EDUCATIONAL — not a certified, listed, professionally-monitored fire-alarm system. Use listed smoke alarms and monitoring where codes require them.
  • Interconnection (all sound when one detects) and low false-alarm rates (so detectors stay enabled) are the key life-safety properties — never compromise them.
  • Provide battery backup and supervise every detector; a dead or removed detector is a silent, dangerous gap.
  • Follow fire-code guidance on detector siting, quantity and placement.
  • Lithium cells vent and burn when abused. Only use protected cells or a proper BMS, never charge below 0 °C, and never leave a charging pack unattended on a wooden desk.
  • MQ-series sensors run a hot element. They get genuinely hot, need ventilation, and must never be enclosed in a sealed plastic box.
  • Never power an RF module without its antenna fitted — the reflected power destroys the output stage. Check your local licence-free band and duty-cycle limits before transmitting.
  • Wear eye protection when soldering or cutting, and solder in a ventilated space — rosin flux fumes are a respiratory irritant.
  • Power the circuit through a bench supply with a current limit while you are testing. A 300 mA limit turns a wiring mistake into a beep instead of a dead board.
  • Disconnect power before changing any wiring. Hot-plugging a sensor onto a live bus is the fastest way to lose a controller.

Maintenance

  • Test the whole interconnected system regularly (one node triggers all) and check sounder loudness.
  • Replace/clean smoke sensors and check batteries; act on every supervision alert.
  • Re-verify nuisance rejection after changes in room use or siting.
  • Keep the room/location map accurate for correct origin reporting.
  • Re-check every screw terminal and header after the first week — thermal cycling loosens connections that felt tight on day one.
  • Log pack voltage. When resting voltage after a full charge drops below about 4.0 V, the cell is near end of life — replace it.
  • Keep the broker and dashboard containers patched, and rotate device credentials at least once a year.
  • Recalibrate at the interval given in the calibration section, and keep the constants in a text file next to the firmware — not only in flash.
  • Keep a short logbook of firmware versions and what changed. Six months later you will not remember why that constant is 1.083.

Future Improvements & Upgrades

A working v1 is a platform, not a finish line. These are the upgrades that add the most capability for the least rework.

  • Add CO detection for a combined fire+CO safety system.
  • Add voice evacuation messages naming the safe route away from the origin.
  • Integrate with smart-home actions (lights on to escape routes, HVAC off).
  • Add automatic escalation to a monitoring service or fire brigade where appropriate and permitted.
  • Design a proper PCB. Once the breadboard version has run for a month, moving to a two-layer board removes the intermittent-contact failures that dominate prototype faults.
  • Add over-the-air firmware updates so you never have to physically reach a deployed node again.
  • Add persistent local storage (microSD or the on-chip flash) so a network outage does not create a hole in your data.
  • Move configuration out of the source: a captive-portal setup page or a JSON config file makes the build reusable without a recompile.
  • Add a battery and solar option so the unit survives a power cut and can be sited away from a socket.
  • Write a small test harness that feeds synthetic sensor values through the decision logic, so you can validate thresholds without physically triggering the event.

Frequently Asked Questions

What is the single most important feature?

Interconnection — when any detector senses fire, all of them sound. A local alarm in a distant room may not wake sleeping occupants; all-sound-on-one-detect does, and it is proven to save lives.

What is rate-of-rise detection?

Alarming on a rapid temperature climb, not just a high absolute temperature. It catches a fast-developing fire early, before the room is hot enough for a fixed threshold, and complements smoke detection.

Why obsess over false alarms?

Because nuisance trips make people disable detectors, and a disabled detector is a leading factor in fire deaths. Fusing smoke with heat and using rate-of-change keeps it accurate enough to stay enabled.

Can I use this instead of proper smoke alarms?

No. This is supplementary and educational, not a certified, listed, monitored fire-alarm system. Where codes require listed smoke alarms and monitoring, you must use them; run this alongside, not instead.

Why report the room of origin?

So occupants can choose an escape route away from the fire and responders go straight to its source. Knowing where it started is as valuable as knowing that it started.

References & Learning Resources

These are the primary sources worth reading in full. Manufacturer datasheets always outrank forum posts when the two disagree.

  1. Smoke detectors and interconnection — NFPA guidanceNFPA
  2. Heat detectors and rate-of-riseReference
  3. Photoelectric vs ionization smoke detectionReference
  4. Nuisance alarms and disabled detectors — fire-safety researchUSFA
  5. Fire alarm system fundamentalsReference