Community project

Three-Way Smart Waste Sorter

Arduino
Photo of Three-Way Smart Waste Sorter
Generated with AI

Mamas Ferdi

Published October 26, 2026

This smart waste sorter automatically separates trash into three categories—toxic, organic, and inorganic—using gesture recognition and material detection. The system uses ultrasonic sensors to measure fill levels in each bin, an IR obstacle sensor to detect when compartments are full, and a moisture sensor to identify wet waste that shouldn't go in certain containers. Three servo-controlled lids open automatically when waste is detected, and LEDs indicate the status of each bin.

Builders will receive a complete wiring diagram showing how to connect the HC-SR04 ultrasonic sensors, IR sensors, SG90 servos, and moisture sensor to an Arduino Uno, along with a parts list, pre-written firmware, and step-by-step assembly instructions. The guide covers mounting the three servos on the bin lids, positioning the sensors, calibrating detection thresholds, and testing the sorting logic.

Wiring diagram

Wiring diagram for Three-Way Smart Waste Sorter

Gather all the parts

QtyComponent
1

HC-SR04

HC-SR04 ultrasonic distance sensor module with separate 40 kHz transmitter and receiver transducers, measuring 2 to 400 cm. A 10 us pulse on TRIG starts a measurement and ECHO stays high for the echo's round-trip time. This HC-SR04+ board runs from 3.3 V or 5 V.

1

HC-SR04

HC-SR04 ultrasonic distance sensor module with separate 40 kHz transmitter and receiver transducers, measuring 2 to 400 cm. A 10 us pulse on TRIG starts a measurement and ECHO stays high for the echo's round-trip time. This HC-SR04+ board runs from 3.3 V or 5 V.

1

HC-SR04

HC-SR04 ultrasonic distance sensor module with separate 40 kHz transmitter and receiver transducers, measuring 2 to 400 cm. A 10 us pulse on TRIG starts a measurement and ECHO stays high for the echo's round-trip time. This HC-SR04+ board runs from 3.3 V or 5 V.

1

HC-SR04

HC-SR04 ultrasonic distance sensor module with separate 40 kHz transmitter and receiver transducers, measuring 2 to 400 cm. A 10 us pulse on TRIG starts a measurement and ECHO stays high for the echo's round-trip time. This HC-SR04+ board runs from 3.3 V or 5 V.

1

IR obstacle sensor module

Modul inframerah yang memberi sinyal digital saat sampah mendekati posisi batas penuh.

1

IR obstacle sensor module

Modul inframerah yang memberi sinyal digital saat sampah mendekati posisi batas penuh.

1

IR obstacle sensor module

Modul inframerah yang memberi sinyal digital saat sampah mendekati posisi batas penuh.

1

SG90 Servo

Micro servo motor (SG90)

1

SG90 Servo

Micro servo motor (SG90)

1

SG90 Servo

Micro servo motor (SG90)

1

LED

Merah

Standard 3mm/5mm through-hole LED. A current-limiting series resistor is added automatically.

1

LED

Kuning

Standard 3mm/5mm through-hole LED. A current-limiting series resistor is added automatically.

1

LED

Hijau

Standard 3mm/5mm through-hole LED. A current-limiting series resistor is added automatically.

1

YL-83 moisture sensor module

Modul sensor kelembapan yang memberi nilai analog saat permukaannya basah atau lembap.

1

USB-C 5V Adapter

USB-C wall adapter delivering regulated 5 V to the board's USB or VBUS rail. Default wired power source for desktop / stationary projects.

1

Resistor

220 Ω

Through-hole resistor (current-limiting in series with an LED)

1

Resistor

220 Ω

Through-hole resistor (current-limiting in series with an LED)

1

Resistor

220 Ω

Through-hole resistor (current-limiting in series with an LED)

Assemble it in 6 steps

1. Pasang tiga servo pada penutup

Pasang servo_toxic pada wadah toxic, servo_anorganic pada wadah anorganik, dan servo_organic pada wadah organik. Sebelum memasang lengan servo, posisikan setiap servo pada sudut tertutup agar sudut 0 menutup dan 90 membuka.

  • Jangan memaksa lengan servo dengan tangan saat servo mendapat daya karena roda giginya dapat rusak.

2. Pasang sensor tinggi sampah

