Siddhant Kumar
Project 083 · Smart City

Manhole Safety Monitor.

Watches sewer level and toxic gas inside a manhole — warning of flooding before it hits the street and of the lethal atmosphere before a worker climbs in.

Advanced 12–18 hours 29 min read GasLevelSafety
Jump to source Bill of materials
Manhole Safety Monitor — reference build illustration MCU VCC · GND · SIG · NC
Difficulty
Advanced
Build time
12–18 hours
Indicative cost
₹4,500 – ₹7,000
Platform
ESP32 DevKit V1 (ESP-WROOM-32)
Category
Smart City
Last updated
28 July 2026
Contents — 26 sections

Project Overview

Watches sewer level and toxic gas inside a manhole — warning of flooding before it hits the street and of the lethal atmosphere before a worker climbs in.

A manhole is two hazards in one hole. As a sewer or drainage access, its level rising toward the surface is an early sign of a blockage or a flood about to back up into streets and homes — caught early, it can be cleared before it overflows. And as a confined space, its atmosphere can be lethal: sewers generate hydrogen sulphide (toxic and, at higher levels, deadly), methane (explosive), carbon monoxide, and oxygen-deficient pockets — and workers die every year entering manholes with a bad atmosphere they could not see. This project monitors both continuously: the level, for flood/blockage early warning, and the toxic gases, for worker and public safety.

The monitor sits in the manhole and senses level (an ultrasonic or pressure sensor tracking how high the water/sewage has risen) and the gases that matter in a sewer — hydrogen sulphide, methane/combustible gas, carbon monoxide, and oxygen level. A rising level trending toward overflow triggers a flood/blockage alert with enough lead time to respond; a dangerous gas concentration triggers a safety alert. Because a manhole is a classic confined space, the gas data does double duty: it feeds a live picture for public/flood safety, and — critically — it can tell a worker (and their supervisor) the atmosphere before anyone descends, complementing the personal gas detector that confined-space entry legally requires.

Manholes are buried, wet, corrosive and without power, so the monitor is battery-powered and reports over LoRa, ruggedised and sealed, with cover-open detection as a bonus (an opened cover may mean unauthorised entry or theft). It is emphatic about scope and safety: this is a monitoring and early-warning aid, not a substitute for the certified, calibrated, personal gas detectors and the confined-space entry procedures that law and life-safety demand — no one should ever enter a manhole relying on a fixed monitor instead of proper detection and procedure. But as a manhole safety monitor, it delivers two genuinely valuable things a city otherwise lacks: early warning of sewer flooding before it reaches the street, and continuous awareness of the toxic atmosphere in a space that kills workers who cannot see the danger.

A city skyline at night
A manhole monitor watches sewer level (flood warning) and toxic gas (safety) in one hole. 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

  • Monitors manhole/sewer level for flood/blockage early warning
  • Senses toxic/explosive gases (H₂S, methane, CO) and oxygen level
  • Alerts on rising level trending toward overflow
  • Alerts on dangerous gas concentrations
  • Provides atmosphere awareness before confined-space entry
  • Detects cover-open (unauthorised entry/theft)
  • Runs on battery + LoRa from buried, powerless infrastructure

Real-World Applications

SettingHow it is used
Sewer flood/blockage early warningCatching rising levels before they back up into streets/homes.
Confined-space / worker safety awarenessAtmosphere awareness before/around manhole entry (with certified detectors and procedures).
Utility asset monitoringLevel, gas and cover status across a network of manholes.
Public safety / smart cityCity-wide sewer and drainage safety monitoring.

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

Features & Capabilities

  • Dual hazard: flood level + toxic atmosphere
  • Sewer gas sensing (H₂S/CH₄/CO/O₂)
  • Flood/blockage early warning with lead time
  • Pre-entry atmosphere awareness (complements personal detectors)
  • Cover-open detection
  • Battery + LoRa, rugged/sealed
  • Explicit: aid, NOT a substitute for certified detectors/procedures

