Siddhant Kumar
Project 078 · Smart City

Smart Waste Bin.

Senses how full each bin is so trucks collect the bins that are actually full — not empty ones on a fixed schedule — cutting collection cost, fuel and overflowing bins.

Beginner 8–14 hours 28 min read WasteSensorsRouting
Jump to source Bill of materials
Smart Waste Bin — reference build illustration MCU VCC · GND · SIG · NC
Difficulty
Beginner
Build time
8–14 hours
Indicative cost
₹1,500 – ₹2,800 per bin
Platform
ESP32 DevKit V1 (ESP-WROOM-32)
Category
Smart City
Last updated
28 July 2026
Contents — 26 sections

Project Overview

Senses how full each bin is so trucks collect the bins that are actually full — not empty ones on a fixed schedule — cutting collection cost, fuel and overflowing bins.

Municipal waste collection is astonishingly inefficient because it is blind: trucks follow fixed routes on fixed schedules, emptying every bin whether it is full or barely used, which means driving to and lifting half-empty bins (wasting fuel, time and money) while other bins overflow between visits (creating litter, smell and complaints). The fix is simple in concept: know how full each bin is, and collect the ones that need it. This project builds the sensor that makes that possible — a fill-level sensor in each bin that reports how full it is, so collection can be driven by actual need rather than a blind timetable.

The sensing is straightforward: an ultrasonic sensor in the lid measures the distance down to the waste surface, which converts to a fill percentage. Each bin reports its fill level (and its trend) over a low-power wide-area network, and the fleet's worth of readings becomes a live map of which bins are full, filling fast, or still empty. From that, collection is optimised: routes are planned to empty the bins that are actually full or nearly so, skipping the empty ones — which cuts the number of lifts, the distance driven and the fuel burned, and stops bins overflowing because a fast-filling bin is collected before it spills.

The value compounds: fewer, fuller collections mean lower cost and emissions, fewer overflow complaints, and — from the fill-rate data — the ability to predict when each bin will be full and right-size bins and schedules. Because bins are everywhere and have no power, the sensor is battery-powered and wireless (LoRa/NB-IoT) and must last a long time on a small battery, so it sleeps and reports infrequently. It is honest that ultrasonic fill sensing has quirks (irregular waste surfaces, a sensor that can be fouled or blocked) and that route optimisation is a logistics problem on top of the sensing. But as a fill-level sensor that turns a blind, wasteful, schedule-driven collection system into a demand-driven one, it delivers a large, well-proven efficiency gain — collect the full bins, skip the empty ones.

A city skyline at night
Fill sensing turns blind, scheduled collection into demand-driven collection of the full bins. 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

  • Senses how full each bin is (ultrasonic fill level → percentage)
  • Reports fill level and trend over a low-power wireless network
  • Builds a live map of which bins are full/filling/empty
  • Drives demand-based collection (empty full bins, skip empty ones)
  • Cuts lifts, distance, fuel and overflow
  • Predicts fill-up times and right-sizes bins/schedules
  • Runs a long time on a small battery (sleep + infrequent reports)

Real-World Applications

SettingHow it is used
Municipal waste collectionDemand-based collection to cut cost/fuel and stop overflows.
Commercial / campus wasteRight-sizing collection for offices, campuses and facilities.
Public-space binsPreventing overflow of high-traffic street/park bins.
Recycling streamsFill monitoring per stream for efficient recycling collection.

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

Features & Capabilities

  • Ultrasonic fill-level sensing
  • Fill-trend and prediction
  • Demand-driven route optimisation
  • Overflow prevention
  • Long battery life (LoRa/NB-IoT, deep sleep)
  • Fleet-wide fill map and analytics
  • Honest about sensing quirks and logistics

Difficulty, Time & Required Skills

AttributeValue
Difficulty levelBeginner
Estimated completion time8–14 hours
Indicative build cost₹1,500 – ₹2,800 per bin
Primary disciplineSmart City
Reference platformESP32 DevKit V1 (ESP-WROOM-32)