Pasang tiga HC-SR04 di bagian atas wadah dengan kedua lingkarannya menghadap ke bawah. Pasang setiap sensor IR menghadap tumpukan sampah sekitar 4–5 cm dari batas penuh, lalu putar sekrup kecilnya sampai dapat mendeteksi sampah.

  • Jangan menutup dua lubang bundar HC-SR04 karena sensor tidak dapat mengukur jarak.

3. Pasang sensor pemilah di lubang masuk

Pasang moisture_yl83 pada jalur masuk agar bagian probe menyentuh sampah yang lewat, dan pasang ultrasonic_gesture menghadap pengguna di depan lubang masuk. Gerakan tangan pada jarak 8 cm dipakai untuk memilih wadah.

  • Jangan merendam papan YL-83; hanya bagian probe yang boleh terkena sampah lembap.

4. Hubungkan sensor ke Arduino Uno

Hubungkan seluruh VCC sensor ke 5V (power) dan seluruh GND ke GND (ground). Hubungkan HC-SR04 toxic: TRIG ke D2 dan ECHO ke D6 (signal); anorganik: TRIG ke D3 dan ECHO ke D7 (signal); organik: TRIG ke D4 dan ECHO ke D8 (signal); sensor gerakan: TRIG ke D5 dan ECHO ke D9 (signal). Hubungkan OUT IR toxic ke D10, anorganik ke D11, organik ke D12 (signal), serta AO YL-83 ke A0 (signal).

5. Hubungkan servo dan LED

Hubungkan kabel sinyal servo toxic ke D13, servo anorganik ke A1, dan servo organik ke A2 (signal). Hubungkan kabel merah servo ke 5V dari supply_5v (power), serta kabel cokelat atau hitam ke GND (ground). Hubungkan A3 ke resistor 220 Ω lalu ke kaki panjang LED merah, A4 ke resistor 220 Ω lalu ke kaki panjang LED kuning, dan A5 ke resistor 220 Ω lalu ke kaki panjang LED hijau (signal). Kaki pendek setiap LED menuju GND (ground).

  • Jangan mengambil daya ketiga servo dari pin 5V Arduino yang berasal dari USB; gunakan supply_5v 5 V minimal 3 A.
  • Sambungkan GND supply_5v ke GND Arduino — tanpa ground bersama servo dapat bergerak tidak menentu.

6. Nyalakan dan atur batas

Hubungkan Arduino Uno ke USB untuk pemrograman. Hubungkan supply_5v ke servo dan sensor, pastikan ground supply_5v serta ground Arduino tersambung. Atur sekrup ketiga sensor IR saat tumpukan sampah berada sekitar 4–5 cm dari sensornya.

  • LED merah, kuning, atau hijau menyala hanya saat penutup wadahnya terbuka.

Review all connections

1. Connections between "supply_5v" and "Arduino"

Functionsupply_5vArduino
power+5V → 5 V power supply output5V
groundGND → shared groundGND

2. Connections between "ultrasonic_toxic" and "Arduino"

Functionultrasonic_toxicArduino
powerVCC → power5V
groundGND → groundGND
digitalTRIG → distance triggerGPIO 2
digitalECHO → distance echoGPIO 6

3. Connections between "ultrasonic_anorganic" and "Arduino"

Functionultrasonic_anorganicArduino
powerVCC → power5V
groundGND → groundGND
digitalTRIG → distance triggerGPIO 3
digitalECHO → distance echoGPIO 7

4. Connections between "ultrasonic_organic" and "Arduino"

Functionultrasonic_organicArduino
powerVCC → power5V
groundGND → groundGND
digitalTRIG → distance triggerGPIO 4
digitalECHO → distance echoGPIO 8

5. Connections between "ultrasonic_gesture" and "Arduino"

Functionultrasonic_gestureArduino
powerVCC → power5V
groundGND → groundGND
digitalTRIG → hand-motion triggerGPIO 5
digitalECHO → hand-motion echoGPIO 9

6. Connections between "ir_toxic" and "Arduino"

Functionir_toxicArduino
powerVCC → power5V
groundGND → groundGND
digitalOUT → full-bin signalGPIO 10

7. Connections between "ir_anorganic" and "Arduino"