Difficulty, Time & Required Skills

AttributeValue
Difficulty levelAdvanced
Estimated completion time12–18 hours
Indicative build cost₹4,500 – ₹7,000
Primary disciplineSmart City
Reference platformESP32 DevKit V1 (ESP-WROOM-32)

Skills you should have (or will pick up)

  • Level sensing (ultrasonic/pressure) in a manhole
  • Sewer gas sensing (H₂S/CH₄/CO/O₂)
  • Flood early warning and gas alarming
  • LoRa + battery for buried infrastructure
  • Confined-space safety awareness (scope/limits)

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
JSN-SR04T waterproof ultrasonic sensor
The 25 cm blind zone matters — mount it above the maximum expected water level.
25–450 cm, ±1 cm, IP67 sealed transducer, 45° beam1₹450
mq41
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 output1₹260
Dissolved-oxygen probe (galvanic)
The membrane and electrolyte are consumables — budget a replacement every 6–12 months.
0–20 mg/L, ±0.3 mg/L, galvanic, no warm-up, membrane cap consumable1₹5,800
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
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
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
Sewer gas sensors
Educational-grade; certified personal detectors required for entry
H₂S, methane/combustible, CO and O₂ sensors (rated for the environment)1₹1,500
Level sensorNon-contact ultrasonic or hydrostatic level (rated, sealed)1₹800
Cover-open sensorReed/tilt to detect an opened cover1₹150
Sealed rugged enclosure + LoRaCorrosion/water-proof housing and LoRa; long-life battery1₹900

Estimated total: ₹11,295, 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
JSN-SR04T waterproof ultrasonic sensor25–450 cm, ±1 cm, IP67 sealed transducer, 45° beam5 VTrigger/Echo or UARTDatasheet
MQ-7 carbon monoxide sensor20–2000 ppm CO, dual-heater cycle (1.4 V / 5 V), analogue output5 VAnalogue (PWM heater)Datasheet
Dissolved-oxygen probe (galvanic)0–20 mg/L, ±0.3 mg/L, galvanic, no warm-up, membrane cap consumable3.3–5 VAnalogueDatasheet
Reed switch + magnet pair (door contact)NO contact, 10–15 mm operating gap, 100 V / 0.5 A, > 10⁷ operationspassiveDigital with pull-upDatasheet
SX1278 LoRa 433 MHz module (Ra-02)−148 dBm sensitivity, +20 dBm output, up to 10 km line of sight, SF7–SF123.3 VSPIDatasheet
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.
JSN-SR04T waterproof ultrasonic sensor5 V30The 25 cm blind zone matters — mount it above the maximum expected water level.
MQ-7 carbon monoxide sensor5 V150Requires an alternating 60 s / 90 s heater cycle to read correctly — a constant 5 V gives wrong numbers.
Dissolved-oxygen probe (galvanic)3.3–5 V5The membrane and electrolyte are consumables — budget a replacement every 6–12 months.
SX1278 LoRa 433 MHz module (Ra-02)3.3 V120Never power the radio without an antenna — the PA will destroy itself.

Summed typical draw is 465 mA. With a 1.5× design margin the supply should deliver at least 700 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
LoRa (sandeepmistry) 0.8.0SX127x radio configuration, packet TX/RX and callbacks.Library Manager → "LoRa" by Sandeep Mistry
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
NTPClient / configTime bundledWall-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.

Manhole Safety Monitor — system block diagramFunctional block diagram of the Manhole Safety Monitor system. SenseLevelflood/blockageGasesH₂S/CH₄/CO/O₂CoveropenAssessESP32level trend / gasAlertFlood warninglead timeGas/safetyatmosphereReportCity mapmanholesPre-entryawarenessrightrightnone
Manhole Safety Monitor — 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.