Skills you should have (or will pick up)

  • Ultrasonic fill-level sensing and percentage conversion
  • Fill-trend and prediction
  • Low-power wireless (LoRa/NB-IoT) and battery life
  • Demand-based route/collection logic
  • Fleet analytics

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
DS18B20 waterproof temperature probe
Dozens can share one GPIO — you address them by ROM code.
−55 to +125 °C, ±0.5 °C from −10 to +85 °C, 9–12-bit resolution, unique 64-bit ROM ID1₹160
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
TP4056 Li-ion charger + DW01 protection
Buy the version *with* protection ICs — the bare charger will over-discharge your cell.
1 A programmable CC/CV charge to 4.2 V ±1 %, over-discharge and short protection1₹45
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
Lid-mounted ultrasonic sensor
Robust to a dirty/damp bin environment
Waterproof ultrasonic ranging in the bin lid (fill level)1₹400
Long-life battery
Battery life is critical at fleet scale
Large battery for years of sleep + infrequent reporting1₹300
LoRa/NB-IoT moduleLow-power wide-area comms1₹500
Rugged bin enclosureSealed housing surviving the bin environment1₹250

Estimated total: ₹3,485, 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
DS18B20 waterproof temperature probe−55 to +125 °C, ±0.5 °C from −10 to +85 °C, 9–12-bit resolution, unique 64-bit ROM ID3.0–5.5 V1-Wire (multi-drop)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
TP4056 Li-ion charger + DW01 protection1 A programmable CC/CV charge to 4.2 V ±1 %, over-discharge and short protection4.5–5.5 V inmicro-USB / padsDatasheet
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.
DS18B20 waterproof temperature probe3.0–5.5 V1.5Dozens can share one GPIO — you address them by ROM code.
SX1278 LoRa 433 MHz module (Ra-02)3.3 V120Never power the radio without an antenna — the PA will destroy itself.
TP4056 Li-ion charger + DW01 protection4.5–5.5 V in1000Buy the version *with* protection ICs — the bare charger will over-discharge your cell.

Summed typical draw is 1311.5 mA. With a 1.5× design margin the supply should deliver at least 2000 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

Block Diagram

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

Smart Waste Bin — system block diagramFunctional block diagram of the Smart Waste Bin system. Sense fillUltrasonicfill %Temp (opt)fireReportESP32fill + trendLoRa/NB-IoTinfrequentAggregateFill mapfull/emptyPredictfill-up timeCollectOptimise routefull bins onlyNo overflowcollect in timerightrightnone
Smart Waste Bin — 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.

Smart Waste Bin — wiring schematicConnection schematic showing which controller pin drives each peripheral. Sensors / InputsControllerActuators / OutputsESP32 DevKit V1(ESP-WROOM-32)3.3 V logic / 5 V USBUltrasonic (lid)GPIO 26/25Distance to waste(fill)Temp (fire safety)GPIO 4Bin temperature(optional)LoRa/NB-IoTSPI/UARTFill reportBattery senseGPIO 34SupervisionTP40563V3 regSupplyStatus LEDGPIO 2Health
Smart Waste Bin — wiring schematic
PeripheralPeripheral pinController pinSignal
Ultrasonic (lid)TRIG/ECHOGPIO 26/25Distance to waste (fill)
Temp (fire safety)DQGPIO 4Bin temperature (optional)
LoRa/NB-IoTbusSPI/UARTFill report
Battery senseADCGPIO 34Supervision
TP4056OUT3V3 regSupply
Status LEDINGPIO 2Health

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

  • Mount the ultrasonic sensor in the lid aimed down at the waste; convert distance to fill percentage using the bin depth.
  • Median-filter readings because a waste surface is irregular and one ping can be off; flag a blocked/fouled sensor.
  • Battery + LoRa/NB-IoT — bins have no power; deep-sleep and report infrequently (on change or a few times a day) for long life.
  • Optionally add a temperature sensor for a bin-fire early warning.
  • Seal the electronics against the damp, dirty bin environment; supervise the battery.
