Touchless automatic lid, dual-sensor waste-level monitoring, full-bin alerts, and a live web dashboard for managing bins across a city.
| Public city dashboard | https://snischayprasad.github.io/Smart-Dustbin-Embedded-System/website/ |
| Try the firmware | Live simulator — no sign-in needed |
| Admin console | /login.html — demo sign-in Nischay / Admin@123 gives a read-only session; fleet control requires Google sign-in as a registered administrator |
On the public page, scroll to Try the firmware yourself and press Uneven pile (A 90 / B 10) — that one button demonstrates the whole point of the dual-sensor design, and needs no sign-in.
Built on the ESP32, so the bin has Wi-Fi and a REST API and the dashboard can drive a real board. An Arduino UNO build is included as an alternative.
No hardware? No problem. Import
simulation/wokwi/diagram.jsoninto wokwi.com and the whole circuit appears, fully wired - Wi-Fi included, via the simulator's built-inWokwi-GUESTnetwork.
An ordinary dustbin is a passive container. This one senses, decides, acts and reports:
- It opens itself. An ultrasonic sensor on the front detects a hand within 25 cm and a servo lifts the lid. Nobody touches a dirty surface.
- It knows how full it is. Two more ultrasonic sensors inside the bin, on opposite diagonals, measure the empty air above the rubbish. Their readings are fused into one fill percentage.
- It escalates sensibly. Green under 75 %, blinking red from 75 %, solid red plus a short chirp at 90 %.
- It reports. Telemetry over serial or Wi-Fi feeds a city dashboard that shows every bin on a map and lets an operator control them remotely.
Two problems, one hygienic and one economic.
Hygiene. A public bin lid is one of the dirtiest surfaces in a building. Every person who opens it passes whatever is on their hands to the next. Removing the touch removes the pathway.
Economics. Waste collection normally runs on a fixed schedule — a van visits every bin whether it needs it or not. Half the visits are to bins that are nearly empty, which burns fuel and driver hours for nothing, while a handful of bins in busy spots overflow long before the van is due. Fill-level data replaces the timetable with evidence.
This is the design decision worth understanding, because it is what separates this project from the usual single-sensor smart bin.
Rubbish is never flat.
[ sensor A ] [ sensor B ]
| ^ | ^
| | 3 cm | | 27 cm
| v | v
~~~~~~~~~~~~\
\~~~~~~~~~~~~~~~~~~~~~~~~~~~~
^ a peak a hollow ^
____|____________________________________|____ bin floor
Sensor A alone says 90% -> "FULL, send a van" (wrong)
Sensor B alone says 10% -> "practically empty" (wrong)
Fused (A+B)/2 says 50% -> correct, plus UNEVEN LOAD flagged
Two sensors on opposite diagonals buy three things at once:
| Benefit | How |
|---|---|
| Accuracy | Two points describe a lumpy surface far better than one |
| Redundancy | If one fails, the bin runs on the other and flags itself degraded, instead of going blind |
| Diagnosis | A gap of more than 25 points means the load is piled to one side — reported as UNEVEN LOAD |
Full worked numbers in docs/12-bin-level-calculation.md.
- Touchless lid on a four-state machine with a safety re-open if a hand returns mid-close
- Dual in-bin level sensors fused into one percentage, with uneven-load detection and graceful single-sensor degradation
- Three-band alert policy — green / blinking red / solid red plus a 200 ms chirp every 2 s (not a continuous siren, which staff disable)
- Non-blocking cooperative scheduler — effectively no
delay()inloop() - Median-of-three filtering, range validation, echo timeouts, honest
SENSOR_ERRORreporting - Power-on self test that pings all three sensors and reports which answered
- Serial command set:
OPEN CLOSE AUTO MUTE UNMUTE EMPTY STATUS HELP - Optional 16x2 I2C LCD, compiled out entirely with one
#define - ESP32 variant exposing a REST API for genuine remote control
- Public website + admin dashboard with a live city map, remote commands and a collection-route planner
- In-browser firmware simulator on both pages — the real state machine ported to JavaScript, driven by three sensor sliders
- Sign in with Google (OAuth 2.0 / OIDC) with the ID token's RS256 signature verified in-browser against Google's JWKS — not just decoded
- Three-tier access — owner, administrator, viewer — from a user registry where every address is stored as a hash; the public demo login is read-only
- Owner-only user management console that hashes new addresses in-browser and generates the registry file to commit
- Optional Firestore store so the admin list is shared and instant — with Security Rules enforcing owner-only writes server-side, which is the one place in this project where authorisation is not merely a UI convention
- 180 automated tests, including 24 that try to get forged JWTs accepted
| Component | Qty | Purpose |
|---|---|---|
| ESP32 DevKit V1 (or Arduino UNO) | 1 | Controller, Wi-Fi |
| HC-SR04 ultrasonic sensor | 3 | 1 hand detection + 2 in-bin level |
| SG90 servo motor | 1 | Lifts the lid |
| Green LED + 220 ohm | 1 | Normal status |
| Red LED + 220 ohm | 1 | Warning / full |
| Active buzzer | 1 | Full-bin alert |
| 16x2 I2C LCD | 1 | Local readout (optional) |
| 1 kΩ + 2 kΩ resistors | 3 pairs | ECHO level shifting (ESP32 only) |
| Breadboard, jumpers, 5 V/2 A supply | - | - |
Approximate total 1,500 INR (the ESP32 is cheaper than an UNO). Zero if you simulate.
| Component | ESP32 GPIO | Arduino UNO pin |
|---|---|---|
| HC-SR04 #1 (hand, outside) | TRIG 5, ECHO 18 | D2 / D3 |
| HC-SR04 #2 (level A, inside) | TRIG 19, ECHO 23 | D4 / D5 |
| HC-SR04 #3 (level B, inside) | TRIG 32, ECHO 33 | D8 / D9 |
| Servo signal | 13 | D6 |
| Buzzer | 25 | D7 |
| Green LED | 26 via 220 Ω | D10 |
| Red LED | 27 via 220 Ω | D12 |
| LCD | 21 SDA, 22 SCL | A4 / A5 |
On real ESP32 hardware, fit a 1 kΩ / 2 kΩ divider on each of the three ECHO lines. The HC-SR04 drives 5 V and ESP32 GPIOs are 3.3 V only. Not needed on the UNO, and not needed in simulation.
Full tables, mounting guidance, the Wokwi pin-naming trap and the power budget: circuit_diagram/connections.md.
| Concept | Where |
|---|---|
| GPIO input / output | TRIG, ECHO, LEDs, buzzer |
| Microsecond pulse timing | pulseIn() on the echo line |
| PWM | Servo angle control |
| Finite state machine | 4-state lid controller |
| Cooperative scheduling | millis() task dispatch, no delay() |
| Sensor fusion | Averaging two in-bin sensors plus a disagreement flag |
| Signal filtering | Median-of-three spike rejection |
| Threshold logic and status bands | 25 cm / 75 % / 90 % |
| Calibration | Measuring the true empty-bin distance |
| Fault handling | Timeouts, sentinels, degraded mode, error blink |
| UART protocol design | Human line plus JSON line telemetry |
| Conditional compilation | #ifdef USE_LCD feature flag |
| Wireless / IoT | Wi-Fi station mode, HTTP server, REST API with CORS |
fillLevel = BIN_HEIGHT_CM - measuredDistance
fillPercent = (fillLevel / BIN_HEIGHT_CM) x 100
fused = (fillA + fillB) / 2
uneven = |fillA - fillB| > 25
With BIN_HEIGHT_CM = 30:
| Distance | 30 cm | 22.5 cm | 15 cm | 7.5 cm | 3 cm | 0 cm |
|---|---|---|---|---|---|---|
| Fill | 0 % | 25 % | 50 % | 75 % | 90 % | 100 % |
| Status | OK | OK | OK | WARNING | FULL | FULL |
- Open wokwi.com, then New Project > ESP32
- Paste
simulation/wokwi/diagram.jsoninto the diagram.json tab - Paste
simulation/wokwi/sketch.inointo the sketch.ino tab - Install ESP32Servo and LiquidCrystal I2C when prompted
- Press play, then click a sensor to change its distance
Wi-Fi works in the simulator via Wokwi-GUEST, so the built-in status page
and the REST API are live. An Arduino UNO variant is in
simulation/wokwi/uno/.
- Arduino IDE: add the ESP32 board package, install ESP32Servo and LiquidCrystal I2C
- Wire per the table above, including the three ECHO dividers
- Board: ESP32 Dev Module. Open
arduino_code/05_esp32_wifi_version/and upload - Serial Monitor at 115200 baud, line ending Newline
- Put your own Wi-Fi SSID and password at the top of the sketch
- Install the Servo and LiquidCrystal I2C libraries
- Open
arduino_code/04_smart_dustbin_complete/and upload - Serial Monitor at 9600 baud, line ending Newline
node server/server.jsOpen http://localhost:3000, or just double-click website/index.html.
Admin login: Nischay / Admin@123
node tests/twin.test.jsnode tests/oauth.test.jsnode tests/users.test.jsnode tests/store.test.js==================================================
SMART DUSTBIN - EMBEDDED SYSTEM (ESP32)
Device : BIN-001
Firmware: v2.0.0-wifi
Sensors : 1 hand + 2 in-bin level (A and B)
Bin height : 30.0 cm
Hand threshold : 25.0 cm
Warn / Full : 75 % / 90 %
Uneven-load gap: 25 %
==================================================
Power-on self test ... outputs OK
Sensor check: HAND OK | LEVEL-A OK | LEVEL-B OK
Connecting to Wi-Fi...
Connected. Dashboard URL: http://10.13.37.2
HTTP server started on port 80
System running. Type HELP for commands.
>>> Hand detected - opening lid
[32s] Hand=12.0cm | Lid=OPEN | A=88% B=14% | Fill=51% | Status=OK | Opens=1 | UNEVEN LOAD
[##########----------]
{"id":"BIN-001","fill":51,"fillA":88,"fillB":14,"spread":74,"uneven":true,"sensors":2,...}
A full captured session is in
data/sample_serial_output.txt.
Every sketch was compiled with arduino-cli against the real toolchains.
| Check | Result |
|---|---|
05_esp32_wifi_version (ESP32) |
983,221 B flash (75 %), 46,144 B RAM (14 %) |
04_smart_dustbin_complete (UNO) |
16,640 B flash (51 %), 836 B RAM (40 %) |
01_lid_module (UNO) |
5,434 B flash (16 %) |
02_bin_level_module (UNO) |
6,318 B flash (19 %) |
03_alert_module (UNO) |
4,056 B flash (12 %) |
src/ modular build (UNO) |
13,414 B flash (41 %) |
Compiler warnings (--warnings all) |
none from project code |
node tests/twin.test.js |
64 passed, 0 failed |
node tests/oauth.test.js |
24 passed, 0 failed (forgery attempts all rejected) |
node tests/users.test.js |
48 passed, 0 failed (access control, no real addresses) |
node tests/store.test.js |
44 passed, 0 failed (cloud store, outage, refusal, auth race, diagnostics) |
| Wokwi ESP32 circuit import | 11 parts, 27 connections, all 16 board pins resolve |
Smart-Dustbin-Embedded-System/
├── src/ Modular firmware (config, drivers, FSM, fusion)
├── arduino_code/ 5 ready-to-upload sketches, built up in stages
├── simulation/ Wokwi circuit + Tinkercad instructions
├── circuit_diagram/ Wiring SVG, pin tables, power budget
├── website/ Public site + admin dashboard
├── server/ Optional zero-dependency Node backend
├── tests/ 64 automated logic assertions
├── data/ Seed fleet, calibration table, captured output
├── docs/ 19 documentation sections
├── screenshots/ Proof images
└── reports/ Project report
Full explanation of every folder
| # | Document |
|---|---|
| 01 | Project explanation |
| 02 | Industry relevance |
| 03 | Tech stack options |
| 04 | Embedded concepts used |
| 05 | Hardware components |
| 06 | Project architecture |
| 07 | Implementation plan |
| 08 | Folder structure |
| 09 | Circuit diagram |
| 10 | Source code guide |
| 11 | Virtual simulation |
| 12 | Bin level calculation |
| 13 | Testing strategy |
| 14 | How to run |
| 15 | GitHub strategy |
| 16 | Website and dashboard |
| 17 | Proof building plan |
| 18 | Screenshot checklist |
| 19 | Interview preparation |
Stated deliberately - knowing the boundaries of your design is part of the engineering.
- The servo is open loop. There is no position feedback, so the firmware cannot detect a jammed lid. A limit switch or current sensing would fix it.
- Two sensors sample two points, not a volume. A narrow spike exactly between A and B is still invisible.
- No temperature compensation. The speed of sound shifts about 0.6 m/s per degree C - negligible indoors, a real error on a bin standing in the sun.
- Authentication is real, authorisation is not. Google sign-in genuinely
verifies an ID token's signature, but with no server and no protected API
the dashboard state still lives in
localStorageand is editable from DevTools. Real authorisation needs the server to verify the token on every request —server/server.jsshows that shape. - Wi-Fi is the wrong radio for street furniture. A real deployment would use LoRaWAN or NB-IoT with deep sleep.
- Deep sleep plus LoRaWAN/NB-IoT for year-long battery life
- Limit switch or current sensing for closed-loop lid control
- Temperature-compensated speed of sound (DHT22)
- Tamper and fire detection (accelerometer plus thermistor)
- Signed over-the-air firmware updates
- Waste segregation using an inductive or capacitive sensor
- Solar charging for outdoor units
- Reading a sensor by timing a pulse to microsecond accuracy
- Driving an actuator with PWM
- Designing a finite state machine, and why it beats a boolean
- Writing non-blocking firmware with a cooperative scheduler
- Fusing redundant sensors and degrading gracefully when one fails
- Calibrating against physical reality instead of trusting a datasheet
- Designing an alert policy people will not disable
- Testing embedded logic automatically, including fault injection
- Building a front end that turns telemetry into an operational decision
Sadhanala Nischay Prasad
MIT - see LICENSE.