Manhole Safety Monitor — wiring schematicConnection schematic showing which controller pin drives each peripheral. Sensors / InputsControllerActuators / OutputsESP32 DevKit V1(ESP-WROOM-32)3.3 V logic / 5 V USBLevel sensorGPIO 26/25/34Sewer levelGas sensorsGPIO 35/32/33H₂S/CH₄/CO/O₂Cover reedGPIO 27Cover openLoRaGPIO 18/19/23/5Alerts/statusBatteryADCSupervisionLocal beacon (opt)GPIO 13On-site alarmSupply3V3 regPower
Manhole Safety Monitor — wiring schematic
PeripheralPeripheral pinController pinSignal
Level sensorTRIG/ECHO/AOUTGPIO 26/25/34Sewer level
Gas sensorsAOUTGPIO 35/32/33H₂S/CH₄/CO/O₂
Cover reedNCGPIO 27Cover open
LoRaSPIGPIO 18/19/23/5Alerts/status
BatterysenseADCSupervision
Local beacon (opt)INGPIO 13On-site alarm
Supply+/–3V3 regPower

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

  • Monitor level (non-contact ultrasonic or hydrostatic) for flood/blockage warning and the sewer gases (H₂S, methane, CO, O₂) for safety.
  • Seal and ruggedise everything against the wet, corrosive sewer environment; use appropriately-rated sensors.
  • Battery + LoRa — manholes have no power/network; deep-sleep and report on change/schedule for long life.
  • Add cover-open detection (reed/tilt) to flag an opened cover.
  • THIS IS AN AID — certified, calibrated personal gas detectors and confined-space procedures are required for any entry, never this fixed monitor alone.
An ESP32 development board with the ESP-WROOM-32 module and USB connector
ESP32 node sensing level trend and H₂S/methane/CO/oxygen, reporting over LoRa on battery. 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.

Manhole Safety Monitor — architecture stackLayered architecture from hardware to user interface. Hardware layerESP32 DevKit V1 (ESP-WROOM-32) · JSN-SR04T waterproof ultrasonic sensor ·MQ-7 carbon monoxide sensor · Dissolved-oxygen probe (galvanic)Driver layerwifi · lorolib · arduinojson · preferencesApplication logicsampling loop · filtering · thresholds · state machineTransport layerLoRa → city sewer/safety dashboard · TLS · retry and backoffPresentation layerdashboard · mobile notifications · historical charts
Manhole Safety Monitor — architecture stack

Working Principle

A manhole concentrates two very different hazards into one small space, and the monitor addresses both because both are otherwise invisible until it is too late. The first is flooding/blockage: a sewer or drain backing up shows first as a rising level inside the manhole, well before it overflows onto the street or into homes, so watching the level gives early warning with time to clear a blockage or mobilise a response. The second is the lethal atmosphere of a confined space: sewers generate hydrogen sulphide, methane, carbon monoxide and oxygen-deficient pockets, and these gases are odour-fooling and deadly — H₂S in particular deadens the sense of smell at dangerous concentrations, so a worker can climb in unaware. Monitoring both level and gas turns two invisible, high-consequence hazards into observable, alertable conditions.

Flood early warning comes from the level and its trend. A non-contact ultrasonic or hydrostatic sensor tracks how high the water/sewage has risen; a level rising steadily toward the overflow point, especially faster than normal, signals a developing blockage or flood. Alerting on that trend — not just a high mark — gives lead time to act before it reaches the surface, which is the difference between a cleared blockage and a flooded street.

The atmosphere side senses the gases that matter in a sewer — H₂S (toxic), methane/combustible (explosive), CO, and oxygen level — and alarms on dangerous concentrations. This data serves public/flood safety, but its most important role is around confined-space entry: it can tell a worker and their supervisor what the atmosphere is before anyone descends, and monitor it while work happens. Here the design draws an emphatic line: continuous atmosphere awareness is a valuable complement to, but never a substitute for, the certified, calibrated personal gas detector each worker must carry and the confined-space entry procedures (ventilation, permit, standby, rescue plan) that law and life-safety require. No one should ever enter relying on a fixed monitor instead of proper detection and procedure — the monitor informs and warns; it does not certify a space safe to enter.

