Siddhant Kumar
Project 053 · Security

Panic Button Network.

SOS buttons across a campus or society that route a located, acknowledged alarm to a control room in seconds — engineered so that when it is pressed, it works.

Intermediate 12–18 hours 32 min read SOSMeshSafety
Jump to source Bill of materials
Panic Button Network — reference build illustration MCU VCC · GND · SIG · NC
Difficulty
Intermediate
Build time
12–18 hours
Indicative cost
₹2,800 – ₹4,500 per button (+ shared gateway/console)
Platform
ESP32 DevKit V1 (ESP-WROOM-32)
Category
Security
Last updated
28 July 2026
Contents — 26 sections

Project Overview

SOS buttons across a campus or society that route a located, acknowledged alarm to a control room in seconds — engineered so that when it is pressed, it works.

A panic button has exactly one job, and it must never fail at it: when someone in trouble presses it, a located alarm has to reach whoever can help, fast, and the person who sent it should know help is coming. That single-mindedness drives the whole design. Scattered across a campus, a housing society, a hospital or a school — in stairwells, car parks, corridors, hostel rooms — the buttons form a network that turns a press into an instant, located alert at a staffed control room, with acknowledgement flowing back so the sender is not left wondering whether anyone saw it.

The engineering challenge is reliability under the worst conditions, because a panic system is judged only by the moments it is used, which are emergencies. So every part is built to keep working when things are going wrong: each button reports its location so responders go straight to the right place; the alert is acknowledged end-to-end so both the control room and the sender have confirmation; the network is supervised so a button with a flat battery or a broken link is detected and fixed before an emergency, not discovered during one; and the communication path is chosen for coverage and resilience (a LoRa mesh or wired bus across a site, with redundancy) rather than a single fragile link. Buttons run on mains with battery backup so a power cut does not disarm them.

The behaviours around the core press are what make it dependable in practice: a button press is unmistakable and hard to trigger accidentally yet easy in a panic; an alert latches until a human acknowledges it, so it cannot be missed by a glance away; the control room sees a clear, prioritised, located alarm with the button's ID and place; and periodic self-tests and battery/link supervision keep the whole network provably healthy. It is honest that a DIY system is not a substitute for a monitored, certified life-safety installation where regulations demand one — but as a responsive, located, supervised SOS network for a campus or community, it does the thing that matters most: when the button is pressed, the alarm gets through, someone knows, and help is dispatched to the right place.

A city skyline at night
SOS points across a campus or society route a located alarm to a staffed control room in seconds. Photograph sourced from Wikimedia Commons — Smart city.jpg. Reused under the licence stated on that page; please check it before republishing.

What this project does

  • Sends an instant, located alarm to a control room when a button is pressed
  • Acknowledges end-to-end so the sender knows help is coming
  • Supervises every button (battery, link) so faults are found before emergencies
  • Latches alarms until a human acknowledges — never missed by a glance away
  • Uses a resilient path (LoRa mesh / wired bus) with redundancy
  • Runs on mains with battery backup so a power cut does not disarm it
  • Prioritises and locates alarms clearly at the control room

Real-World Applications

SettingHow it is used
Campus / university safetyEmergency SOS points across grounds, car parks and buildings routing to campus security with location.
Residential society / gated communityPanic buttons in common areas and homes alerting a guard control room instantly.
Hospitals / care facilitiesStaff-assist and patient SOS points with located, acknowledged alerts.
Schools / workplacesLockdown/assistance buttons in classrooms and offices routing to a coordinator.

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

Features & Capabilities

  • Single-purpose reliability: when pressed, it works
  • Located alarms so responders go straight to the place
  • End-to-end acknowledgement to the sender
  • Network supervision (battery/link) — faults found in advance
  • Latched, prioritised alarms at a staffed control room
  • Resilient comms with backup power
  • Honest scope vs certified life-safety systems

Difficulty, Time & Required Skills

AttributeValue
Difficulty levelIntermediate
Estimated completion time12–18 hours
Indicative build cost₹2,800 – ₹4,500 per button (+ shared gateway/console)
Primary disciplineSecurity
Reference platformESP32 DevKit V1 (ESP-WROOM-32)