Functionir_anorganicArduino
powerVCC → power5V
groundGND → groundGND
digitalOUT → full-bin signalGPIO 11

8. Connections between "ir_organic" and "Arduino"

Functionir_organicArduino
powerVCC → power5V
groundGND → groundGND
digitalOUT → full-bin signalGPIO 12

9. Connections between "moisture_yl83" and "Arduino"

Functionmoisture_yl83Arduino
powerVCC → power5V
groundGND → groundGND
analogAO → moisture readingGPIO 14

10. Connections between "servo_toxic" and "Arduino"

Functionservo_toxicArduino
powerVCC → servo power5V
groundGND → shared groundGND
pwmSIGNAL → toxic lid controlGPIO 13

11. Connections between "servo_anorganic" and "Arduino"

Functionservo_anorganicArduino
powerVCC → servo power5V
groundGND → shared groundGND
pwmSIGNAL → anorganic lid controlGPIO 15

12. Connections between "servo_organic" and "Arduino"

Functionservo_organicArduino
powerVCC → servo power5V
groundGND → shared groundGND
pwmSIGNAL → organic lid controlGPIO 16

13. Connections between "led_res_toxic" and "Arduino"

Functionled_res_toxicArduino
digitalP1 → red LED controlGPIO 17
digitalP2 → LED ANODEEXT

14. Connections between "led_toxic" and "Arduino"

Functionled_toxicArduino
groundGND → groundGND

15. Connections between "led_res_anorganic" and "Arduino"

Functionled_res_anorganicArduino
digitalP1 → yellow LED controlGPIO 18
digitalP2 → LED ANODEEXT

16. Connections between "led_anorganic" and "Arduino"

Functionled_anorganicArduino
groundGND → groundGND

17. Connections between "led_res_organic" and "Arduino"

Functionled_res_organicArduino
digitalP1 → green LED controlGPIO 19
digitalP2 → LED ANODEEXT

18. Connections between "led_organic" and "Arduino"

Functionled_organicArduino
groundGND → groundGND

Deploy the firmware

#include <Arduino.h>
#include <Servo.h>

#define TOXIC_TRIG_PIN 2
#define TOXIC_ECHO_PIN 6
#define ANORGANIC_TRIG_PIN 3
#define ANORGANIC_ECHO_PIN 7
#define ORGANIC_TRIG_PIN 4
#define ORGANIC_ECHO_PIN 8
#define GESTURE_TRIG_PIN 5
#define GESTURE_ECHO_PIN 9
#define TOXIC_FULL_IR_PIN 10
#define ANORGANIC_FULL_IR_PIN 11
#define ORGANIC_FULL_IR_PIN 12
#define MOISTURE_PIN A0
#define TOXIC_SERVO_PIN 13
#define ANORGANIC_SERVO_PIN A1
#define ORGANIC_SERVO_PIN A2
#define TOXIC_LED_PIN A3
#define ANORGANIC_LED_PIN A4
#define ORGANIC_LED_PIN A5

const int FULL_DISTANCE_CM = 5;
const int GESTURE_DISTANCE_CM = 8;
const int MOISTURE_WET_THRESHOLD = 450;
const unsigned long GESTURE_WINDOW_MS = 500;
const unsigned long LID_OPEN_MS = 1500;

Servo toxicServo, anorganicServo, organicServo;
int toxicDistance = 400, anorganicDistance = 400, organicDistance = 400;
bool gesturePresentLast = false;
unsigned long firstGestureAt = 0, nextBinReadAt = 0;
uint8_t gestureCount = 0;

int readDistanceCm(uint8_t trig, uint8_t echo, int maximum) {
  digitalWrite(trig, LOW); delayMicroseconds(3);
  digitalWrite(trig, HIGH); delayMicroseconds(10); digitalWrite(trig, LOW);
  unsigned long duration = pulseIn(echo, HIGH, (unsigned long)maximum * 58UL + 2000UL);
  return duration ? (int)(duration / 58UL) : maximum + 1;
}

bool binIsFull(int distance, uint8_t irPin) { return distance <= FULL_DISTANCE_CM || digitalRead(irPin) == LOW; }
bool materialIsWet() { return analogRead(MOISTURE_PIN) < MOISTURE_WET_THRESHOLD; }