The deployment realities and honest scope complete it. Manholes are buried, wet, corrosive and powerless, so the monitor is battery-powered, reports over LoRa, and is sealed and ruggedised for the environment, deep-sleeping and reporting on change/schedule for long life; cover-open detection adds a flag for unauthorised entry or cover theft. And the scope is stated plainly and repeatedly: this is a monitoring and early-warning aid — for flooding, and for atmosphere awareness — not a certified safety instrument and not a replacement for the personal detectors and procedures that confined-space work legally and morally demands. Within that frame, it delivers two things a city otherwise lacks and that genuinely save property and lives: warning of sewer flooding before it hits the street, and continuous awareness of a toxic atmosphere in a space that kills the workers who cannot see the danger.

The maths behind it

Flood/blockage early warning

plainFlood/blockage early warning
Level L rising toward the overflow point L_of:

  alert if L > L_warn OR dL/dt > R_warn (rising fast)
  time_to_overflow ≈ (L_of − L) / (dL/dt)

Early warning with lead time to clear a blockage/respond.

Gas / atmosphere safety

plainGas / atmosphere safety
Alarm on dangerous concentrations:

  H2S > exposure limit (toxic; deadly higher)
  CH4 > %LEL alarm (explosive)
  CO  > exposure limit
  O2  < 19.5% (deficient) or > 23.5%

Atmosphere AWARENESS — NOT a substitute for personal
detectors + confined-space procedures for entry.

Cover-open + battery life

plainCover-open + battery life
cover_open from reed/tilt → flag (unauthorised entry/theft)

Buried + powerless → battery + LoRa:
  deep-sleep; report on change/schedule; faster if alarmed.

Program Flowchart

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

Manhole Safety Monitor — firmware flowchartControl flow through the main program loop. Wake; read level, gases, coverLevel rising towardoverflow?Flood/blockage alertCheck gasFlood/blockage alertCheck gasDangerous gas / low O₂?Safety alert (atmosphere)Report statusSafety alert (atmosphere)Report statusSleep (faster if alarmed)
Manhole Safety Monitor — 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. Deploy sealed, rugged sensing

    Fit a level sensor (non-contact/hydrostatic) and sewer gas sensors (H₂S/CH₄/CO/O₂), sealed and ruggedised against the wet, corrosive environment, plus a cover-open sensor.

    Battery-power with deep sleep and LoRa reporting; supervise the battery.

  2. Set up alerts

    Alert on rising level trending toward overflow (with lead time) and on dangerous gas/low-oxygen concentrations; flag cover-open.

  3. Report and map

    Report level/gas/cover status and alerts over LoRa to a city map, with pre-entry atmosphere awareness for authorised workers/supervisors.

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. Assess flood and atmosphere

    Compute the level trend and time-to-overflow for flood warning, and evaluate gas concentrations for safety, sampling faster when alarmed.

    cppmanhole-assess.ino
    #define L_OVERFLOW 20.0f     // cm below cover = overflow risk
    #define R_WARN 5.0f          // cm/min rising fast
    
    const char* floodCheck(float level, float rate){
      if (level > (100.0f - L_OVERFLOW)) return "level near overflow";
      if (rate > R_WARN) return "level rising fast (blockage?)";
      return nullptr;
    }
    
    // Atmosphere AWARENESS (not entry certification).
    const char* gasCheck(float h2s, float ch4_lel, float co, float o2){
      if (o2 < 19.5f || o2 > 23.5f) return "oxygen out of range";
      if (h2s > H2S_LIMIT)          return "H2S toxic";
      if (ch4_lel > LEL_ALARM)      return "methane explosive";
      if (co > CO_LIMIT)            return "CO high";
      return nullptr;
    }
    if (rate > R_WARN) return "level rising fast (blockage?)"A fast-rising level warns of a developing blockage/flood with lead time, before it overflows onto the street.
    if (o2 < 19.5f || o2 > 23.5f) return "oxygen out of range"Oxygen deficiency (or enrichment) is a primary confined-space killer and is checked first.
    if (h2s > H2S_LIMIT) return "H2S toxic"Hydrogen sulphide — the classic lethal sewer gas that fools the sense of smell — is alarmed at its toxic limit.
    Atmosphere AWARENESS (not entry certification)The comment states the scope in the code: this informs and warns about the atmosphere; it does not certify a space safe to enter, which requires personal detectors and procedures.
  2. Alert, report and supervise

    Raise flood and gas/safety alerts, flag cover-open, report status/alerts over LoRa to a city map, and supervise battery — sampling faster while alarmed.

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.