Skills you should have (or will pick up)

  • Designing single-purpose reliable alerting
  • Located alarms and end-to-end acknowledgement
  • Network supervision (battery/link heartbeats)
  • Resilient comms (LoRa mesh / wired bus) with backup power
  • Control-room prioritisation and latching

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
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
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
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
Reed switch + magnet pair (door contact)
Wire it normally-closed so a cut cable reads the same as an open door — fail-safe by construction.
NO contact, 10–15 mm operating gap, 100 V / 0.5 A, > 10⁷ operations1₹55
DS3231 precision RTC + CR2032 backup
Vastly better than DS1307; some boards trickle-charge a non-rechargeable cell — cut that resistor.
±2 ppm (±1 min/year), temperature-compensated crystal, alarms, 32 kHz out1₹180
5 V 3 A regulated SMPS adapter
Measure the real output — many "3 A" adapters sag below 4.7 V at 2 A.
100–240 VAC in, 5 V ±5 % out, 3 A, short-circuit and over-voltage protection1₹350
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
Robust panic button + housing
Optionally protected/latching to prevent casual presses
Large, tamper-resistant, hard-to-trigger-accidentally, easy-in-panic button1₹350
LoRa mesh gateway (control room)Gateway with backhaul to the control-room console1₹2,500
Backup battery + charger per buttonBattery + charger so a mains cut does not disarm the button1₹300
Control-room console/annunciatorScreen/panel showing located, prioritised, latched alarms with ack1₹1,500

Estimated total: ₹6,890, 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
Active piezo buzzer 5 V85 dB at 10 cm, 2.3 kHz resonance, 12 mm diameter3–5 VDigital / PWMDatasheet
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
SX1278 LoRa 433 MHz module (Ra-02)−148 dBm sensitivity, +20 dBm output, up to 10 km line of sight, SF7–SF123.3 VSPIDatasheet
Reed switch + magnet pair (door contact)NO contact, 10–15 mm operating gap, 100 V / 0.5 A, > 10⁷ operationspassiveDigital with pull-upDatasheet
DS3231 precision RTC + CR2032 backup±2 ppm (±1 min/year), temperature-compensated crystal, alarms, 32 kHz out2.3–5.5 VI²C (0x68)Datasheet
5 V 3 A regulated SMPS adapter100–240 VAC in, 5 V ±5 % out, 3 A, short-circuit and over-voltage protection5 VDC barrel / USBDatasheet
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.
Active piezo buzzer 5 V3–5 V30Active buzzers make tone on DC; passive ones need a PWM carrier.
0.96″ SSD1306 OLED display3.3–5 V20Static images burn in — invert or scroll the screen periodically.
SX1278 LoRa 433 MHz module (Ra-02)3.3 V120Never power the radio without an antenna — the PA will destroy itself.
DS3231 precision RTC + CR2032 backup2.3–5.5 V0.2Vastly better than DS1307; some boards trickle-charge a non-rechargeable cell — cut that resistor.
5 V 3 A regulated SMPS adapter5 V3000Measure the real output — many "3 A" adapters sag below 4.7 V at 2 A.

Summed typical draw is 3330.2 mA. With a 1.5× design margin the supply should deliver at least 5000 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
Adafruit SSD1306 + GFX 2.5.xFramebuffer and text/graphics primitives for the OLED.Library Manager → "Adafruit SSD1306"
LoRa (sandeepmistry) 0.8.0SX127x radio configuration, packet TX/RX and callbacks.Library Manager → "LoRa" by Sandeep Mistry
NTPClient / configTime bundledWall-clock time from an NTP server for timestamping.Bundled (`configTime()` on ESP32)
ArduinoJson 7.xZero-allocation JSON serialisation and parsing.Library Manager → "ArduinoJson" by Benoit Blanchon
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.

