Contents — 26 sections
Project Overview
A wearable that watches for the two things that kill plant workers — toxic gas and a man-down fall — and raises a located, acknowledged alarm to a control room in seconds.
Two hazards account for a grim share of industrial fatalities, and both are ones a person often cannot save themselves from. Toxic or oxygen-deficient atmospheres — hydrogen sulphide in a sewer, carbon monoxide in a boiler room, oxygen displaced in a tank — can incapacitate a worker in seconds, before they even realise, and a rescuer who rushes in unprotected becomes the next casualty. A man-down event — a fall, a collapse, an incapacitation — leaves a worker unable to call for help, and if they are alone or unseen, minutes of delay can be fatal. This wearable watches for both continuously and, when it detects danger, raises a located, acknowledged alarm to a control room fast enough to matter.
It carries a gas sensor (or several) for the specific hazards of the workplace — H₂S, CO, combustible gas, low oxygen — alarming the moment concentration crosses a danger threshold, both to the worker (loud/vibrating) and to the control room. It carries an accelerometer that recognises the signatures of a man-down event: the impact and sudden stillness of a fall, or prolonged no-motion suggesting incapacitation, with a pre-alarm the worker can cancel if they are fine (to reduce false alarms). And it carries a manual panic button for any other emergency. Every alarm goes out located (who, and where) and is acknowledged by the control room so the worker knows help is coming and the system knows a human is responding.
Being a life-safety device for the two hazards above, its design is dominated by reliability and honest limits. It runs a full shift on battery with battery supervision, uses a communication path with coverage across the plant (LoRa/mesh, sometimes cellular), and — this must be stated plainly — a DIY wearable is not a certified gas detector or a substitute for the intrinsically-safe, calibrated, professionally-certified safety equipment that hazardous industrial work legally requires. Real gas detection in explosive/toxic atmospheres demands certified instruments; this project is an educational build and, at most, a supplementary awareness layer. Within that honest frame, though, it embodies the right architecture: sense the killers, alarm the worker and a control room instantly, locate and acknowledge, and never pretend a hobby device replaces the certified gear that lives are actually trusted to.
What this project does
- Monitors for toxic/combustible gas and low oxygen (workplace-specific)
- Detects man-down events (fall impact + stillness, or prolonged no-motion)
- Provides a manual panic button for any emergency
- Alarms the worker (loud/vibrate) and a control room instantly
- Sends located, acknowledged alerts (who + where)
- Runs a full shift on supervised battery with plant-wide comms
- Is explicit that it is not a certified safety device
Real-World Applications
| Setting | How it is used |
|---|---|
| Confined-space / lone workers (educational) | Awareness of gas and man-down events for workers who may be alone or unseen — alongside certified equipment. |
| Plant / process areas | Supplementary gas and fall alerting routed to a control room with location. |
| Utilities / sewers / tanks | Demonstrating the sensing and alarm architecture for toxic-atmosphere and fall hazards. |
| Safety-tech education | Teaching man-down detection, gas alarming and located, acknowledged alerting. |
Deployment contexts where a build of this kind earns its keep.
Features & Capabilities
- Gas + man-down + panic — the core worker-safety triggers
- Fall/incapacitation detection with a cancellable pre-alarm
- Located, acknowledged control-room alarms
- Worker + control-room dual alerting
- Shift battery life with supervision
- Plant-wide resilient comms
- Honest: supplementary/educational, NOT certified safety equipment
Difficulty, Time & Required Skills
| Attribute | Value |
|---|---|
| Difficulty level | Advanced |
| Estimated completion time | 14–22 hours |
| Indicative build cost | ₹3,500 – ₹6,000 per wearable |
| Primary discipline | Industrial |
| Reference platform | ESP32 DevKit V1 (ESP-WROOM-32) |
Skills you should have (or will pick up)
- Gas sensing and danger-threshold alarming
- Man-down/fall detection from accelerometer signatures
- Located, acknowledged alerting and pre-alarm cancellation
- Wearable battery life and supervision
- Resilient plant-wide comms
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.
| Component | Key specification | Qty | Approx. 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 DAC | 1 | ₹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 output | 1 | ₹150 |
| MQ-135 air-quality sensor Not a true CO₂ sensor — calibrate against clean air (R0) before trusting ppm. | NH₃, NOx, benzene, smoke, CO₂ proxy, 10–1000 ppm, analogue output | 1 | ₹180 |
| MQ-7 carbon monoxide sensor Requires an alternating 60 s / 90 s heater cycle to read correctly — a constant 5 V gives wrong numbers. | 20–2000 ppm CO, dual-heater cycle (1.4 V / 5 V), analogue output | 1 | ₹260 |
| MPU-6050 6-axis IMU Gyro bias drifts with temperature — re-zero at boot while the device is still. | 3-axis gyro ±250–2000 °/s, 3-axis accel ±2–16 g, 16-bit ADC, on-chip DMP | 1 | ₹190 |
| 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 diameter | 1 | ₹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–SF12 | 1 | ₹480 |
| 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 discharge | 1 | ₹450 |
| Gas sensor(s) for the hazard Real safety needs certified, calibrated, IS-rated detectors | H₂S/CO/combustible/O₂ sensors appropriate to the workplace (educational-grade) | 1 | ₹900 |
| Vibration motor + loud buzzer | Haptic + audible worker alarm | 1 | ₹200 |
| Wearable enclosure + battery | Comfortable, rugged, shift-life battery with supervision | 1 | ₹500 |
| Control-room gateway/console | LoRa/mesh gateway + console for located, acknowledged alarms | 1 | ₹2,500 |
Estimated total: ₹6,285, 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
| Part | Specification | Supply | Interface | Reference |
|---|---|---|---|---|
| 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 DAC | 3.3 V logic / 5 V USB | UART, SPI, I²C, I²S, CAN, PWM | Datasheet |
| MQ-2 combustible gas / smoke sensor | 300–10000 ppm LPG, propane, methane, hydrogen, smoke; analogue + digital output | 5 V (heater) | Analogue + comparator digital | Datasheet |
| MQ-135 air-quality sensor | NH₃, NOx, benzene, smoke, CO₂ proxy, 10–1000 ppm, analogue output | 5 V (heater) | Analogue | Datasheet |
| MQ-7 carbon monoxide sensor | 20–2000 ppm CO, dual-heater cycle (1.4 V / 5 V), analogue output | 5 V | Analogue (PWM heater) | Datasheet |
| MPU-6050 6-axis IMU | 3-axis gyro ±250–2000 °/s, 3-axis accel ±2–16 g, 16-bit ADC, on-chip DMP | 2.375–3.46 V (module 5 V tolerant) | I²C (0x68/0x69) | Datasheet |
| Active piezo buzzer 5 V | 85 dB at 10 cm, 2.3 kHz resonance, 12 mm diameter | 3–5 V | Digital / PWM | Datasheet |
| SX1278 LoRa 433 MHz module (Ra-02) | −148 dBm sensitivity, +20 dBm output, up to 10 km line of sight, SF7–SF12 | 3.3 V | SPI | Datasheet |
| 18650 Li-ion cell 3400 mAh + holder | 3.7 V nominal, 4.2 V full, 3400 mAh, ~12.6 Wh, 2 C discharge | 3.0–4.2 V | Holder / spot-welded tabs | Datasheet |
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.
| Load | Supply rail | Typical current (mA) | Notes |
|---|---|---|---|
| ESP32 DevKit V1 (ESP-WROOM-32) | 3.3 V logic / 5 V USB | 160 | Wi-Fi transmit bursts peak near 500 mA — size the regulator accordingly. |
| MQ-2 combustible gas / smoke sensor | 5 V (heater) | 150 | Needs 24–48 h burn-in and a stable 5 V; the heater alone draws ~150 mA. |
| MQ-135 air-quality sensor | 5 V (heater) | 150 | Not a true CO₂ sensor — calibrate against clean air (R0) before trusting ppm. |
| MQ-7 carbon monoxide sensor | 5 V | 150 | Requires an alternating 60 s / 90 s heater cycle to read correctly — a constant 5 V gives wrong numbers. |
| MPU-6050 6-axis IMU | 2.375–3.46 V (module 5 V tolerant) | 3.9 | Gyro bias drifts with temperature — re-zero at boot while the device is still. |
| Active piezo buzzer 5 V | 3–5 V | 30 | Active buzzers make tone on DC; passive ones need a PWM carrier. |
| SX1278 LoRa 433 MHz module (Ra-02) | 3.3 V | 120 | Never power the radio without an antenna — the PA will destroy itself. |
Summed typical draw is 763.9 mA. With a 1.5× design margin the supply should deliver at least 1200 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.jsonunder 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
dialoutgroup:sudo usermod -aG dialout $USERand 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
| Library | Why it is needed | Install |
|---|---|---|
| WiFi (ESP32 core) bundled | Station/AP connection management for the ESP32. | Bundled with the ESP32 Arduino core |
| MPU6050_light / Adafruit MPU6050 1.3.x | IMU register access, calibration and complementary-filter angles. | Library Manager → "MPU6050_light" by rfetick |
| LoRa (sandeepmistry) 0.8.0 | SX127x radio configuration, packet TX/RX and callbacks. | Library Manager → "LoRa" by Sandeep Mistry |
| ArduinoJson 7.x | Zero-allocation JSON serialisation and parsing. | Library Manager → "ArduinoJson" by Benoit Blanchon |
| Preferences (NVS) bundled | Wear-levelled key/value storage in ESP32 flash for settings. | Bundled with the ESP32 core |
| NTPClient / configTime bundled | Wall-clock time from an NTP server for timestamping. | Bundled (`configTime()` on ESP32) |
Block Diagram
The block diagram shows the functional decomposition of the system — what senses, what decides, what acts, and where the data ends up.
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.
| Peripheral | Peripheral pin | Controller pin | Signal |
|---|---|---|---|
| Gas sensor(s) | AOUT | GPIO 34/35 | Toxic/combustible/O₂ |
| MPU-6050 | SDA/SCL/INT | GPIO 21/22/27 | Man-down (fall/stillness) |
| Panic button | NO | GPIO 26 | Manual SOS |
| Buzzer + vibrator | IN | GPIO 13/14 | Worker alarm |
| LoRa/mesh | SPI | GPIO 18/19/23/5 | Located alert to control room |
| Battery sense | ADC | GPIO 32 | Supervision |
| Charger | OUT | 3V3 reg | Shift power |
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
- Use gas sensors appropriate to the workplace hazard; understand these are educational-grade, not certified detectors.
- Mount the accelerometer firmly on the body so fall/stillness signatures are faithful.
- Provide both loud audible and haptic (vibration) worker alarms so it is felt in noise/PPE.
- Power for a full shift with battery supervision, and use a comms path with plant-wide coverage (LoRa/mesh; cellular where needed).
- Keep the panic button easy to press but guarded against accidental activation.
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.
Working Principle
This wearable is a life-safety device targeted at two specific killers, and life-safety design means everything is optimised for the rare, adverse moment of use, with brutal honesty about limits. The two hazards are chosen because they share a lethal property: the victim often cannot save themselves. A toxic or oxygen-deficient atmosphere can incapacitate before the worker even perceives danger — and, notoriously, lures would-be rescuers to their deaths — so it must be detected by an instrument, not by human senses. A man-down event leaves the worker unable to call for help, so the device must call on their behalf. The wearable's whole reason to exist is to sense these, alarm instantly, and get a located, acknowledged call to people who can respond.
Gas detection alarms on concentration crossing a danger threshold for the specific hazard — a toxic gas rising past its exposure limit, oxygen falling below safe, combustible gas approaching its explosive limit. The response is immediate and dual: the worker is alerted loudly and by vibration (because in plant noise and PPE, sound alone may not reach them) so they can evacuate or don protection, and the control room is alerted simultaneously so help and rescue (properly equipped) can be organised. The device must be candid that its educational-grade sensors are not the certified, calibrated, intrinsically-safe detectors that hazardous work legally mandates — so its gas function is, at most, a supplementary awareness layer, never the primary protection lives are trusted to.
Man-down detection reads the accelerometer for the signatures of incapacitation. A fall shows as a characteristic sequence — often a brief free-fall or lurch, a sharp impact, then abnormal stillness — and prolonged no-motion (a worker who has not moved for an unusual period) suggests collapse. The design must balance sensitivity against false alarms, because a wearable that cries wolf gets taken off, so a detected man-down triggers a cancellable pre-alarm: the device warns the worker (buzz/vibrate) and, if they are fine, they cancel it within a few seconds; only if they do not cancel does it escalate to a full located alarm. This "confirm before escalate" pattern keeps false alarms tolerable while still catching a genuinely incapacitated worker who cannot cancel. A manual panic button covers every other emergency the sensors do not.
Because it is trusted (even supplementarily) for safety, the wearable lives or dies on reliability, location, acknowledgement and supervision. Alarms carry the worker's identity and location so responders go straight to them — vital in a large plant. They are acknowledged end-to-end so the worker knows help is coming and the control room confirms it is handling the event. The device runs a full shift on battery with battery supervision, over comms with plant-wide coverage, and heartbeats its health so a dead or low wearable is flagged before an incident — because a silently failed safety device is worse than none. Above all, the design is emphatically honest: a homebrew wearable, however well-architected, is not a certified gas detector or a replacement for the intrinsically-safe, calibrated, professionally-certified safety equipment that industrial hazardous work requires by law. It is an educational realisation of the right ideas — sense the killers, alarm the worker and a control room instantly, locate and acknowledge, supervise relentlessly — and it must never be presented, or relied upon, as the real thing.
The maths behind it
Gas danger alarm
For each gas, alarm on crossing its danger threshold:
toxic : conc > exposure_limit (e.g. ppm)
O2 : O2 < safe_min (e.g. 19.5%) OR > safe_max
LEL : combustible > %LEL_alarm (with margin)
Alarm worker (loud+vibrate) AND control room, immediately.
Man-down detection
From accelerometer magnitude a and orientation:
free-fall : a ≈ 0 briefly
impact : a spike (high g)
stillness : low motion sustained after impact
no-motion : |a − 1g| < ε for > T_still (collapse)
man_down = (impact THEN stillness) OR prolonged no-motion
Pre-alarm + escalate
On man_down:
pre-alarm the worker for T_cancel seconds
if worker cancels -> resume (false alarm avoided)
else -> escalate: located, acknowledged control-room alarm
Reduces false alarms while catching real incapacitation.
Program Flowchart
The firmware is a single cooperative loop. Nothing blocks for long, so networking, sensing and the user interface all stay responsive.
Assembly Instructions
Build on a breadboard first and only commit to solder once the whole system has run for an hour without a fault.
Build a reliable, comfortable wearable
Assemble the gas sensor(s), a firmly-mounted accelerometer, loud + haptic alarms, and a guarded panic button in a comfortable, rugged enclosure with shift battery life and supervision.
Set up located, acknowledged comms
Use a comms path with plant-wide coverage (LoRa/mesh; cellular where needed) so alarms reach a control-room console with the worker's location and are acknowledged back.
Configure detection and pre-alarm
Set gas danger thresholds for the workplace, man-down signatures, and the cancellable pre-alarm and escalation, plus heartbeat supervision.
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.
Detect gas, man-down and panic
Alarm immediately on gas crossing a danger threshold or a panic press; on man-down, run a cancellable pre-alarm before escalating.
cppsafety-triggers.ino#define T_STILL_MS 20000 // no-motion time suggesting collapse #define T_CANCEL_MS 8000 // pre-alarm cancel window uint32_t stillSince=0, preAlarmStart=0; bool preAlarm=false; bool gasDanger(float toxic, float o2, float lel){ return toxic > TOXIC_LIMIT || o2 < O2_MIN || lel > LEL_ALARM; } // Man-down: impact-then-stillness OR prolonged no-motion. bool manDown(float aMag, uint32_t now){ static bool impacted=false; static uint32_t impactAt=0; if (aMag > 3.0f){ impacted=true; impactAt=now; } // impact spike bool still = fabsf(aMag - 1.0f) < 0.08f; // ~stationary (g) if (still){ if(!stillSince) stillSince=now; } else stillSince=0; bool afterImpact = impacted && (now-impactAt<30000) && stillSince && (now-stillSince>3000); bool collapsed = stillSince && (now-stillSince>T_STILL_MS); return afterImpact || collapsed; } // Cancellable pre-alarm before escalating a man-down. bool escalateManDown(bool md, bool cancelled, uint32_t now){ if (md && !preAlarm){ preAlarm=true; preAlarmStart=now; warnWorker(); } if (preAlarm && cancelled){ preAlarm=false; return false; } if (preAlarm && now-preAlarmStart>T_CANCEL_MS){ preAlarm=false; return true; } return false; }return toxic > TOXIC_LIMIT || o2 < O2_MIN || lel > LEL_ALARMAny gas crossing its danger threshold — toxic high, oxygen low, combustible high — triggers an immediate alarm.bool afterImpact = impacted && ... && (now-stillSince>3000)A fall is recognised as an impact spike followed by abnormal stillness, the classic man-down signature.bool collapsed = stillSince && (now-stillSince>T_STILL_MS)Prolonged no-motion catches a collapse without a sharp impact, e.g. a slow incapacitation.if (md && !preAlarm){ preAlarm=true; ... warnWorker(); }A detected man-down first warns the worker, giving them a chance to cancel if they are fine — the false-alarm control that keeps the device worn.if (preAlarm && now-preAlarmStart>T_CANCEL_MS){ preAlarm=false; return true; }Only if the worker does not cancel within the window does it escalate to a full located alarm — catching someone genuinely unable to respond.Alarm, locate, acknowledge, supervise
On any trigger, alarm the worker (loud+vibrate) and send a located alert to the control room, retry until acknowledged, confirm to the worker, and 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.
/* ═══════════════════════════════════════════════════════════════
Worker Safety Wearable — ESP32 (EDUCATIONAL / SUPPLEMENTARY)
Detects toxic/low-O2 gas and man-down (fall/stillness), plus a panic
button; alarms the worker (loud+vibrate) and a control room with a
located, acknowledged alert; supervises battery/link.
NOT a certified, calibrated, intrinsically-safe safety device.
══════════════════════════════════════════════════════════════════ */
#include <Wire.h>
#include <MPU6050.h>
#include <LoRa.h>
#include <SPI.h>
#include <Preferences.h>
#include <math.h>
#define PIN_TOXIC 34
#define PIN_O2 35
#define PIN_PANIC 26
#define PIN_BUZZER 13
#define PIN_VIBE 14
#define PIN_CANCEL 33
#define T_STILL_MS 20000
#define T_CANCEL_MS 8000
#define HEARTBEAT_MS 60000UL
MPU6050 imu; Preferences prefs;
const uint16_t WORKER_ID = 7;
const char *ZONE = "Boiler room"; // updated by location beacons in practice
uint32_t stillSince=0, preAlarmStart=0, lastBeat=0, seq=0;
bool preAlarm=false;
void workerAlarm(bool on){ digitalWrite(PIN_BUZZER,on); digitalWrite(PIN_VIBE,on); }
bool sendAlert(const char *type){
for (int a=0; a<5; a++){
LoRa.beginPacket();
LoRa.printf("{\"t\":\"%s\",\"id\":%u,\"zone\":\"%s\",\"seq\":%lu}",
type, WORKER_ID, ZONE, (unsigned long)++seq);
LoRa.endPacket();
if (waitAck(seq, 1500)){ /* confirm to worker */ return true; }
}
return false;
}
bool gasDanger(){
float toxic = analogRead(PIN_TOXIC)/4095.0f * TOXIC_FS;
float o2 = analogRead(PIN_O2)/4095.0f * 25.0f; // %O2 (calibrate)
return toxic > TOXIC_LIMIT || o2 < 19.5f;
}
bool manDown(float aMag, uint32_t now){
static bool impacted=false; static uint32_t impactAt=0;
if (aMag>3.0f){ impacted=true; impactAt=now; }
bool still = fabsf(aMag-1.0f)<0.08f;
if (still){ if(!stillSince) stillSince=now; } else stillSince=0;
bool afterImpact = impacted&&(now-impactAt<30000)&&stillSince&&(now-stillSince>3000);
bool collapsed = stillSince&&(now-stillSince>T_STILL_MS);
return afterImpact||collapsed;
}
void setup(){
Serial.begin(115200);
pinMode(PIN_PANIC,INPUT_PULLUP); pinMode(PIN_CANCEL,INPUT_PULLUP);
pinMode(PIN_BUZZER,OUTPUT); pinMode(PIN_VIBE,OUTPUT);
Wire.begin(21,22); imu.initialize();
SPI.begin(); LoRa.setPins(5,14,2); LoRa.begin(433E6); LoRa.setSpreadingFactor(10);
}
void loop(){
uint32_t now=millis();
int16_t ax,ay,az; imu.getAcceleration(&ax,&ay,&az);
float g=1.0f/16384.0f;
float aMag=sqrtf((ax*g)*(ax*g)+(ay*g)*(ay*g)+(az*g)*(az*g));
// panic + gas = immediate
if (digitalRead(PIN_PANIC)==LOW){ workerAlarm(true); sendAlert("PANIC"); }
if (gasDanger()){ workerAlarm(true); sendAlert("GAS"); }
// man-down with cancellable pre-alarm
if (manDown(aMag, now) && !preAlarm){ preAlarm=true; preAlarmStart=now; workerAlarm(true); }
if (preAlarm && digitalRead(PIN_CANCEL)==LOW){ preAlarm=false; workerAlarm(false); }
if (preAlarm && now-preAlarmStart>T_CANCEL_MS){
preAlarm=false; sendAlert("MAN_DOWN"); // escalate located alarm
}
if (now-lastBeat>HEARTBEAT_MS){ // supervision
LoRa.beginPacket();
LoRa.printf("{\"t\":\"HB\",\"id\":%u,\"vbat\":%.2f}",
WORKER_ID, readBattery());
LoRa.endPacket(); lastBeat=now;
}
delay(100);
}
Configuration & Calibration
Configuration steps
- Set gas danger thresholds for the workplace hazard (educational-grade sensors, clearly labelled as such).
- Configure man-down signatures, the pre-alarm cancel window, and escalation.
- Set the located-alert path (with acknowledgement), heartbeat interval and battery-low threshold.
- Integrate plant location (beacons/zones) so alerts are located.
Calibration procedure
An uncalibrated sensor produces confident, precise, wrong numbers. Do this once per physical unit and record the constants.
Gas
Understand these are educational sensors; for any real use, certified, calibrated detectors are required. Set thresholds and test response conservatively.
Man-down
Tune fall/stillness thresholds so genuine falls/incapacitation are caught while normal movement and brief rest do not false-alarm (with the pre-alarm as backstop).
Comms/battery
Verify located, acknowledged delivery across the plant and shift battery life with supervision.
Network Architecture & Connectivity
Communication protocol
Alarms deliver with retry and acknowledgement, located by worker/zone; heartbeats supervise every wearable. Worker alarm and delivery do not depend on a single link.
| Topic / endpoint | Direction | Payload |
|---|---|---|
safety/alarm | wearable → console | type (gas/man-down/panic), worker, zone |
safety/ack | console → wearable | acknowledgement → confirm to worker |
safety/heartbeat | wearable → console | battery, link (supervision) |
Message contract between the device and the broker.
Cloud platform configuration
A control-room console shows located, acknowledged alarms and every wearable's health, and coordinates (properly-equipped) response.
Dashboard setup
A plant map of workers with instant located alarms, an alarm queue with acknowledge, and a wearable-health/supervision view.
Mobile app integration
Located alarms to responders and supervision alerts for low-battery/silent wearables.
Security considerations
- Authenticate wearables/acknowledgements so alarms cannot be spoofed.
- Keep worker alarm and delivery independent of a single link; supervise continuously.
- Never present as certified equipment; certified, calibrated, IS-rated detectors are legally required for hazardous work.
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.
| Test | What you should see |
|---|---|
| Expose to test gas (safely) | Worker + control-room alarm; located, acknowledged |
| Simulate a fall | Pre-alarm; if not cancelled, escalates to man-down alarm |
| Cancel the pre-alarm | No escalation (false alarm avoided) |
| Remain motionless past the timeout | Collapse detected; man-down escalated |
| Press panic | Immediate located alarm |
| Let battery run low / go silent | Supervision flags low battery / missing heartbeat |
Bench-test checklist. If a row fails, stop and fix it before moving on.
Expected output
The control-room console shows located, acknowledged alarms (gas/man-down/panic) with the worker and zone, and a health view of every wearable.
{
"type": "MAN_DOWN",
"worker": 7,
"zone": "Boiler room",
"seq": 22,
"time": "2026-07-27T14:03:51",
"acknowledged": true
}
A located man-down alert (worker 7, boiler room) reaches the control room and is acknowledged; a gas or panic event would be handled identically — always with a supplementary, never a certified, guarantee.
Troubleshooting: Common Errors & Fixes
Performance Optimisation
- Prioritise instant, reliable alarming (retry+ack) over everything.
- Keep man-down detection light so it runs continuously without draining the shift battery.
- Heartbeat health so a dead/low wearable is known before an incident.
- Make the worker alarm both loud and haptic for noisy/PPE environments.
- Replace every
delay()with amillis()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_twhere 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 EDUCATIONAL/SUPPLEMENTARY — not a certified, calibrated, intrinsically-safe gas detector. Hazardous industrial work legally requires certified safety equipment; never rely on this for life safety.
- Real toxic/explosive atmospheres demand certified instruments and proper procedures (confined-space entry, rescue plans).
- Provide located, acknowledged alarms and supervision; a silent or unlocated alarm fails when it matters.
- Test regularly and never let this replace required PPE, gas detectors or safe systems of work.
- 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
- Act on every supervision alert; replace/charge batteries; fix silent wearables.
- Test gas response and man-down detection regularly (with the pre-alarm).
- Verify located, acknowledged delivery across the plant.
- Reinforce that it is supplementary — certified equipment remains mandatory.
- 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 heart-rate/temperature for heat-stress detection.
- Add precise indoor location (UWB/beacons) for faster rescue.
- Add two-way voice to the control room.
- Integrate with certified gas-detection systems as a data/awareness layer.
- 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
References & Learning Resources
These are the primary sources worth reading in full. Manufacturer datasheets always outrank forum posts when the two disagree.