cppmanhole-safety-monitor.ino
/* ═══════════════════════════════════════════════════════════════
   Manhole Safety Monitor — ESP32, LoRa, battery (sealed/rugged)

   Monitors sewer LEVEL (flood/blockage early warning) and toxic/
   explosive GASES + oxygen (worker/public safety awareness), plus
   cover-open. AN AID — NOT a substitute for certified personal gas
   detectors and confined-space entry procedures.
   ══════════════════════════════════════════════════════════════════ */

#include <LoRa.h>
#include <SPI.h>
#include <Preferences.h>
#include <math.h>

#define PIN_TRIG 26
#define PIN_ECHO 25
#define PIN_H2S  35
#define PIN_CH4  32
#define PIN_CO   33
#define PIN_O2   34
#define PIN_COVER 27
#define DEPTH_CM 100.0f
#define NODE_ID 23

Preferences prefs;
RTC_DATA_ATTR float prevLevel = NAN; RTC_DATA_ATTR uint32_t prevMs = 0;

float levelCm(){
  digitalWrite(PIN_TRIG,LOW); delayMicroseconds(2);
  digitalWrite(PIN_TRIG,HIGH); delayMicroseconds(10); digitalWrite(PIN_TRIG,LOW);
  long us=pulseIn(PIN_ECHO,HIGH,30000);
  if(!us) return NAN;
  return DEPTH_CM - us/58.0f;                    // water height
}
float gas(int pin, float fs){ long s=0; for(int i=0;i<32;i++) s+=analogRead(pin);
  return (s/32.0f)/4095.0f*fs; }

void report(float lvl,float h2s,float ch4,float co,float o2,bool cover,
            const char* flood,const char* gasAlert){
  LoRa.beginPacket();
  LoRa.printf("{\"mh\":%d,\"level\":%.0f,\"h2s\":%.1f,\"ch4_lel\":%.0f,"
              "\"co\":%.0f,\"o2\":%.1f,\"cover_open\":%d,"
              "\"flood\":\"%s\",\"gas\":\"%s\"}",
              NODE_ID, lvl, h2s, ch4, co, o2, cover?1:0,
              flood?flood:"none", gasAlert?gasAlert:"none");
  LoRa.endPacket();
}