Panic Button Network — system block diagramFunctional block diagram of the Panic Button Network system. PressPanic buttonlocatedBackup powermains + batteryDeliverESP32send + latchLoRa meshresilient pathRespondControl roomlocated, prioritisedAcknowledgeback to senderAssureSupervisionbattery/link healthrightrightnone
Panic Button Network — 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.

Panic Button Network — wiring schematicConnection schematic showing which controller pin drives each peripheral. Sensors / InputsControllerActuators / OutputsESP32 DevKit V1(ESP-WROOM-32)3.3 V logic / 5 V USBPanic buttonGPIO 27SOS pressTamper switchGPIO 14Enclosure tamperDS3231 RTCGPIO 21/22Event timestampsLoRa SX1276GPIO 18/19/23/5/14/2Resilient alert pathOLED + buzzerGPIO 21-22 / 26Local ack + statusBackup batteryADCBattery supervisionMains 5V + charger3V3 regPowered + backup
Panic Button Network — wiring schematic
PeripheralPeripheral pinController pinSignal
Panic buttonNO/NCGPIO 27SOS press
Tamper switchNCGPIO 14Enclosure tamper
DS3231 RTCSDA/SCLGPIO 21/22Event timestamps
LoRa SX1276SPI+CTRLGPIO 18/19/23/5/14/2Resilient alert path
OLED + buzzerI²C / INGPIO 21-22 / 26Local ack + status
Backup batterysenseADCBattery supervision
Mains 5V + chargerOUT3V3 regPowered + backup

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

  • Wire the button so a press is unambiguous and debounced; consider a protected/latching actuator to prevent casual/accidental presses while staying easy in a real emergency.
  • Power from mains with automatic battery backup, and sense the battery so low-power is supervised and reported.
  • Use a resilient comms path — a LoRa mesh (each button relaying) or a supervised wired bus — with redundancy where possible.
  • Add a tamper switch and give the RTC a coin-cell backup for accurate event times.
  • Provide clear local feedback (buzzer/OLED) that the alert was sent and acknowledged.
An ESP32 development board with the ESP-WROOM-32 module and USB connector
ESP32 module delivering the alert with retry and acknowledgement and heartbeating its own health. 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.

Panic Button Network — architecture stackLayered architecture from hardware to user interface. Hardware layerESP32 DevKit V1 (ESP-WROOM-32) · sensors and actuatorsDriver layerwifi · pubsub · ssd1306 · lorolibApplication logicsampling loop · filtering · thresholds · state machineTransport layerLoRa mesh (or wired bus) → control-room console · TLS · retry and backoffPresentation layerdashboard · mobile notifications · historical charts
Panic Button Network — architecture stack

Working Principle

A panic button is a life-safety alerting device, and life-safety design is dominated by one idea: the system must work in the rare, adverse moment it is needed, so everything is engineered for that moment rather than for the common case where nothing happens. That inverts normal priorities. Convenience, features, and efficiency are secondary; reliability, supervision, and confirmation are paramount. The measure of the system is not how it behaves on an ordinary Tuesday but whether, at 3 a.m. during a power cut when someone is in danger, a press still produces a located alarm at a staffed console and a confirmation back to the sender.

Three properties turn a button-and-buzzer into a dependable SOS system. First, location: an alarm that just says "someone pressed a button somewhere" wastes the seconds that matter, so every button carries its identity and place, and the control room sees exactly where help is needed. Second, acknowledgement: the alert is confirmed end-to-end — the control room's console shows and latches it, and a confirmation flows back to the button so the person who pressed it knows their call was received, which is both reassurance and evidence the path worked. A one-way send that might have been lost is not good enough when a life may depend on it. Third, latching and prioritisation: an alarm holds until a human explicitly acknowledges it, so it cannot be missed by a glance away, and it is presented prominently above routine information.

The property that separates a real system from a hopeful one is supervision. A panic network sits idle almost all the time, and the danger is that a button quietly dies — flat backup battery, broken antenna, severed wire — and nobody notices until the emergency reveals it, too late. So every button periodically sends a heartbeat reporting that it is alive and healthy (battery level, link quality), and the control room tracks these and raises a maintenance alarm the moment a button goes silent or reports a low battery. This turns "is the system working?" from an assumption into a continuously-verified fact. Combined with backup power (so a mains cut does not silently disarm the network) and a resilient comms path (a LoRa mesh where each button relays for others, or a supervised wired bus, ideally with redundancy so one failure does not create a dead zone), supervision is what lets you trust the system on the day it is used.

