#include <Servo.h>
#include "HX711.h"
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// Pin definitions
#define LDR_PIN 8 // LDR module digital output connected to pin 8
#define TRIG_PIN 9 // HC-SR04 Trigger pin
#define ECHO_PIN 10 // HC-SR04 Echo pin
#define LOADCELL_DOUT_PIN 3 // HX711 Data pin
#define LOADCELL_SCK_PIN 2 // HX711 Clock pin
#define BUZZER_PIN 4 // Pin for Active Buzzer
#define COIN_DISPENSER_PIN 11 // Pin for coin dispenser servo (servo pin 11)
#define GATE_SERVO_PIN 5 // Pin for gate servo (servo pin 5)
#define LASER_PIN 7 // Pin for Laser Diode (with external resistor)
#define LOAD_CELL_SERVO_PIN 6 // Pin for load cell servo (servo pin 6)
// Servo setup for load cell, coin dispenser, and gate
Servo loadCellServo; // Servo for load cell (plastic bottle dispenser)
Servo coinDispenser; // Servo for DIY coin dispenser
Servo gateServo; // Servo for gate
const int moveAngle = 20; // Angle to move coin dispenser and gate servo
// HX711 setup for load cell
HX711 scale;
float calibration_factor = -690; // Adjust this calibration factor based on your scale
// Variables for distance and LDR state
long duration;
int distance;
int ldrState; // Store the LDR state (HIGH or LOW)
float weight; // Variable to store weight reading
// Counter for plastic bottles
int plasticCounter = 0; // Count number of plastic bottles detected
// I2C LCD setup
LiquidCrystal_I2C lcd(0x27, 16, 2); // Change the address (0x27) if needed
void setup() {
Serial.begin(9600); // Start serial communication
// Initialize pin modes
pinMode(LDR_PIN, INPUT); // Set the LDR pin as input
pinMode(TRIG_PIN, OUTPUT); // Set the Trigger pin as output
pinMode(ECHO_PIN, INPUT); // Set the Echo pin as input
pinMode(BUZZER_PIN, OUTPUT); // Set the Buzzer pin as output
pinMode(LASER_PIN, OUTPUT); // Set the Laser pin as output
// Turn on the laser diode (ensure an external resistor is used)
digitalWrite(LASER_PIN, HIGH);
// Initialize HX711 scale
scale.begin(LOADCELL_DOUT_PIN, LOADCELL_SCK_PIN);
scale.set_scale(calibration_factor);
scale.tare(); // Reset the scale to 0
// Initialize servos
loadCellServo.attach(LOAD_CELL_SERVO_PIN); // Attach the load cell servo to pin 6
coinDispenser.attach(COIN_DISPENSER_PIN); // Attach the coin dispenser servo to pin 11
gateServo.attach(GATE_SERVO_PIN); // Attach the gate servo to pin 5
// Initialize servos to their neutral positions
loadCellServo.write(0); // Start at 0 degrees for load cell servo
coinDispenser.write(90); // Set coin dispenser to neutral position
gateServo.write(90); // Set gate servo to neutral position
// Initialize the I2C LCD
lcd.begin(16, 2); // Initialize the LCD with 16 columns and 2 rows
lcd.clear(); // Clear the LCD screen
lcd.setCursor(0, 0); // Set cursor to the top left of the screen
lcd.print("Plastic Counter"); // Display initial message
delay(2000); // Wait for 2 seconds
// Turn on the LCD backlight
lcd.backlight();
Serial.println("Plastic Detection & Weight Measurement System Started");
}
void loop() {
// Read the LDR module state (HIGH or LOW) from the digital output
ldrState = digitalRead(LDR_PIN);
// Measure distance using the ultrasonic sensor
digitalWrite(TRIG_PIN, LOW); // Ensure TRIG is low initially
delayMicroseconds(2);
digitalWrite(TRIG_PIN, HIGH); // Send trigger pulse
delayMicroseconds(10);
digitalWrite(TRIG_PIN, LOW); // End trigger pulse
duration = pulseIn(ECHO_PIN, HIGH); // Read the echo pulse duration
// Calculate distance in cm
distance = duration * 0.034 / 2;
// Read the weight from the HX711 scale
weight = scale.get_units(10); // Average over 10 readings for stability
// Display information on Serial Monitor
Serial.print("LDR State: ");
if (ldrState == LOW) {
Serial.print("Laser Detected ");
} else {
Serial.print("Laser Not Detected ");
}
// Display distance in cm
Serial.print("| Distance: ");
Serial.print(distance);
Serial.print(" cm | ");
// Display weight in grams
Serial.print("Weight: ");
Serial.print(weight);
Serial.println(" g");
// Logic to detect plastic, check weight (10 to 50 grams), and distance
if (ldrState == LOW && distance < 7 && weight >= 9 && weight <= 30) {
// All conditions are met for plastic detection
Serial.println("Plastic Detected");
plasticCounter++; // Increment the plastic bottle counter
// Move the gate servo backward to open the gate
// Rotate the load cell servo for bottle dispensing
loadCellServo.write(60); // Rotate to 180 degrees to dispense
delay(1000); // Wait for 1 second
gateServo.write(90 - (moveAngle -9)); // Move backward by moveAngle (e.g., 70 degrees)
delay(1000);
// Wait for the servo to move
loadCellServo.write(0); // Return to 0 degrees (original position)
delay(1000); // Wait for 1 second
// Move the gate servo forward to close the gate
gateServo.write(90 + (moveAngle -8)); // Move forward by moveAngle (e.g., 110 degrees)
delay(1000); // Wait for the servo to move back
gateServo.write(90); // Return to neutral position
delay(500); // Short delay
// Move coin dispenser when counter reaches 3
if (plasticCounter >= 3) {
// Display "Dispensing Coin" before moving the coin dispenser
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Dispensing Coin");
// Move the coin dispenser
coinDispenser.write(90 + moveAngle); // Move forward by moveAngle (e.g., 110 degrees)
delay(1000); // Wait for the servo to move
// Move the servo backward (counter-clockwise) by the same moveAngle
coinDispenser.write(90 - moveAngle); // Move back by moveAngle (e.g., 70 degrees)
delay(1000);
coinDispenser.write(90); // Return to neutral position
delay(1000);
plasticCounter = 0; // Reset the counter after releasing a coin
}
// Show on LCD that plastic was detected
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Valid");
lcd.setCursor(0, 1);
lcd.print("Plastic Bottle");
// Sound the buzzer once for valid plastic
tone(BUZZER_PIN, 1000, 500); // Buzzer sounds for 500ms at 1000Hz
delay(2000); // Display this for 2 seconds before resetting
}
else if (ldrState == HIGH && distance < 7 && weight >= 9 && weight <= 30) {
// Laser not detected, but distance and weight are valid
Serial.println("Not Plastic");
// Show on LCD that object is not plastic
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Invalid");
lcd.setCursor(0, 1);
lcd.print("Remove Object");
// Sound the buzzer repeatedly for invalid plastic
while (ldrState == HIGH && distance < 7 && weight >= 9 && weight <= 30) {
tone(BUZZER_PIN, 1000, 500); // Buzzer sounds for 500ms at 1000Hz
delay(500); // Wait for 500ms before sounding again
// Recheck sensor states
ldrState = digitalRead(LDR_PIN); // Recheck LDR state
digitalWrite(TRIG_PIN, LOW); // Trigger low
delayMicroseconds(2);
digitalWrite(TRIG_PIN, HIGH); // Send trigger pulse
delayMicroseconds(10);
digitalWrite(TRIG_PIN, LOW); // End trigger pulse
duration = pulseIn(ECHO_PIN, HIGH); // Read the echo pulse duration
distance = duration * 0.034 / 2; // Recalculate distance
weight = scale.get_units(10); // Recheck weight
}
delay(2000); // Display this for 2 seconds before resetting
}
else {
// No valid object detected
Serial.println("No Object Detected");
// Show on LCD the current counter and insert bottle message
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Counter: ");
lcd.print(plasticCounter); // Display the current plastic counter
lcd.setCursor(0, 1);
lcd.print("Insert Bottle");
// Turn off the buzzer if no object detected
noTone(BUZZER_PIN); // Stop buzzer sound
}
// Reset counter if it reaches 3
if (plasticCounter >= 3) {
plasticCounter = 0; // Reset the counter
}
delay(30); // Small delay for stability
}