void openLid(Servo &servo, uint8_t ledPin, bool full, const char *name) {
  if (full) { Serial.print(name); Serial.println(" bin is full; lid stays closed."); return; }
  digitalWrite(ledPin, HIGH); servo.write(90); Serial.print("Opening "); Serial.println(name);
  delay(LID_OPEN_MS); servo.write(0); digitalWrite(ledPin, LOW);
}

void updateBinLevels() {
  toxicDistance = readDistanceCm(TOXIC_TRIG_PIN, TOXIC_ECHO_PIN, 30); delay(25);
  anorganicDistance = readDistanceCm(ANORGANIC_TRIG_PIN, ANORGANIC_ECHO_PIN, 30); delay(25);
  organicDistance = readDistanceCm(ORGANIC_TRIG_PIN, ORGANIC_ECHO_PIN, 30);
}

void setup() {
  Serial.begin(115200);
  const uint8_t trigPins[] = {TOXIC_TRIG_PIN, ANORGANIC_TRIG_PIN, ORGANIC_TRIG_PIN, GESTURE_TRIG_PIN};
  const uint8_t echoPins[] = {TOXIC_ECHO_PIN, ANORGANIC_ECHO_PIN, ORGANIC_ECHO_PIN, GESTURE_ECHO_PIN};
  for (uint8_t p : trigPins) pinMode(p, OUTPUT);
  for (uint8_t p : echoPins) pinMode(p, INPUT);
  pinMode(TOXIC_FULL_IR_PIN, INPUT); pinMode(ANORGANIC_FULL_IR_PIN, INPUT); pinMode(ORGANIC_FULL_IR_PIN, INPUT);
  pinMode(TOXIC_LED_PIN, OUTPUT); pinMode(ANORGANIC_LED_PIN, OUTPUT); pinMode(ORGANIC_LED_PIN, OUTPUT);
  digitalWrite(TOXIC_LED_PIN, LOW); digitalWrite(ANORGANIC_LED_PIN, LOW); digitalWrite(ORGANIC_LED_PIN, LOW);
  toxicServo.attach(TOXIC_SERVO_PIN); anorganicServo.attach(ANORGANIC_SERVO_PIN); organicServo.attach(ORGANIC_SERVO_PIN);
  toxicServo.write(0); anorganicServo.write(0); organicServo.write(0);
  updateBinLevels(); nextBinReadAt = millis() + 400; Serial.println("Smart trash sorter ready.");
}

void loop() {
  unsigned long now = millis();
  if (now >= nextBinReadAt) { updateBinLevels(); nextBinReadAt = millis() + 400; }
  if (materialIsWet()) {
    openLid(organicServo, ORGANIC_LED_PIN, binIsFull(organicDistance, ORGANIC_FULL_IR_PIN), "organic");
    gestureCount = 0; firstGestureAt = 0; delay(100); return;
  }
  int gestureDistance = readDistanceCm(GESTURE_TRIG_PIN, GESTURE_ECHO_PIN, 12);
  bool gesturePresent = gestureDistance <= GESTURE_DISTANCE_CM;
  if (gesturePresent && !gesturePresentLast) {
    if (gestureCount == 0 || now - firstGestureAt > GESTURE_WINDOW_MS) { gestureCount = 1; firstGestureAt = now; }
    else { gestureCount++; }
  }
  gesturePresentLast = gesturePresent;
  if (gestureCount >= 2 && now - firstGestureAt <= GESTURE_WINDOW_MS) {
    openLid(toxicServo, TOXIC_LED_PIN, binIsFull(toxicDistance, TOXIC_FULL_IR_PIN), "toxic"); gestureCount = 0; firstGestureAt = 0;
  } else if (gestureCount == 1 && now - firstGestureAt > GESTURE_WINDOW_MS) {
    openLid(anorganicServo, ANORGANIC_LED_PIN, binIsFull(anorganicDistance, ANORGANIC_FULL_IR_PIN), "anorganic"); gestureCount = 0; firstGestureAt = 0;
  }
  delay(20);
}

Download project files

Remix this project

Make it yours in one click

Open a full copy of this project in your own Schematik workspace — diagram, code, parts, and assembly steps included. Swap the sensor, add features, or redesign the whole thing with AI. The author's original stays untouched.

Open in Schematik