The design is finally about honest scope and human factors. The button must be unmistakable and hard to trigger by accident yet effortless to press in a panic; the alarm must reach a place where a human will actually act; and the whole thing must be regularly self-tested. It is candid that a DIY panic network, however well-built, is not a substitute for a professionally-monitored, certified life-safety installation where regulations or duty of care require one — a certified system carries guarantees and monitoring a homebrew cannot. But within its scope — a responsive, located, acknowledged, supervised SOS network for a campus or community — it delivers exactly what a panic button must: pressed in trouble, it gets through, someone knows, and help is sent to the right place.

The maths behind it

Reliable delivery (retry + ack)

plainReliable delivery (retry + ack)
On press:
  repeat up to N times:
    send SOS(button_id, location, seq)
    wait for ACK(seq) up to T
    if ACK received → confirm to sender, stop
  if no ACK after N → escalate (alt path / audible / SMS)

One-way sends are not enough; require and surface the ACK.

Supervision heartbeat

plainSupervision heartbeat
Each button, every H minutes:
  send HEARTBEAT(button_id, battery, rssi)

Control room:
  if no heartbeat within k·H  → button UNHEALTHY (maintenance)
  if battery < B_min          → low-battery maintenance alarm

Silence is itself an alarm — a dead button must be noticed.

Mesh relay for coverage/resilience

plainMesh relay for coverage/resilience
SOS packets flood the LoRa mesh with dedup + hop limit:
  each button relays neighbours' unseen SOS (hops < HOP_MAX)
  → reaches the control-room gateway even if one path fails

Redundant paths mean a single broken link is not a dead zone.

Program Flowchart

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

Panic Button Network — firmware flowchartControl flow through the main program loop. Idle (supervised)Button pressed?Send located SOS (retry)Send periodic heartbeatSend located SOS (retry)Control room ack received?Confirm to sender; latch at roomRetry / escalate pathConfirm to sender; latch atroomRetry / escalate pathSend periodic heartbeatSupervise battery/link
Panic Button Network — 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 a reliable, supervised button

    Fit a robust, unmistakable panic button (protected against casual/accidental presses but effortless in an emergency), power it from mains with automatic battery backup, and sense the battery for supervision. Add a tamper switch and a backed-up RTC.

  2. Set up the resilient comms

    Use a LoRa mesh (each button relaying) or a supervised wired bus to reach the control-room gateway, with redundancy so a single failure is not a dead zone. Encode each button's location/ID.

  3. Set up the control-room console

    Provide a console/annunciator that shows located, prioritised, latched alarms and lets an operator acknowledge them, plus a maintenance view of button health.

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. Send with retry and require acknowledgement

    On a press, send the located SOS and wait for an acknowledgement, retrying and escalating if none arrives, and confirm to the sender when the control room acknowledges.

    cpppanic-send.ino
    #define N_RETRY 5
    #define ACK_TIMEOUT_MS 1500
    
    bool sendSOS(uint32_t seq) {
      for (int attempt = 0; attempt < N_RETRY; attempt++) {
        txSOS(BUTTON_ID, LOCATION, seq);            // located alert into the mesh
        localFeedback("sending...");
        if (waitForAck(seq, ACK_TIMEOUT_MS)) {      // control room received it
          localFeedback("HELP COMING");             // confirm to the sender
          return true;
        }
      }
      escalate();                                   // alt path / audible / SMS
      localFeedback("escalating");
      return false;
    }
    
    void onButtonPress() {
      static uint32_t seq = 0;
      latchLocalAlarm();                            // local sounder on
      sendSOS(++seq);                               // deliver, confirm or escalate
    }
    for (int attempt = 0; attempt < N_RETRY; attempt++)The SOS is retried several times, because a single transmission can be lost and a life-safety alert cannot depend on one lucky packet.
    if (waitForAck(seq, ACK_TIMEOUT_MS))Delivery is confirmed by an acknowledgement from the control room, not assumed — the difference between hoping the alert arrived and knowing it did.
    localFeedback("HELP COMING")The sender is told their call was received, which both reassures the person in danger and proves the path worked end-to-end.
    escalate(); // alt path / audible / SMSIf no acknowledgement arrives after all retries, the button escalates to an alternate path rather than failing silently.
  2. Heartbeat and supervise

    Send periodic heartbeats with battery and link status; at the control room, flag any button that goes silent or reports low battery as a maintenance alarm so faults are fixed before an emergency.

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.