An HC-SR04 ultrasonic distance sensor with its two transducers
An ultrasonic sensor in the lid measures the fill level and reports it over low-power wireless. Photograph sourced from Wikimedia Commons — HC-SR04.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.

Smart Waste Bin — architecture stackLayered architecture from hardware to user interface. Hardware layerESP32 DevKit V1 (ESP-WROOM-32) · JSN-SR04T waterproof ultrasonic sensor ·DS18B20 waterproof temperature probeDriver layerwifi · lorolib · arduinojson · preferencesApplication logicsampling loop · filtering · thresholds · state machineTransport layerLoRa/NB-IoT → waste-management platform · TLS · retry and backoffPresentation layerdashboard · mobile notifications · historical charts
Smart Waste Bin — architecture stack

Working Principle

Waste collection is inefficient for one root reason: it operates without information. A fixed schedule must assume the worst — collect everything often enough that nothing overflows — which guarantees that most collections are of bins that did not need it, while a bin that fills faster than average still overflows between visits. Every wasted lift is fuel, labour and truck-wear spent on nothing; every overflow is litter, smell and a complaint. The entire inefficiency comes from not knowing how full each bin is, so the fix is to measure it and collect by need.

The measurement is simple and robust: an ultrasonic sensor in the lid times an echo down to the waste surface, and the distance converts to a fill percentage against the bin's depth (empty = full distance, full = short distance). The practical care is that a waste surface is irregular — a bag piled on one side, a gap in the middle — so a single ping can mislead; taking several pings and using the median gives a stable fill reading. The sensor should also recognise and flag a blocked or fouled face (a bag pressed against it, dirt on the transducer) rather than report a false "full".

Those per-bin fill levels aggregate into a live map, and that map enables the two wins. First, demand-driven collection: routes are planned to empty the bins that are actually full or nearly full and skip the empty ones, which directly cuts the number of lifts, the distance driven and the fuel burned — a large, well-documented saving. Second, overflow prevention: a bin filling fast is visible and collected before it spills, and the fill-rate trend lets the system predict when each bin will be full, so collection can be scheduled just ahead of overflow rather than reactively. Over time the same fill-rate data supports right-sizing — bigger bins or more frequent service where fill is high, less where it is low.

The deployment shape is dictated by the fact that bins are everywhere and have no power. So the sensor is battery-powered and wireless over a low-power wide-area network (LoRa or NB-IoT — long range, tiny data, minimal power), and the dominant design constraint is battery life: fill changes slowly, so the sensor deep-sleeps almost all the time and reports infrequently — a few times a day, or on a meaningful change — which makes years of life on a small battery achievable at fleet scale, with supervision so a dead sensor is noticed. The design is honest that ultrasonic fill sensing has quirks to manage and that turning the fill map into optimal routes is a separate logistics problem (a routing optimisation on top of the sensing). But the core contribution is clear and high-value: it replaces a blind, wasteful, schedule-driven system with a demand-driven one — collect the full bins, skip the empty ones, and stop the overflows — which is one of the most tangible and widely-proven wins in smart-city infrastructure.

The maths behind it

Fill percentage

plainFill percentage
Sensor at the lid, bin depth D, distance to waste d:

  fill% = (D − d) / D × 100   (clamp 0–100)

Median of several pings (waste surface is irregular).
Flag blocked/fouled sensor (implausible/constant near-zero d).

Fill-rate prediction

plainFill-rate prediction
From fill history:
  rate = Δfill / Δt   (%/day)
  days_to_full ≈ (100 − fill) / rate

Schedule collection just before predicted overflow;
right-size service from the fill rate.

Battery life (infrequent reporting)

plainBattery life (infrequent reporting)
life ≈ capacity / ( I_sleep + f_report·E_tx )

Fill changes slowly → report a few times/day or on change,
deep-sleep between → years on a small battery at fleet scale.

Program Flowchart

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

