Reverse Vending Machine
Plastic Bottle & Can Sorter
Automatically detect, classify and sort plastic bottles and aluminium cans using sensors, servo motors, load cell, GSM and WiFi — complete with reward tracking on an LCD display.
Project Overview & Components
This Reverse Vending Machine (RVM) project automatically identifies, segregates, and records plastic bottles and aluminium cans. It uses multiple sensors for detection and verification, servo motors for sorting, and dual wireless communication (GSM + WiFi) for cloud data reporting and reward tracking.
Components Used
Arduino UNO
Main microcontroller — runs detection, sorting and communication logic
HC-SR04 × 2
Ultrasonic sensors — object distance & insertion detection
HX711 + Load Cell
Precision weight measurement for item validation and reward calculation
Inductive Sensor
Detects metallic aluminium cans — ignores plastic
Photoelectric Sensor
Object presence detection — confirms item insertion
Servo Motors × 4
SG90/MG90S — control sorting gates for cans and bottles
SIM800/SIM900 GSM
SMS and mobile data transmission for reporting
ESP8266 WiFi
Cloud data upload — IoT integration and monitoring
16×2 LCD Display
User interface — item type, weight, points earned
Relay / Driver Circuits
Safe actuator control for motors and modules
Working Principle (6-Stage Flow)
Object Insertion Detection
The photoelectric sensor detects when an item enters the machine. The ultrasonic sensor (HC-SR04 #1) confirms the object's position and distance to ensure it's properly inserted.
Material Identification
The inductive proximity sensor checks for metal. If triggered → aluminium can. If no metal signal → system proceeds to weight check to confirm it's a plastic bottle.
Sorting Mechanism
The appropriate servo motor rotates to open the correct gate: metal cans go to the can compartment, plastic bottles go to the bottle compartment. HC-SR04 #2 verifies correct routing.
Weight Recording
The HX711 load cell measures the item's exact weight. This is stored in memory and used to calculate the reward points the user has earned for recycling.
Data Communication
Transaction data (item type, weight, timestamp, points) is transmitted via the GSM module as an SMS, and/or uploaded to a cloud server via the ESP8266 WiFi module.
User Interface
The 16×2 LCD displays the full transaction: "Insert Item" → item type (Can/Bottle) → weight → points earned → "Thank You!" message before resetting for the next cycle.
Key Features
Dual Detection
Inductive + weight sensors together ensure near-zero misclassification between metal cans and plastic bottles
Weight Validation
HX711 rejects items too light or heavy — preventing fraud and non-standard items from earning rewards
Dual Comms
GSM for offline environments + WiFi for IoT dashboards — works with or without internet connectivity
Reward-Ready
Built-in points calculation based on item type and weight — ready to integrate with loyalty/reward apps
Data Logging
Every transaction is timestamped and reported — ideal for fleet management of public recycling stations
Scalable
Modular code structure makes it easy to deploy multiple units and aggregate data across a smart city network
Pin Assignment & Wiring Guide
Sensors
| Component | Arduino Pin | Type |
|---|---|---|
| HC-SR04 #1 TRIG | Pin 5 | Digital OUTPUT |
| HC-SR04 #1 ECHO | Pin 6 | Digital INPUT |
| HC-SR04 #2 TRIG | Pin 7 | Digital OUTPUT |
| HC-SR04 #2 ECHO | Pin 8 | Digital INPUT |
| Inductive Sensor | Pin 2 | Digital INPUT |
| Photoelectric Sensor | Pin 16 | Digital INPUT |
Actuators & Displays
| Component | Arduino Pin | Type |
|---|---|---|
| Servo 1 | Pin 9 | PWM OUTPUT |
| Servo 2 | Pin 10 | PWM OUTPUT |
| Servo 3 | Pin 11 | PWM OUTPUT |
| Servo 4 | Pin 12 | PWM OUTPUT |
| HX711 DOUT | Pin 13 | Digital INPUT |
| HX711 SCK | Pin 14 | Digital OUTPUT |
| LCD RS | Pin 17 | Digital OUTPUT |
| LCD E | Pin 18 | Digital OUTPUT |
| LCD DB4–DB7 | Pins 19–22 | Digital OUTPUT |
Communication Modules
| Module | Arduino Pin | Connection |
|---|---|---|
| GSM TX | Pin 3 | SoftwareSerial TX |
| GSM RX | Pin 18 | SoftwareSerial RX |
| ESP8266 | Pins 0/1 or SoftSerial | UART TX/RX |
The SIM800/SIM900 GSM module requires a 4.0V – 4.2V power supply at up to 2A. Do not power it directly from the Arduino 5V pin. Use a dedicated Li-ion cell or a step-down regulator. The ESP8266 also requires 3.3V logic — use a level shifter when interfacing with the 5V Arduino UNO.
Wiring Overview
System block diagram: sensors on the left feed data to the Arduino UNO, which drives actuators and communication modules on the right.
Full Arduino Code
This sketch initialises all sensors, reads distance, weight and material type, then drives the correct servo gate and transmits transaction data. Paste this into the Arduino IDE and upload to your UNO.
Required libraries: Servo.h (built-in), HX711.h (install via Library Manager → search "HX711 by bogde"), LiquidCrystal.h (built-in).
/* * Arduino Sketch for Plastic Bottle and Can Reverse Vending Machine * Interfaces with multiple sensors and actuators to segregate * plastic bottles and cans, with GSM/WiFi data transmission. * * Components: * - 2× HC-SR04 Ultrasonic Sensors (distance / presence) * - HX711 + Load Cell (weight measurement) * - 4× Servo Motors SG90/MG90S (sorting gates) * - Inductive Sensor (metal detection) * - Photoelectric Sensor (object presence) * - SIM800/SIM900 GSM Module (SMS / data comms) * - 16×2 LCD Display (user interface) */ #include <Servo.h> #include <HX711.h> #include <LiquidCrystal.h> // ── Pin Definitions ─────────────────────────────────────────────── #define TRIG_PIN1 5 // HC-SR04 #1 Trigger #define ECHO_PIN1 6 // HC-SR04 #1 Echo #define TRIG_PIN2 7 // HC-SR04 #2 Trigger #define ECHO_PIN2 8 // HC-SR04 #2 Echo #define SERVO_PIN1 9 // Sorting gate servo 1 #define SERVO_PIN2 10 // Sorting gate servo 2 #define SERVO_PIN3 11 // Sorting gate servo 3 #define SERVO_PIN4 12 // Sorting gate servo 4 #define LOAD_CELL_DOUT_PIN 13 // HX711 data output #define LOAD_CELL_SCK_PIN 14 // HX711 clock #define INDUCTIVE_SENSOR_PIN 2 // Metal detection (interrupt-capable) #define PHOTOELECTRIC_SENSOR_PIN 16 // Object presence #define GSM_TX_PIN 3 // GSM module TX (SoftwareSerial) #define GSM_RX_PIN 18 // GSM module RX #define LCD_RS_PIN 17 #define LCD_E_PIN 18 #define LCD_DB4_PIN 19 #define LCD_DB5_PIN 20 #define LCD_DB6_PIN 21 #define LCD_DB7_PIN 22 // ── Object Declarations ──────────────────────────────────────────── Servo servo1, servo2, servo3, servo4; HX711 scale; LiquidCrystal lcd(LCD_RS_PIN, LCD_E_PIN, LCD_DB4_PIN, LCD_DB5_PIN, LCD_DB6_PIN, LCD_DB7_PIN); // ── Helper: read ultrasonic distance (cm) ───────────────────────── long getDistance(int trigPin, int echoPin) { digitalWrite(trigPin, LOW); delayMicroseconds(2); digitalWrite(trigPin, HIGH); delayMicroseconds(10); digitalWrite(trigPin, LOW); long duration = pulseIn(echoPin, HIGH); return (duration / 2) / 29.1; } void setup() { Serial.begin(9600); // Ultrasonic sensor pins pinMode(TRIG_PIN1, OUTPUT); pinMode(ECHO_PIN1, INPUT); pinMode(TRIG_PIN2, OUTPUT); pinMode(ECHO_PIN2, INPUT); // Servo motors servo1.attach(SERVO_PIN1); servo2.attach(SERVO_PIN2); servo3.attach(SERVO_PIN3); servo4.attach(SERVO_PIN4); // Centre all servo gates at startup servo1.write(0); servo2.write(0); servo3.write(0); servo4.write(0); // Load cell — calibrate with known weight before deployment scale.begin(LOAD_CELL_DOUT_PIN, LOAD_CELL_SCK_PIN); scale.set_scale(2280.0); // Adjust this calibration factor scale.tare(); // Zero the scale on startup // LCD welcome screen lcd.begin(16, 2); lcd.print("RVM System"); lcd.setCursor(0, 1); lcd.print("Insert Item..."); // Detection sensors pinMode(INDUCTIVE_SENSOR_PIN, INPUT); pinMode(PHOTOELECTRIC_SENSOR_PIN, INPUT); } void loop() { // ── Step 1: Read all sensors ────────────────────────────────────── long distance1 = getDistance(TRIG_PIN1, ECHO_PIN1); long distance2 = getDistance(TRIG_PIN2, ECHO_PIN2); float weight = scale.get_units(10); // Avg of 10 readings int inductiveValue = digitalRead(INDUCTIVE_SENSOR_PIN); int photoValue = digitalRead(PHOTOELECTRIC_SENSOR_PIN); // ── Step 2: Only process if object is detected ──────────────────── if (photoValue == HIGH && distance1 < 20) { lcd.clear(); // ── Step 3: Classify material ───────────────────────────────── if (inductiveValue == HIGH) { // Metal detected → Aluminium can servo1.write(90); // Open can gate lcd.print("Item: CAN"); lcd.setCursor(0, 1); lcd.print("Wt:"); lcd.print(weight, 1); lcd.print("g"); delay(1500); servo1.write(0); } else if (weight > 10 && weight < 600) { // No metal + valid weight → Plastic bottle servo2.write(90); // Open bottle gate lcd.print("Item: BOTTLE"); lcd.setCursor(0, 1); lcd.print("Wt:"); lcd.print(weight, 1); lcd.print("g"); delay(1500); servo2.write(0); } else { // Unknown / rejected item lcd.print("Unknown Item"); lcd.setCursor(0, 1); lcd.print("Not accepted"); } // ── Step 4: Calculate and display reward points ─────────────── int points = (inductiveValue == HIGH) ? (int)(weight * 0.02) // cans earn 0.02 pts/g : (int)(weight * 0.01); // bottles earn 0.01 pts/g delay(1000); lcd.clear(); lcd.print("Points: +"); lcd.print(points); lcd.setCursor(0, 1); lcd.print("Thank You!"); // ── Step 5: Debug data to Serial Monitor ───────────────────── Serial.print("Dist1:"); Serial.print(distance1); Serial.print("cm | "); Serial.print("Dist2:"); Serial.print(distance2); Serial.print("cm | "); Serial.print("Weight:"); Serial.print(weight); Serial.print("g | "); Serial.print("Metal:"); Serial.println(inductiveValue ? "YES" : "NO"); delay(2000); // ── Step 6: Reset LCD for next item ────────────────────────── lcd.clear(); lcd.print("RVM System"); lcd.setCursor(0, 1); lcd.print("Insert Item..."); } delay(200); // Short polling interval }
Step-by-Step Build Instructions
Install Libraries
Open Arduino IDE → Sketch → Include Library → Manage Libraries. Search for and install "HX711 by bogde". Servo.h and LiquidCrystal.h are included by default.
Wire the Ultrasonic Sensors
Connect HC-SR04 #1: TRIG→Pin 5, ECHO→Pin 6. HC-SR04 #2: TRIG→Pin 7, ECHO→Pin 8. Power both from Arduino 5V and GND.
Wire the Load Cell & HX711
Connect HX711: DOUT→Pin 13, SCK→Pin 14, VCC→5V, GND→GND. Mount the load cell inside the insertion chute platform so items rest on it before sorting.
Wire Detection Sensors
Inductive sensor OUT→Pin 2, Photoelectric sensor OUT→Pin 16. Mount the inductive sensor in the detection zone wall. Mount photoelectric across the insertion chute.
Wire Servo Motors
Servo 1 signal→Pin 9, Servo 2→Pin 10, Servo 3→Pin 11, Servo 4→Pin 12. Power servos from an external 5V supply (not Arduino) if using more than 2 simultaneously.
Wire the LCD Display
RS→Pin 17, E→Pin 18, DB4→Pin 19, DB5→Pin 20, DB6→Pin 21, DB7→Pin 22. Connect a 10kΩ potentiometer between VCC, Pin 3 (VO contrast), and GND.
Connect GSM Module
Use a separate 4.2V / 2A power supply for the SIM800/SIM900. Connect GSM RX→Pin 3 and GSM TX→Pin 18 (via voltage divider or level shifter).
Upload & Calibrate
Upload the sketch. Open Serial Monitor at 9600 baud. Place a known weight (e.g. 200g) on the load cell and adjust the set_scale() value until the reading matches. See calibration notes below.
Test with Items
Insert a plastic bottle → verify LCD shows "Item: BOTTLE" and servo 2 activates. Insert an aluminium can → verify "Item: CAN" and servo 1 activates. Check Serial Monitor for logged data.
Load Cell Calibration
The HX711 raw reading must be scaled to grams. The set_scale() value depends on your specific load cell's rated capacity and sensitivity.
Quick calibration: Comment out scale.set_scale() and call scale.get_units(10) with a known weight on the cell. Divide the raw output by your known weight in grams — that's your scale factor. Enter it in set_scale(factor).
| Load Cell Capacity | Typical Scale Factor | Use Case |
|---|---|---|
| 1 kg | ~2280 | Small bottles (≤500ml) |
| 5 kg | ~400–800 | Standard 1.5L bottles & cans |
| 10 kg | ~200–400 | Large / commercial use |
Always call scale.tare() in setup() to zero the scale before each session. Make sure no weight is on the load cell when the Arduino powers on.
Comments
Post a Comment