This page provides the complete Arduino code for the Eco-Genie material sorting system, including an in-depth breakdown of its functionality.
This section provides an in-depth understanding of the functionality of the Eco-Genie system:
getUltrasonicDistance() function converts the echo duration into a distance measurement. If an object is detected, the system initiates material classification.determineMaterial() function processes sensor readings:
actuateServo() function ensures smooth movement via slowMoveServo(), adding delays for controlled speed.moveStepper() function drives the motor for 244,000 steps at a speed defined by a 25-microsecond delay. The direction pin toggles based on material type to ensure proper bin alignment.setup(), serial communication, LCD, sensors, servo, and stepper motor pins are initialized. The LCD displays "System Ready," and the servo returns to its neutral position (90°) before entering the main loop.
#include "Wire.h"
#include "LiquidCrystal_I2C.h"
#include "Servo.h"
// Initialize the LCD with the I2C address 0x27 and dimensions 16x2
LiquidCrystal_I2C lcd(0x27, 16, 2);
// Pin assignments for sensors
const int trigPin = 26;
const int echoPin = 28;
const int capacitivePin = 24;
const int inductivePin = 22;
Servo tipperServo;
const int servoPin = 48;
// Stepper Motor Pins for CNC Shield
const int stepPinX = 2; // Step pin for the X-axis stepper motor
const int dirPinX = 5; // Direction pin for the X-axis stepper motor
// Variables to store sensor readings and counts
int capacitiveReadings = 0;
int inductiveReadings = 0;
// Detection thresholds
const int ultrasonicThreshold = 2; // Threshold in mm (7 cm)
const int detectionThreshold = 50; // Number of readings for material detection
const int materialDelay = 10000; // 10 seconds total delay for readings
const long stepsDistance = 244000; // Updated steps for halfway tipping action
int stepDelay = 25; // Speed set to 50 microseconds delay (faster motor speed)
// Variables for servo operation
const int neutralPosition = 90;
const int tipPosition = 0; // Tipping position is 0 degrees
// Function to read ultrasonic distance
long getUltrasonicDistance() {
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
long duration = pulseIn(echoPin, HIGH);
return duration * 0.034 / 2; // Convert duration to distance in cm
}
// Function to determine material based on sensor readings
String determineMaterial(int capacitiveCount, int inductiveCount) {
if (capacitiveCount > 25 && inductiveCount > 25) {
return "Aluminum Detected"; // Both sensors detect
} else if (capacitiveCount > 25 && inductiveCount <= 25) {
return "Glass Detected"; // Only capacitive detects
} else if (capacitiveCount <= 25 && inductiveCount <= 25) {
return "Plastic Detected"; // Neither sensor detects
}
return "No Material Detected";
}
// Function to move stepper motor
void moveStepper(long steps, bool direction) {
digitalWrite(dirPinX, direction); // Set motor direction
for (long i = 0; i < steps; i++) {
digitalWrite(stepPinX, HIGH);
delayMicroseconds(stepDelay);
digitalWrite(stepPinX, LOW);
delayMicroseconds(stepDelay);
}
}
// Function to move the servo slowly to a target position
void slowMoveServo(int targetAngle) {
int currentAngle = tipperServo.read(); // Get current position of the servo
if (currentAngle < targetAngle) {
for (int angle = currentAngle; angle <= targetAngle; angle++) {
tipperServo.write(angle);
delay(15); // Adjust delay for speed control
}
} else {
for (int angle = currentAngle; angle >= targetAngle; angle--) {
tipperServo.write(angle);
delay(15); // Adjust delay for speed control
}
}
}
// Servo function to tip the container and return to the original position
void actuateServo() {
// Move the servo slowly to the tipping position (0 degrees)
slowMoveServo(tipPosition);
delay(500); // Hold position for tipping
// Move the servo back to the neutral position (90 degrees)
slowMoveServo(neutralPosition);
}
// Setup function
void setup() {
Serial.begin(9600);
lcd.begin();
lcd.backlight();
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
pinMode(capacitivePin, INPUT);
pinMode(inductivePin, INPUT);
// Attach the servo
tipperServo.attach(servoPin);
tipperServo.write(neutralPosition); // Set servo to neutral position
// Set stepper motor pins
pinMode(stepPinX, OUTPUT);
pinMode(dirPinX, OUTPUT);
Serial.println("System Initialized");
lcd.clear();
lcd.print("System Ready");
delay(2000);
lcd.clear();
}
void loop() {
// Step 1: Check if an object is detected by the ultrasonic sensor
lcd.clear();
lcd.print("Waiting for Obj...");
long distance = getUltrasonicDistance();
if (distance > ultrasonicThreshold) {
delay(500);
return; // No object detected, continue looping
}
// Step 2: Object detected, start material detection process
lcd.clear();
lcd.print("Object Detected");
delay(1000);
int capacitiveCount = 0;
int inductiveCount = 0;
// Take multiple readings to determine material
for (int i = 0; i < detectionThreshold; i++) {
int capacitiveReading = digitalRead(capacitivePin);
int inductiveReading = digitalRead(inductivePin);
if (capacitiveReading == LOW) capacitiveCount++;
if (inductiveReading == LOW) inductiveCount++;
delay(materialDelay / detectionThreshold);
}
// Step 3: Determine material type
String material = determineMaterial(capacitiveCount, inductiveCount);
Serial.println(material);
lcd.clear();
lcd.print(material);
// Step 4: Actuate stepper motor and servo based on detected material
if (material == "Plastic Detected") {
moveStepper(stepsDistance, false);
actuateServo();
delay(1000);
moveStepper(stepsDistance, true);
} else if (material == "Aluminum Detected") {
moveStepper(stepsDistance, true);
actuateServo();
delay(1000);
moveStepper(stepsDistance, false);
} else if (material == "Glass Detected") {
actuateServo();
delay(1000);
}
// Step 5: Reset display and prepare for next detection
delay(5000);
lcd.clear();
lcd.print("Resetting...");
delay(2000);
lcd.clear();
}