void setup(){
  Serial.begin(115200);
  pinMode(PIN_TRIG,OUTPUT); pinMode(PIN_ECHO,INPUT); pinMode(PIN_COVER,INPUT_PULLUP);
  SPI.begin(); LoRa.setPins(5,14,2); LoRa.begin(433E6); LoRa.setSpreadingFactor(10);

  float lvl = levelCm();
  uint32_t now = millis();
  float rate = (!isnan(prevLevel)&&prevMs)? (lvl-prevLevel)/((now-prevMs)/60000.0f):0;
  prevLevel=lvl; prevMs=now;

  float h2s=gas(PIN_H2S,H2S_FS), ch4=gas(PIN_CH4,100), co=gas(PIN_CO,CO_FS),
        o2=gas(PIN_O2,25);
  bool cover = digitalRead(PIN_COVER)==HIGH;

  const char* flood = (lvl > 80.0f) ? "near overflow" :
                      (rate > 5.0f) ? "rising fast" : nullptr;
  const char* gasAlert = (o2<19.5f||o2>23.5f)?"oxygen out of range":
                         (h2s>H2S_LIMIT)?"H2S toxic":
                         (ch4>LEL_ALARM)?"methane explosive":
                         (co>CO_LIMIT)?"CO high":nullptr;

  report(lvl,h2s,ch4,co,o2,cover,flood,gasAlert);

  bool alarmed = flood || gasAlert || cover;
  esp_sleep_enable_timer_wakeup((uint64_t)(alarmed?120:900)*1000000ULL);
  esp_deep_sleep_start();
}
void loop(){}
float rate = ... (lvl-prevLevel)/((now-prevMs)/60000.0f)The level's rate of rise (persisted across sleep) gives flood/blockage early warning before the level actually reaches overflow.
const char* gasAlert = (o2<19.5f||o2>23.5f)?"oxygen out of range":The atmosphere is evaluated for the sewer killers — oxygen deficiency, H₂S, methane, CO — as safety awareness.
bool cover = digitalRead(PIN_COVER)==HIGHA cover-open flag catches unauthorised entry or cover theft alongside the environmental hazards.
esp_sleep_enable_timer_wakeup((uint64_t)(alarmed?120:900)The node deep-sleeps for long battery life but samples faster when a flood or gas hazard is present.
AN AID — NOT a substitute for certified personal gas detectorsThe header states the scope: entry safety requires certified personal detectors and confined-space procedures, never this fixed monitor.

Configuration & Calibration

Configuration steps

  • Configure level sensing and the overflow/rate thresholds, and the gas sensors and safety limits (H₂S/CH₄/CO/O₂).
  • Configure cover-open detection, LoRa reporting and battery supervision.
  • Set faster sampling when alarmed and the city-map integration.
  • State the scope clearly: aid, not a substitute for certified detectors/procedures.

Calibration procedure

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

  1. Level

    Calibrate the level scale and overflow point; verify the rate-of-rise warning.

  2. Gas

    Understand these are educational-grade sensors; set conservative safety limits and test response. Certified personal detectors are required for entry.

  3. Battery/report

    Verify long battery life with deep sleep and faster-when-alarmed reporting.

Network Architecture & Connectivity

Manhole Safety Monitor — network topologyPath taken by telemetry from field node to end user. Edge nodesGatewayCloudClientsManhole nodeESP32Other manholesnetworkLoRaCity gatewayto dashboardMQTTSewer/safety dashboardlevel + gasOpsflood/gas alertsCrewsawareness
Manhole Safety Monitor — network topology

Communication protocol

Nodes report level/gas/cover on change/schedule (faster when alarmed); flood and gas/safety alerts publish immediately. Framed as an aid, not entry certification.

Topic / endpointDirectionPayload
manhole/<id>/statusnode → dashboardlevel, gases, O₂, cover
manhole/<id>/alertnode → opsflood/blockage / gas / cover-open
manhole/<id>/healthnode → opsbattery/supervision

Message contract between the device and the broker.

Cloud platform configuration

A dashboard maps manhole level, atmosphere and cover status across the city, raises flood and gas alerts, and provides atmosphere awareness — clearly as an aid, not a substitute for certified detectors/procedures.

Dashboard setup

A city map of manhole level/gas/cover, flood/gas alerts, and sensor/battery health.

Mobile app integration

Flood/blockage and gas/safety alerts; cover-open notifications.

Security considerations

  • Authenticate node data; supervise battery/health.
  • Frame gas data as awareness, never entry certification.
  • Alert on silent nodes.

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
Raise the level toward overflowFlood/blockage early warning with lead time
Introduce test gas / low oxygen (safely)Gas/safety alert
Open the coverCover-open flag
Alarmed vs quietFaster sampling when alarmed; long life when quiet
Confirm scope in output/UIClear "aid, not a substitute for personal detectors/procedures" messaging
Solar/battery cycleNode reports over a season; supervision works

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

Expected output

The city map shows each manhole's level, gas readings, cover status and alerts (flood, gas, cover), with pre-entry atmosphere awareness clearly framed as an aid.

jsonmanhole.json
{
  "mh": 23,
  "level": 84,
  "h2s": 12.0,
  "ch4_lel": 8,
  "co": 5,
  "o2": 20.6,
  "cover_open": 0,
  "flood": "near overflow",
  "gas": "none"
}

Manhole 23 near overflow (flood early warning) with a currently-safe atmosphere; a dangerous gas reading would raise a safety alert — but entry always requires certified personal detectors and confined-space procedures, never this monitor alone.

Automated machinery on a factory production line
A monitoring and early-warning aid — never a substitute for certified personal detectors and confined-space procedures. Photograph sourced from Wikimedia Commons — Factory automation.jpg. Reused under the licence stated on that page; please check it before republishing.

Troubleshooting: Common Errors & Fixes

Flood not caught early

Likely cause. Alerting only on high level

Fix. Use the rate of rise for early warning with lead time

Gas readings drift

Likely cause. Sensor ageing/environment

Fix. Recalibrate; conservative limits; certified personal detectors for entry

Node corrodes/fails

Likely cause. Wet/corrosive environment

Fix. Seal and ruggedise; rated sensors; supervise battery

Treated as entry-safe device

Likely cause. Scope misunderstanding

Fix. It is an AID — entry requires certified detectors and confined-space procedures

Battery dies

Likely cause. Reporting too often

Fix. Deep sleep; report on change/schedule; faster only when alarmed

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.

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

  • Deep-sleep between reads; sample faster when a flood or gas hazard is present.
  • Persist level state for rate-of-rise across sleep.
  • Report on change/schedule and alerts immediately.
  • Supervise battery/health across the network.
  • 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 A MONITORING/EARLY-WARNING AID — NOT a substitute for certified, calibrated PERSONAL gas detectors and confined-space entry procedures (ventilation, permit, standby, rescue). Never enter relying on a fixed monitor.
  • Confined spaces and toxic/explosive atmospheres are lethal — H₂S deadens smell; follow the law and life-safety procedures.
  • Seal/ruggedise for the wet, corrosive environment; use rated sensors.
  • Provide flood early warning and atmosphere awareness; escalate real hazards to proper procedures.
  • 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

  • Recalibrate/replace gas sensors regularly; verify level sensing.
  • Inspect seals/enclosure for corrosion; supervise battery.
  • Test alerts and cover-open detection.
  • Reinforce scope: aid, not a substitute for personal detectors/procedures.
  • 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 flow/rainfall data for better flood prediction.
  • Add H₂S corrosion monitoring for asset management.
  • Integrate with confined-space entry management (still requiring personal detectors).
  • City-wide sewer analytics and predictive maintenance.
  • 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 two hazards does it cover?

Flooding/blockage (a rising sewer level backing up toward the street) and the lethal confined-space atmosphere (H₂S, methane, CO, low oxygen). Both are otherwise invisible until too late.

Can workers rely on it to enter safely?

Absolutely not. It is a monitoring and early-warning aid. Confined-space entry legally and morally requires certified, calibrated personal gas detectors and proper procedures (ventilation, permit, standby, rescue). It complements those; it never replaces them.

How does it warn of flooding early?

By watching the level and its rate of rise. A fast-rising level signals a developing blockage or flood before it overflows onto the street, giving lead time to respond.

Why is H₂S so dangerous?

It is toxic and deadly at higher concentrations, and it deadens the sense of smell, so a worker can be overcome without warning. That is exactly why certified personal detection and procedures are mandatory for entry.

How does it work in a buried, powerless manhole?

Battery power, LoRa reporting, deep sleep and a sealed, ruggedised enclosure — reporting on change/schedule and faster when a hazard is present for long life.

References & Learning Resources

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

  1. Confined space and sewer gas hazards (OSHA)OSHA
  2. Hydrogen sulphide (H₂S) safetyReference
  3. Sewer gasReference
  4. Manhole / sewer monitoringReference
  5. Gas detection and exposure limitsReference