cpppanic-button-node.ino
/* ═══════════════════════════════════════════════════════════════
   Panic Button Network — ESP32 node, LoRa mesh, supervised

   Single-purpose reliable SOS: on press, sends a located alert with
   retry until acknowledged (confirming to the sender), escalates if
   not, and periodically heartbeats battery/link so a dead button is
   noticed before an emergency. Mains + battery backup.
   ══════════════════════════════════════════════════════════════════ */

#include <SPI.h>
#include <LoRa.h>
#include <Wire.h>
#include <Adafruit_SSD1306.h>
#include <Preferences.h>

#define PIN_BTN    27
#define PIN_TAMPER 14
#define PIN_BUZZER 26
#define PIN_VBAT   34
#define LORA_CS     5
#define LORA_RST   14
#define LORA_DIO0   2
#define N_RETRY     5
#define ACK_MS   1500
#define HEARTBEAT_MS 300000UL      // 5 min health beat

const uint16_t BUTTON_ID = 12;
const char *LOCATION = "Block C stairwell";
Adafruit_SSD1306 oled(128,64,&Wire);
Preferences prefs;
uint32_t seq = 0, lastBeat = 0;
volatile bool pressed = false;

void IRAM_ATTR onPress() { pressed = true; }

float batteryV() { return analogRead(PIN_VBAT)/4095.0f*3.3f*2.0f; }

void showLocal(const char *msg) {
  oled.clearDisplay(); oled.setCursor(0,0);
  oled.printf("Btn %d\n%s\n%s", BUTTON_ID, LOCATION, msg); oled.display();
}

void txSOS(uint32_t s) {
  LoRa.beginPacket();
  LoRa.printf("{\"t\":\"SOS\",\"id\":%u,\"loc\":\"%s\",\"seq\":%lu}",
              BUTTON_ID, LOCATION, (unsigned long)s);
  LoRa.endPacket();
}

bool waitForAck(uint32_t s, uint32_t timeout) {
  uint32_t t0 = millis();
  while (millis() - t0 < timeout) {
    if (LoRa.parsePacket()) {
      String p; while (LoRa.available()) p += (char)LoRa.read();
      if (p.indexOf("\"ACK\"") >= 0 && p.indexOf(String(s)) >= 0) return true;
    }
  }
  return false;
}

bool sendSOS() {
  digitalWrite(PIN_BUZZER, HIGH);              // local sounder latches on
  uint32_t s = ++seq;
  for (int a = 0; a < N_RETRY; a++) {
    showLocal("sending...");
    txSOS(s);
    if (waitForAck(s, ACK_MS)) { showLocal("HELP COMING"); return true; }
  }
  escalate();                                  // alt path / audible / SMS
  showLocal("escalating");
  return false;
}

void heartbeat() {
  LoRa.beginPacket();
  LoRa.printf("{\"t\":\"HB\",\"id\":%u,\"vbat\":%.2f}",
              BUTTON_ID, batteryV());
  LoRa.endPacket();
}

void setup() {
  Serial.begin(115200);
  pinMode(PIN_BTN, INPUT_PULLUP);
  pinMode(PIN_TAMPER, INPUT_PULLUP);
  pinMode(PIN_BUZZER, OUTPUT);
  attachInterrupt(PIN_BTN, onPress, FALLING);
  Wire.begin(21,22); oled.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  SPI.begin();
  LoRa.setPins(LORA_CS, LORA_RST, LORA_DIO0);
  LoRa.begin(433E6); LoRa.setSpreadingFactor(10);
  showLocal("ready");
}

