Table of Contents

Smart Trash Bin Monitoring System

Emir Talha Fidan (32780) Ilker Bakikol (31706)

1. Introduction

By 32780 Every year, inefficient waste-collection leads to unnecessary pickups, added CO₂ emissions, and overflowing public bins. Our Smart Trash-Bin Fill-Level Monitoring System uses a VL53L0X Time-of-Flight sensor mounted inside a 41 × 35 × 60 cm³ bin to measure the fill height, displays the percentage full on an SH1106 OLED, and—when a user-configurable threshold is exceeded—sends alerts via a Telegram bot.

This document walks through each step—hardware assembly (breadboard layout), Arduino IDE firmware, Node-RED flow, Telegram-bot config, and ESP32 simulation—so you can reproduce and extend the system today, then evolve it for outdoor use tomorrow.


2. Materials & System Overview

By 32780

2.1. Hardware Components

Component Purpose
ESP32-S3-DevKitC-1 Main MCU, Wi-Fi, GPIOs
VL53L0X ToF sensor Measures distance from bin top to contents
SH1106 128×64 I²C OLED (U8g2 lib) Displays distance (cm) & fill (%)
LED (GPIO 2) Visual “almost full” warning
Powerbank (5 V USB) Supplies 5 V to ESP32 for portable operation
Wires, breadboard, connectors Prototyping and wiring


2.2. Software Components


3. Hardware Assembly

By 32780

3.1. Breadboard Layout


4. Arduino IDE Firmware

By 32780 Below is the main sketch. Please replace `YOUR_SSID`, `YOUR_PASS`, `NODE_RED_URL`, and `BOT_TOKEN` with your actual credentials.

#include <Wire.h>
#include <Adafruit_VL53L0X.h>
#include <U8g2lib.h>
#include <WiFi.h>
#include <HTTPClient.h>
#include <UniversalTelegramBot.h>
 
#define I2C_SDA 8
#define I2C_SCL 9
#define LED_PIN 2
 
#define BIN_HEIGHT_CM 60.0
#define DISTANCE_OFFSET_CM -3.0
 
// Wi-Fi
const char* ssid       = "YOUR_SSID";
const char* password   = "YOUR_PASS";
// Node-RED endpoint
const char* alert_url  = "http://YOUR_IP_ADDRESS/bin-alert";
 
// Telegram
const char* telegram_token = "BOT_TOKEN";
String chat_id = "CHAT_ID"; 
 
U8G2_SH1106_128X64_NONAME_F_HW_I2C display(U8G2_R0, U8X8_PIN_NONE, I2C_SCL, I2C_SDA);
Adafruit_VL53L0X lox = Adafruit_VL53L0X();
WiFiClientSecure secured_client;
UniversalTelegramBot bot(telegram_token, secured_client);
 
unsigned long lastAlertTime = 0, lastSignalTime = 0;
const unsigned long signalInterval = 30000;
float lastDistance = 0, lastPercentage = 0;
bool updatesEnabled = true;
 
void setup() {
  Serial.begin(115200);
  Wire.begin(I2C_SDA, I2C_SCL);
  // Initialize display
  display.begin();
  display.clearBuffer();
  display.setFont(u8g2_font_ncenB08_tr);
  display.drawStr(0,10,"Init Display");
  display.sendBuffer();
  // Initialize sensor
  if (!lox.begin()) while (1);
  pinMode(LED_PIN, OUTPUT);
  // Connect Wi-Fi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print('.');
  }
  Serial.println("\\nWiFi OK");
  secured_client.setInsecure();
}
 
void loop() {
  VL53L0X_RangingMeasurementData_t m;
  lox.rangingTest(&m, false);
  if (m.RangeStatus != 4) {
    float d = m.RangeMilliMeter/10.0 + DISTANCE_OFFSET_CM;
    float p = constrain(100.0 - (d/BIN_HEIGHT_CM)*100.0, 0.0, 100.0);
    lastDistance = d; lastPercentage = p;
    // Update OLED
    display.clearBuffer();
    display.setCursor(0,12);
    display.print("Dist: "); display.print(d,1); display.print("cm");
    display.setCursor(0,30);
    display.print("Fill: "); display.print((int)p); display.print("%");
    int w = map((int)p,0,100,0,120);
    display.drawFrame(0,45,120,10);
    display.drawBox(0,45,w,10);
    display.sendBuffer();
    // Alert on ≥80%
    if (p >= 80.0) {
      digitalWrite(LED_PIN, HIGH);
      if (millis() - lastAlertTime > 15000) {
        sendWarning(d, p);
        lastAlertTime = millis();
      }
    } else {
      digitalWrite(LED_PIN, LOW);
    }
  }
  // Periodic update
  if (millis() - lastSignalTime > signalInterval) {
    if (updatesEnabled) sendRegularUpdate(lastDistance, lastPercentage);
    lastSignalTime = millis();
  }
  // Telegram commands
  static unsigned long lastBot = 0;
  if (millis() - lastBot > 1000) {
    int n = bot.getUpdates(bot.last_message_received + 1);
    while (n) {
      handleNewMessages(n);
      n = bot.getUpdates(bot.last_message_received + 1);
    }
    lastBot = millis();
  }
  delay(500);
}
 
// ... (sendWarning, sendRegularUpdate, handleNewMessages functions)

Code Summary

1. Initialization (setup)

  1. Serial debug +
    Wire.begin()

    for I²C

  2. lox.begin()

    for ToF sensor and OLED splash

  3. Connect to Wi-Fi (SSID/password)
  4. Initialize HTTPClient & Telegram bot
  5. On failure (sensor or Wi-Fi), print/display error

2. Main Loop

  1. Ranging measurement via
    lox.rangingTest()
  2. If valid, calculate

`fill % = ((BIN_HEIGHT_CM − distance_cm) / BIN_HEIGHT_CM) × 100`

  1. Update OLED: distance, fill %, bar graph
  2. LED Alert: ON if ≥ 80 %, OFF if below (with hysteresis)
  3. HTTP POST to Node-RED every 30 s
  4. Telegram: one-time warning on threshold cross; optional periodic updates
  5. Handle Telegram commands (
    /start

    ,

    /status

    ,

    /stop

    , etc.)

  6. Delay to regulate loop frequency

5. Node-RED Flow

By 32780 Our Node-RED instance handles incoming HTTP POSTs at `/bin-alert` and:


6. Telegram Bot Configuration

By 32780

Commands:


7. Results

By 31706

{"bin":"Kitchen","fill":85,"status":"Nearly Full"}
  1. Regular status updates (e.g., every 30 s) are also sent.
  2. On sensor error, OLED shows “Sensor error” and that cycle’s data is skipped; an error flag can be forwarded.


8. Discussion & Lessons Learned

By 31706

* Limitations


9. Conclusion

By 31706

Deploying multiple units in smart buildings or campuses enables optimized waste collection scheduling, reduces overflow incidents, and contributes to smarter urban infrastructure by leveraging low-cost sensors and Wi-Fi connectivity. This project demonstrates a practical IoT solution for everyday problems, with clear pathways for scaling and enhancement.


10. References

By 31706