Smart Waste Bin — firmware flowchartControl flow through the main program loop. Wake on scheduleMeasure fill (median)Changed enough / thresholdcrossed?Report fillSleepReport fillSleepPlatform: aggregate + predictOptimise collection (fullbins)
Smart Waste Bin — 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. Fit and calibrate the fill sensor

    Mount the ultrasonic sensor in the lid aimed at the waste, set the bin depth, and calibrate empty (full distance) and full (short distance). Median-filter readings and flag blocked/fouled faces.

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

  2. Set up wireless reporting

    Report fill (and trend) over LoRa/NB-IoT infrequently (on change or a few times a day) for long battery life.

  3. Aggregate and optimise

    Aggregate fill levels into a live map, predict fill-up times, and drive demand-based route optimisation and overflow prevention.

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. Measure fill robustly and report on change

    Take several pings, use the median, convert to fill percentage, flag blockage, and report only on a meaningful change or scheduled beat.

    cppbin-fill.ino
    #define BIN_DEPTH_CM 100.0f
    #define REPORT_DELTA 10.0f     // report on >=10% change
    RTC_DATA_ATTR float lastReported = -1;
    
    float medianDistance(){
      float d[5];
      for(int i=0;i<5;i++){ d[i]=pingCm(); delay(60); }
      for(int i=1;i<5;i++){float k=d[i];int j=i-1;
        while(j>=0&&d[j]>k){d[j+1]=d[j];j--;}d[j+1]=k;}
      return d[2];                          // median rejects an odd ping
    }
    
    int fillPercent(float dist){
      if (dist < 3 || isnan(dist)) return -1;          // blocked/fouled -> flag
      float f = (BIN_DEPTH_CM - dist)/BIN_DEPTH_CM*100;
      return (int)constrain(f, 0.0f, 100.0f);
    }
    
    bool shouldReport(int fill, bool scheduledBeat){
      if (fill < 0) return true;                        // report a blockage
      if (scheduledBeat) return true;
      return fabsf(fill - lastReported) >= REPORT_DELTA; // meaningful change
    }
    float medianDistance()Takes several pings and uses the median, so one spurious echo off an irregular waste surface does not fake the fill level.
    if (dist < 3 || isnan(dist)) return -1; // blocked/fouled -> flagA too-close or invalid reading means the sensor is blocked or fouled, which is flagged rather than reported as a false "full".
    float f = (BIN_DEPTH_CM - dist)/BIN_DEPTH_CM*100The distance to the waste is converted to a fill percentage against the bin depth — the actionable number for collection.
    return fabsf(fill - lastReported) >= REPORT_DELTA;Reporting only on a meaningful change (plus a scheduled beat) keeps transmissions rare, which is what gives years of battery life.
  2. Aggregate, predict and optimise collection

    Aggregate fill into a map, compute fill-rate and days-to-full, and plan routes to collect full/nearly-full bins and skip empty ones, preventing overflow.

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.

cppsmart-waste-bin.ino
/* ═══════════════════════════════════════════════════════════════
   Smart Waste Bin — ESP32 + ultrasonic, LoRa/NB-IoT, battery

   Senses bin fill level (median-filtered), reports on meaningful change
   for long battery life, and feeds demand-based collection. Flags a
   blocked sensor; optional temperature for fire safety.
   ══════════════════════════════════════════════════════════════════ */

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

#define PIN_TRIG 26
#define PIN_ECHO 25
#define BIN_DEPTH_CM 100.0f
#define REPORT_DELTA 10.0f
#define SLEEP_S 21600          // 6 h base (fill changes slowly)
#define BIN_ID 312

Preferences prefs;
RTC_DATA_ATTR float lastReported = -1;