void loop() {
  if (pressed) { pressed = false; sendSOS(); }

  if (millis() - lastBeat > HEARTBEAT_MS) {    // supervision heartbeat
    heartbeat();
    lastBeat = millis();
  }

  // relay neighbours' SOS packets (dedup + hop limit) for mesh resilience
  relayMeshIfNeeded();
}
attachInterrupt(PIN_BTN, onPress, FALLING)A press is captured by interrupt so the alert is sent immediately, even while the node is busy heartbeating or relaying.
digitalWrite(PIN_BUZZER, HIGH); // local sounder latches onA local sounder fires on press regardless of the network, giving immediate on-site alarm and reassurance.
if (waitForAck(s, ACK_MS)) { showLocal("HELP COMING"); return true; }The button retries until the control room acknowledges and then confirms to the sender — reliable, confirmed delivery, not a hopeful one-way send.
void heartbeat()Periodic health beats report the button is alive and its battery level, so the control room can flag a silent or low-battery button for maintenance before it is ever needed.
relayMeshIfNeeded();Each button relays others' SOS packets, giving the mesh redundant paths so one broken link does not create a coverage dead zone.

Configuration & Calibration

Configuration steps

  • Set each button's ID and human-readable location; configure the control-room gateway/console.
  • Set retry count/timeout, heartbeat interval, and low-battery/silence thresholds for supervision.
  • Choose the resilient comms (LoRa mesh / wired bus) and any escalation path (audible, SMS).
  • Configure alarm latching/acknowledgement and prioritisation at the console.

Calibration procedure

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

  1. Delivery reliability

    Verify that a press is acknowledged within the timeout across the whole site, including the farthest/most-shadowed buttons; add relays where needed.

  2. Supervision thresholds

    Set the heartbeat interval and the silence/low-battery thresholds so a genuinely dead or dying button is flagged promptly without nuisance alarms.

  3. Backup power

    Confirm each button keeps working on battery through a simulated mains cut for the required duration.

Network Architecture & Connectivity

Panic Button Network — network topologyPath taken by telemetry from field node to end user. Edge nodesGatewayCloudClientsPanic buttonESP32Relay buttonsmesh peersLoRa mesh / busControl-room GWto consoleMQTT/consoleControl roomlocated, latched alarmsConsolelocated alarmsRespondersdispatch
Panic Button Network — network topology

Communication protocol

SOS packets are delivered with retry and acknowledgement and flood the mesh with dedup for resilience; heartbeats supervise health. The local sounder and delivery are independent of any single link.

Topic / endpointDirectionPayload
panic/sosbutton → consolelocated SOS (id, location, seq)
panic/ackconsole → buttonacknowledgement (seq) → confirms to sender
panic/heartbeatbutton → consolebattery, link — supervision

Message contract between the device and the broker.

Cloud platform configuration

A control-room console presents located, prioritised, latched alarms and lets operators acknowledge them, and maintains a health map that flags any silent or low-battery button for maintenance.

Dashboard setup

A site map of buttons with instant located alarms, an alarm queue with acknowledge, and a supervision view of battery/link health per button.

Mobile app integration

Located SOS alerts and maintenance alerts (silent/low-battery button) to responders and facilities staff.

Security considerations

  • Authenticate buttons and acknowledgements so alarms cannot be spoofed or falsely acknowledged.
  • Keep the local sounder and delivery independent of any single link; supervise continuously.
  • Protect against tamper and ensure backup power so the network cannot be silently disarmed.

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
Press a buttonLocated alarm at the console within seconds; sender sees "HELP COMING"
Block the primary pathMesh relays / escalation still delivers; sender still acknowledged
Remove a button's battery/mainsOn battery it still works; total loss is flagged by missing heartbeat
Let a button go silentControl room raises a maintenance alarm for that button
Low batteryHeartbeat reports it; maintenance alarm before it fails
Acknowledge at the consoleAlarm de-latches; sender confirmation stands

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

