Arduino UNO Smart Waste Sorting System Using Ultrasonic Sensor, Moisture Sensor, Servo, Stepper Motor and LCD
Arduino UNO Smart Waste Sorting System — Automatic Garbage Segregation Using Sensors
Build an automated garbage segregation system that classifies waste into
wet, dry, and metal categories using sensor-based detection and motorized mechanisms —
all controlled by an Arduino UNO. Ideal for smart city projects, STEM exhibitions,
and environmental engineering demos. Full code, wiring tables, and diagram.json included.
What This System Does
The Arduino UNO Smart Waste Sorting System is an automated garbage segregation machine that uses three sensors to classify waste into separate bins — completely hands-free. An HC-SR04 detects when waste is placed, a moisture sensor identifies wet waste, and an inductive proximity sensor catches metal objects. The stepper motor then rotates the bin platform to the correct compartment, and the servo motor opens the chute to drop waste in.
💧 Wet Waste
- Moisture sensor reads LOW (wet detected)
- Inductive sensor reads LOW (no metal)
- Stepper → 120° (wet bin)
- Servo sweeps 0° → 180°
📦 Dry Waste
- Moisture sensor reads HIGH (no moisture)
- Inductive sensor reads LOW (no metal)
- 3 consecutive detections confirm dry
- Stepper stays at 0° (dry bin)
Key Features
How the Waste Sorting Works
Object Detection
HC-SR04 ultrasonic sensor detects waste placed within 5cm of the input chute.
Waste Classification
Moisture sensor and inductive sensor read simultaneously to classify the waste type.
Automated Sorting
Stepper rotates the bin platform. Servo opens the chute. LCD updates the status.
Priority Logic
Metal detection takes priority — if the inductive sensor fires, the system immediately
processes metal waste regardless of the moisture reading. If no metal is found, the
moisture sensor determines wet vs dry. Dry waste requires 3 consecutive detections
(configurable via dryThreshold) to avoid false positives.
LCD Status Messages
| Condition | LCD Row 1 Message |
|---|---|
| No waste detected (>5cm) | "Put Waste" |
| Metal detected | "Metal Detected" |
| Wet waste (moisture LOW) | "Wet Object" |
| Dry waste (moisture HIGH × 3) | "Dry Object" |
Components Required
Libraries Required
| Library | Purpose | Install |
|---|---|---|
| Stepper.h | 28BYJ-48 stepper motor via ULN2003 | Built-in Arduino |
| Wire.h | I2C communication for LCD | Built-in Arduino |
| LiquidCrystal_I2C.h | I2C LCD display control | Library Manager |
| Servo.h | SG90 servo motor control | Built-in Arduino |
Complete Wiring Guide
HC-SR04 Ultrasonic Sensor
| HC-SR04 Pin | Arduino Pin | Wire |
|---|---|---|
| VCC | 5V | Red |
| GND | GND | Black |
| TRIG | Digital 3 | Yellow |
| ECHO | Digital 2 | Green |
Moisture / Rain Sensor
| Sensor Pin | Arduino Pin | Wire | Notes |
|---|---|---|---|
| VCC | Digital 6 (POWER_PIN) | Red | Software-controlled power — saves energy |
| GND | GND | Black | |
| DO | Digital 0 (DO_PIN) | Blue | LOW = wet, HIGH = dry |
Avoid pin 0 in production: Digital pin 0 is the hardware Serial RX pin. While it works in this sketch, it can conflict with serial uploading. In a real build, consider moving DO to pin 4 or 5 and adjusting the DO_PIN define.
Inductive Proximity Sensor
| Sensor Pin | Arduino Pin | Wire | Notes |
|---|---|---|---|
| VCC | 5V | Red | Some modules need 12V — check datasheet |
| GND | GND | Black | |
| OUT | Digital 7 | Orange | HIGH = metal detected |
SG90 Servo Motor
| Servo Wire | Arduino Pin | Color |
|---|---|---|
| Power (+) | 5V | Red |
| Ground (–) | GND | Black / Brown |
| Signal | Digital 13 | Orange / Yellow |
28BYJ-48 Stepper Motor (via ULN2003 Driver)
| ULN2003 Pin | Arduino Pin | Wire |
|---|---|---|
| IN1 | Digital 8 | Blue |
| IN2 | Digital 10 | Blue |
| IN3 | Digital 9 | Blue |
| IN4 | Digital 11 | Blue |
| VCC (+) | 5V | Red |
| GND (–) | GND | Black |
Stepper pin order matters: The Stepper(2048, 8, 10, 9, 11) constructor uses interleaved pin order (IN1, IN3, IN2, IN4) which produces the correct half-step sequence for the 28BYJ-48. Do not change this order.
16×2 I2C LCD Display
| LCD Pin | Arduino Pin | Wire |
|---|---|---|
| VCC | 5V | Red |
| GND | GND | Black |
| SDA | A4 | Green |
| SCL | A5 | Yellow |
Stepper Motor Bin Positions
The 28BYJ-48 makes 2048 steps per revolution. The three waste bins are positioned 120° apart around the rotating platform:
After each sorting cycle, the stepper always returns to the dry position (0°) to
reset for the next item. The position tracker (currentPosition)
ensures efficient movement by calculating only the delta steps needed.
Step-by-Step Setup
-
1
Set Up the Arduino UNO in Wokwi
Go to wokwi.com, click "New Project", and select "Arduino Uno". The Uno appears on the canvas — this is your main controller for all sensors and motors.
-
2
Add the HC-SR04 Ultrasonic Sensor
Click "+", search for "HC-SR04", and place it above the Uno. Connect TRIG to digital pin 3 and ECHO to digital pin 2. This sensor detects when waste is within 5cm of the input chute.
-
3
Add the Moisture / Rain Sensor
Search for "Rain Sensor" or "Moisture Sensor". Connect its VCC to digital pin 6 (software-controlled power) and DO to digital pin 0. LOW output = moisture detected (wet waste).
-
4
Add the Inductive Proximity Sensor
Search for "Inductive Sensor" and connect its output to digital pin 7. This sensor outputs HIGH when a metal object is detected — it takes priority in the sorting logic.
-
5
Add the SG90 Servo Motor
Search for "Servo" and connect the signal wire to digital pin 13. The servo controls the waste chute flap — sweeping from 0° to 180° releases waste into the selected bin.
-
6
Add the Stepper Motor with ULN2003 Driver
Search for "Stepper Motor (28BYJ-48)" which includes the ULN2003 board. Connect IN1→pin 8, IN2→pin 10, IN3→pin 9, IN4→pin 11. This motor rotates the 3-compartment bin platform.
✅In Wokwi, the 28BYJ-48 + ULN2003 is often a single combined component. If not, search for "ULN2003 Stepper Driver" and attach the motor to it.
-
7
Add the 16×2 I2C LCD
Search for "LCD 1602 I2C" and connect SDA to A4 and SCL to A5. The LCD address is
0x27— confirm this matches your physical module. -
8
Paste the diagram.json and Code, then Simulate
Copy the
diagram.jsonbelow into Wokwi's diagram tab, paste the Arduino code into the editor, and press ▶ Play. The serial monitor will show distance and sensor readings in real time.
Arduino Code — Complete Sketch
Copy and paste this into the Wokwi code editor or Arduino IDE. All logic is contained in a single sketch.
#include <Stepper.h> #include <Wire.h> #include <LiquidCrystal_I2C.h> #include <Servo.h> // ── Pin Definitions ─────────────────────────── #define POWER_PIN 6 // Software power for moisture sensor #define DO_PIN 0 // Moisture sensor digital output #define SERVO_PIN 13 // SG90 servo signal pin // ── Ultrasonic Sensor ───────────────────────── const int trigPin = 3; const int echoPin = 2; long duration; int distance; // ── Inductive Sensor ────────────────────────── const int InductiveSensor = 7; // ── Stepper Motor (28BYJ-48 via ULN2003) ───── int stepsPerRevolution = 2048; int rpm = 10; // Pin order: IN1, IN3, IN2, IN4 for correct sequence Stepper myStepper(stepsPerRevolution, 8, 10, 9, 11); // ── Servo Motor ─────────────────────────────── Servo myServo; // ── I2C LCD (address 0x27, 16×2) ───────────── LiquidCrystal_I2C lcd(0x27, 16, 2); // ── Dry Detection Threshold ─────────────────── int dryCounter = 0; const int dryThreshold = 3; // 3 consecutive reads = confirmed dry // ── Stepper Position Tracker (steps from 0°) ── int currentPosition = 0; const int dryPosition = 0; // 0° const int wetPosition = stepsPerRevolution / 3; // 120° const int metalPosition = stepsPerRevolution * 2 / 3; // 240° // ───────────────────────────────────────────── void setup() { myStepper.setSpeed(rpm); myServo.attach(SERVO_PIN); pinMode(InductiveSensor, INPUT); pinMode(trigPin, OUTPUT); pinMode(echoPin, INPUT); pinMode(POWER_PIN, OUTPUT); pinMode(DO_PIN, INPUT); lcd.init(); lcd.backlight(); Serial.begin(9600); } // ───────────────────────────────────────────── void loop() { getDistance(); int inductiveValue = digitalRead(InductiveSensor); // Metal detection takes PRIORITY if (inductiveValue == HIGH) { processMetal(); return; } // No object detected → idle state if (distance > 5) { lcd.setCursor(0, 0); lcd.print("Put Waste "); dryCounter = 0; returnStepperToDry(); } // Object detected within 5cm else { int rain_state = getRainState(); if (inductiveValue == LOW && rain_state == LOW) { processWet(); // Wet: no metal, moisture present } else if (inductiveValue == LOW && rain_state == HIGH) { dryCounter++; if (dryCounter >= dryThreshold) { processDry(); // Dry: confirmed after 3 readings } } } } // ── Ultrasonic distance measurement ────────── void getDistance() { digitalWrite(trigPin, LOW); delayMicroseconds(2); digitalWrite(trigPin, HIGH); delayMicroseconds(10); digitalWrite(trigPin, LOW); duration = pulseIn(echoPin, HIGH); distance = duration * 0.034 / 2; Serial.print("Distance: "); Serial.println(distance); } // ── Moisture sensor read (power-cycled) ─────── int getRainState() { digitalWrite(POWER_PIN, HIGH); delay(10); int rain_state = digitalRead(DO_PIN); digitalWrite(POWER_PIN, LOW); Serial.println(rain_state == HIGH ? "Dry" : "Wet"); return rain_state; } // ── Metal waste processing ──────────────────── void processMetal() { lcd.setCursor(0, 0); lcd.print("Metal Detected "); moveStepperTo(metalPosition); delay(1000); myServo.write(180); delay(500); myServo.write(0); delay(500); returnStepperToDry(); } // ── Wet waste processing ────────────────────── void processWet() { lcd.setCursor(0, 0); lcd.print("Wet Object "); moveStepperTo(wetPosition); delay(1000); myServo.write(180); delay(500); myServo.write(0); delay(500); returnStepperToDry(); } // ── Dry waste processing ────────────────────── void processDry() { lcd.setCursor(0, 0); lcd.print("Dry Object "); moveStepperTo(dryPosition); delay(1000); myServo.write(180); delay(500); myServo.write(0); delay(500); } // ── Stepper position control ────────────────── void moveStepperTo(int targetPosition) { int stepsToMove = targetPosition - currentPosition; myStepper.step(stepsToMove); currentPosition = targetPosition; } void returnStepperToDry() { if (currentPosition != dryPosition) { moveStepperTo(dryPosition); } }
Dry threshold: Change dryThreshold = 3 to 1 for faster response, or increase it to reduce false positives from borderline moisture readings.
IoT Upgrade Possibilities
This system is designed to be expandable. Add any of the following to transform it into a full Smart City Waste Monitoring System:
Comments
Post a Comment