float pingCm(){
  digitalWrite(PIN_TRIG,LOW); delayMicroseconds(2);
  digitalWrite(PIN_TRIG,HIGH); delayMicroseconds(10); digitalWrite(PIN_TRIG,LOW);
  long us=pulseIn(PIN_ECHO,HIGH,30000);
  return us? us/58.0f : NAN;
}
float medianDistance(){
  float d[5]; for(int i=0;i<5;i++){ d[i]=pingCm(); delay(60);}
  for(int i=1;i<5;i++){float k=d[i];int j=i-1;
    while(j>=0&&(isnan(d[j])||d[j]>k)){d[j+1]=d[j];j--;}d[j+1]=k;}
  return d[2];
}

void report(int fill, float vbat){
  LoRa.beginPacket();
  LoRa.printf("{\"bin\":%d,\"fill\":%d,\"vbat\":%.2f}",
              BIN_ID, fill, vbat);
  LoRa.endPacket();
}

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

  float dist = medianDistance();
  int fill;
  if (dist < 3 || isnan(dist)) fill = -1;          // blocked/fouled
  else fill = (int)constrain((BIN_DEPTH_CM-dist)/BIN_DEPTH_CM*100, 0.0f, 100.0f);

  bool scheduledBeat = true;                        // every wake is a beat here
  bool changed = (fill < 0) || (lastReported < 0) ||
                 (fabsf(fill - lastReported) >= REPORT_DELTA);

  if (changed || scheduledBeat){
    report(fill, readBattery());
    lastReported = fill;
  }

  esp_sleep_enable_timer_wakeup((uint64_t)SLEEP_S*1000000ULL);
  esp_deep_sleep_start();
}
void loop(){}
float medianDistance()Uses the median of several pings so an irregular waste surface or a single bad echo does not corrupt the fill reading.
if (dist < 3 || isnan(dist)) fill = -1; // blocked/fouledA blocked or fouled sensor is flagged as a special value rather than reported as a false full bin.
if (changed || scheduledBeat){The bin reports only on a meaningful fill change or a scheduled beat, keeping transmissions rare for long battery life.
esp_sleep_enable_timer_wakeup((uint64_t)SLEEP_S*1000000ULL)The sensor deep-sleeps for hours between reads, drawing almost nothing — essential for a battery-powered fleet of thousands of bins.
LoRa.printf("{\"bin\":%d,\"fill\":%dA tiny fill report per bin aggregates into the live map that drives demand-based collection.

Configuration & Calibration

Configuration steps

  • Set the bin depth and the report-on-change threshold and beat interval.
  • Configure the blockage flag and optional temperature (fire) sensing.
  • Configure LoRa/NB-IoT reporting and battery supervision.
  • Set the collection thresholds and prediction lead time at the platform.

Calibration procedure

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

  1. Fill scale

    Calibrate empty (full distance) and full (short distance) for the bin; verify the fill percentage at intermediate levels.

  2. Robustness

    Confirm the median filter rejects irregular-surface pings and that blockage is flagged.

  3. Battery/report

    Verify report-on-change + beat and measure battery life at the expected report rate.

Network Architecture & Connectivity

Smart Waste Bin — network topologyPath taken by telemetry from field node to end user. Edge nodesGatewayCloudClientsBin sensorESP32Other binsfleetLoRa / NB-IoTCity gatewayto platformMQTTWaste platformfill + routesDispatchroutesOpsoverflow/blockage
Smart Waste Bin — network topology

Communication protocol

Bins report fill on meaningful change plus a slow beat; the platform aggregates fill, predicts fill-up, and optimises collection routes.

Topic / endpointDirectionPayload
waste/bin/<id>/fillbin → platformfill %, battery, blockage flag
waste/route/planplatform → dispatchoptimised route (full bins)
waste/bin/<id>/alertbin → opsoverflow risk / blocked / low battery

Message contract between the device and the broker.

Cloud platform configuration

A waste-management platform maps fill, predicts fill-up, optimises routes to collect full bins and skip empty ones, and flags overflow/blockage — cutting cost, fuel and complaints.

Dashboard setup

A city map of bin fill, predicted overflows, optimised routes, and sensor/battery health.

Mobile app integration

Overflow-risk, blockage and low-battery alerts; route plans for crews.

Security considerations

  • Authenticate reports so fill data is trustworthy.
  • Supervise battery/health; flag silent bins.
  • Keep reporting rare for battery life at fleet scale.

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
Fill the bin partwayFill percentage tracks; reports on meaningful change
Irregular surface (bag on one side)Median filter gives a stable reading
Block the sensor faceBlockage flagged (not a false full)
Leave stable for a dayOnly scheduled beats — battery saved
Aggregate many binsMap/prediction drives full-bin collection
Battery run-downLow battery reported (supervision)

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

Expected output

The platform shows a map of bin fill levels, predicted fill-up times, and optimised collection routes (full bins), with overflow and blockage/battery alerts.

jsonbin.json
{
  "bin": 312,
  "fill": 84,
  "vbat": 3.71
}

Bin 312 at 84% full — flagged for the next optimised route while empty bins nearby are skipped; a fast fill-rate would schedule it just before overflow, and a blocked sensor would report a flag instead of a false full.

An ESP32 development board with the ESP-WROOM-32 module and USB connector
Aggregated fill data optimises routes and prevents overflow — cutting cost, fuel and complaints. 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.

Troubleshooting: Common Errors & Fixes

Unreliable fill readings

Likely cause. Irregular surface / single ping

Fix. Median-filter several pings; mount aimed at the bin centre

False "full"

Likely cause. Blocked/fouled sensor

Fix. Flag blockage (too-close/invalid distance); clean the sensor

Battery dies fast

Likely cause. Reporting too often

Fix. Report on change + slow beat; deep-sleep between

Overflows still happen

Likely cause. No prediction / late collection

Fix. Predict fill-up from rate; collect with lead time

Dead sensor unnoticed

Likely cause. No supervision

Fix. Report battery/beat; flag silent bins

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

  • Report on meaningful change plus a slow beat; deep-sleep for years of battery life.
  • Median-filter fill; flag blockage.
  • Aggregate and predict at the platform; optimise routes there.
  • Supervise battery/health across the fleet.
  • 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

  • Seal electronics against the damp, dirty bin environment; site the sensor safely in the lid.
  • Optional temperature sensing can give a bin-fire early warning.
  • Ultrasonic fill sensing has quirks — filter and flag rather than trust a single reading.
  • Route optimisation is a logistics layer; validate route plans operationally.
  • 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

  • Clean fouled sensors (flagged as blocked); check mounting.
  • Replace batteries on a fleet plan; act on supervision alerts.
  • Recalibrate fill scale if bins change.
  • Review prediction/route performance and tune thresholds.
  • 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 full route-optimisation with truck capacity/constraints.
  • Add fill-type/contamination sensing for recycling.
  • Add dynamic pricing/scheduling from fill analytics.
  • Add bin-fire detection and public-facing fill maps.
  • 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

Where does the saving come from?

From collecting by need instead of schedule — emptying the bins that are actually full and skipping the empty ones. That cuts the number of lifts, the distance driven and the fuel burned, and stops bins overflowing between fixed visits.

How does it measure fill?

An ultrasonic sensor in the lid measures the distance down to the waste, which converts to a fill percentage against the bin depth. Several pings are median-filtered because a waste surface is irregular.

Why battery and wireless?

Bins are everywhere and have no power, so sensors are battery-powered and use low-power wireless (LoRa/NB-IoT). Because fill changes slowly, they deep-sleep and report infrequently, giving years of battery life.

What if a bag blocks the sensor?

A too-close or invalid reading is recognised as a blockage and flagged, rather than reported as a false "full" — so crews clean it instead of the map lying.

Can it prevent overflows?

Yes — a fast-filling bin is visible, and the fill-rate trend predicts when it will be full, so it can be collected just before it overflows rather than after.

References & Learning Resources

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

  1. Smart waste managementReference
  2. Fill-level sensing (ultrasonic)Reference
  3. Route optimisation / vehicle routingReference
  4. LoRa / NB-IoT low-power networksReference
  5. Smart-city waste efficiency studiesReference