Expected output

The control-room console shows located, prioritised, latched alarms with button ID/place and time, plus a health view of every button's battery and link.

jsonpanic-event.json
{
  "type": "SOS",
  "button": 12,
  "location": "Block C stairwell",
  "seq": 41,
  "time": "2026-07-27T02:14:55",
  "acknowledged": true
}

A located SOS from button 12 reaches the console and is acknowledged — the sender is told help is coming, and the event is recorded; a silent or low-battery button would instead appear as a maintenance alarm before any emergency.

A wall-mounted CCTV surveillance camera
A control-room console shows located, prioritised, latched alarms and every button's battery and link health. Photograph sourced from Wikimedia Commons — CCTV camera.jpg. Reused under the licence stated on that page; please check it before republishing.

Troubleshooting: Common Errors & Fixes

Alarm sometimes not received

Likely cause. One-way send / weak single path

Fix. Use retry+ack and a mesh/redundant path; add relays for shadowed buttons

Dead button discovered during a drill

Likely cause. No supervision

Fix. Add heartbeats and treat silence/low-battery as maintenance alarms

Button disarmed by power cut

Likely cause. No backup power

Fix. Add battery backup and verify battery run-time

Accidental presses

Likely cause. Too-easy actuator

Fix. Use a protected/guarded button that is still easy in a real emergency

Alarm missed at the console

Likely cause. Not latched/prioritised

Fix. Latch until acknowledged; present prominently above routine info

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 latency and delivery certainty over everything — retry with acknowledgement, not fire-and-forget.
  • Keep the mesh quiet except for heartbeats and alarms so an SOS propagates instantly.
  • Supervise continuously so the network's health is a known fact, not an assumption.
  • Debounce presses but never delay the alert.
  • 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

  • A panic system is life-safety: engineer for the emergency, supervise so faults are found first, and provide backup power and resilient comms.
  • Require and surface acknowledgement so the sender knows help is coming.
  • A DIY network is not a certified, professionally-monitored life-safety system; use a certified installation where regulations or duty of care require one.
  • Test regularly (drills and self-tests) so the system is provably ready.
  • 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.
  • 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

  • Act on every supervision alarm — replace flat batteries and fix silent buttons promptly.
  • Run periodic end-to-end drills and self-tests across all buttons.
  • Verify backup-power run-time and comms resilience after any site change.
  • Keep button locations and the console map accurate as the site evolves.
  • 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 two-way voice/intercom at the button for the control room to talk to the sender.
  • Add wearable/mobile panic triggers linked into the same network.
  • Integrate with door locks/lighting/CCTV to guide responders to the location.
  • Add automatic escalation to external emergency services where appropriate.
  • 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 makes this different from a button and a buzzer?

Reliability engineering: located alarms so responders go to the right place, end-to-end acknowledgement so the sender knows help is coming, supervision so dead buttons are found before an emergency, backup power, and a resilient comms path.

Why does supervision matter so much?

A panic network is idle almost always, so a button can quietly die and go unnoticed until it fails in an emergency. Heartbeats let the control room detect a silent or low-battery button and fix it in advance.

Why acknowledge back to the sender?

A one-way send might be lost, leaving a person in danger unsure anyone saw it. Confirming end-to-end reassures the sender and proves the alert actually reached a staffed console.

What if the power or a link fails?

Buttons run on battery backup so a mains cut does not disarm them, and the mesh/redundant path routes around a broken link. Both conditions are also supervised and alarmed.

Can this replace a professional alarm system?

For a campus or community it is a responsive, located, supervised SOS network — but it is not a certified, professionally-monitored life-safety installation. Where regulations or duty of care require one, use a certified system.

References & Learning Resources

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

  1. Panic alarm / duress systems — overviewReference
  2. Life-safety systems and supervision principlesReference
  3. LoRa mesh networkingReference
  4. Reliable messaging: retries and acknowledgementsReference
  5. Alarm annunciation and prioritisationReference