#include <ESP32Servo.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
// ===== PINS =====
#define IR1 13
#define IR2 12
#define METAL 2
#define START_BTN 18
#define END_BTN 19
#define SERVO_PIN 4
#define WEIGHT_PIN 34
#define LEVEL_PLASTIC 35
#define LEVEL_CANS 32
// LEDs Plastic
#define GREEN_P 25
#define ORANGE_P 26
#define RED_P 27
// LEDs Cans
#define GREEN_C 14
#define ORANGE_C 23
#define RED_C 15
#define BUZZER 33
#define SERVO_UNKNOWN 5
// ===== OBJECTS =====
Servo servo;
Servo servoUnknown;
LiquidCrystal_I2C lcd(0x27, 16, 2);
Adafruit_SSD1306 oled(128, 64, &Wire, -1);
// ===== VARIABLES =====
int points = 0;
int bigBottle = 0;
int smallBottle = 0;
int cans = 0;
bool active = false;
bool objectDetected = false; // 🔒 منع التكرار
float totalWeightPlastic = 0;
float totalWeightCans = 0;
float latitude = 36.1911;
float longitude = 5.4137;
unsigned long lastSend = 0;
const int interval = 5000; // كل 5 ثواني
// ===== SETUP =====
void setup() {
Serial.begin(115200);
pinMode(IR1, INPUT_PULLUP);
pinMode(IR2, INPUT_PULLUP);
pinMode(METAL, INPUT_PULLUP);
pinMode(START_BTN, INPUT_PULLUP);
pinMode(END_BTN, INPUT_PULLUP);
pinMode(GREEN_P, OUTPUT);
pinMode(ORANGE_P, OUTPUT);
pinMode(RED_P, OUTPUT);
pinMode(GREEN_C, OUTPUT);
pinMode(ORANGE_C, OUTPUT);
pinMode(RED_C, OUTPUT);
pinMode(BUZZER, OUTPUT);
servo.setPeriodHertz(50);
servo.attach(SERVO_PIN, 500, 2400);
servoUnknown.setPeriodHertz(50);
servoUnknown.attach(SERVO_UNKNOWN, 500, 2400);
// وضعه في الوضع العادي
servoUnknown.write(90);
lcd.init();
lcd.backlight();
oled.begin(SSD1306_SWITCHCAPVCC, 0x3C);
oled.clearDisplay();
lcd.setCursor(0,0);
lcd.print("System Ready");
oled.setTextSize(1);
oled.setTextColor(WHITE);
oled.setCursor(0,0);
oled.print("Press START");
oled.display();
}
// ===== LOOP =====
void loop() {
// ===== START =====
if (digitalRead(START_BTN) == LOW && !active) {
active = true;
// 🔥 تصفير القيم
points = 0;
bigBottle = 0;
smallBottle = 0;
cans = 0;
totalWeightPlastic = 0;
totalWeightCans = 0;
lcd.clear();
lcd.setCursor(0,0);
lcd.print("New Session");
oled.clearDisplay();
oled.setCursor(0,0);
oled.print("STARTED");
oled.display();
delay(500);
}
// ===== END =====
if (digitalRead(END_BTN) == LOW && active) {
active = false;
Serial.println("===== SESSION DATA =====");
Serial.print("Plastic Weight: ");
Serial.println(totalWeightPlastic);
Serial.print("Cans Weight: ");
Serial.println(totalWeightCans);
// ===== عرض الملخص =====
oled.clearDisplay();
oled.setCursor(0,0);
oled.print("SESSION END");
oled.setCursor(0,10);
oled.print("Pts: ");
oled.print(points);
oled.setCursor(0,20);
oled.print("Big: ");
oled.print(bigBottle);
oled.setCursor(0,30);
oled.print("Small: ");
oled.print(smallBottle);
oled.setCursor(0,40);
oled.print("Cans: ");
oled.print(cans);
oled.display();
// عرض نفس المعلومات في LCD
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Pts:");
lcd.print(points);
lcd.setCursor(0,1);
lcd.print("C:");
lcd.print(cans);
lcd.print(" BB:");
lcd.print(bigBottle);
lcd.print(" SB:");
lcd.print(smallBottle);
delay(4000); // عرض 4 ثواني
}
// ===== إرسال الموقع كل 5 ثواني =====
if (millis() - lastSend > interval) {
lastSend = millis();
Serial.println("----- LOCATION -----");
Serial.print("Lat: ");
Serial.println(latitude);
Serial.print("Lng: ");
Serial.println(longitude);
}
// ===== LEVEL PLASTIC =====
int rawP = analogRead(LEVEL_PLASTIC);
int levelP = map(rawP, 0, 4095, 0, 100);
// ===== LEVEL CANS =====
int rawC = analogRead(LEVEL_CANS);
int levelC = map(rawC, 0, 4095, 0, 100);
// ===== LEDs PLASTIC =====
digitalWrite(GREEN_P, LOW);
digitalWrite(ORANGE_P, LOW);
digitalWrite(RED_P, LOW);
if (levelP < 65) digitalWrite(GREEN_P, HIGH);
else if (levelP < 85) digitalWrite(ORANGE_P, HIGH);
else {
digitalWrite(RED_P, HIGH);
delay(300);
digitalWrite(RED_P, LOW);
delay(300);
}
// ===== LEDs CANS =====
digitalWrite(GREEN_C, LOW);
digitalWrite(ORANGE_C, LOW);
digitalWrite(RED_C, LOW);
if (levelC < 65) digitalWrite(GREEN_C, HIGH);
else if (levelC < 85) digitalWrite(ORANGE_C, HIGH);
else {
digitalWrite(RED_C, HIGH);
delay(300);
digitalWrite(RED_C, LOW);
delay(300);
}
// ===== BUZZER =====
if (levelP >= 95 || levelC >= 95) {
digitalWrite(BUZZER, HIGH);
delay(300);
digitalWrite(BUZZER, LOW);
delay(300);
} else {
digitalWrite(BUZZER, LOW);
}
if (!active) return;
// ===== قراءة الوزن =====
int raw = analogRead(WEIGHT_PIN);
float weight = (raw / 4095.0) * 100.0;
bool ir1 = digitalRead(IR1) == LOW;
bool ir2 = digitalRead(IR2) == LOW;
bool metal = digitalRead(METAL) == LOW;
oled.clearDisplay();
oled.setCursor(0,0);
oled.print("Detecting...");
oled.display();
// ===== منع التكرار =====
// إذا لا يوجد شيء → إعادة فتح النظام
if (weight < 5 && !ir1 && !ir2 && !metal) {
objectDetected = false;
return;
}
// إذا تم حساب العنصر مسبقاً → لا تعيد الحساب
if (objectDetected) return;
// 🥫 CAN
if (metal && weight > 10 && weight < 60) {
oled.clearDisplay();
oled.setCursor(0,0);
oled.print("CAN detected");
oled.display();
servo.write(0);
cans++;
points += 2;
totalWeightCans += weight;
objectDetected = true;
delay(1500);
}
// 🧴 BIG
else if (ir2 && weight > 50) {
oled.clearDisplay();
oled.setCursor(0,0);
oled.print("BIG Bottle");
oled.display();
servo.write(180);
bigBottle++;
points += 2;
totalWeightPlastic += weight;
objectDetected = true;
delay(1500);
}
// 🧴 SMALL
else if (ir1 && weight > 20) {
oled.clearDisplay();
oled.setCursor(0,0);
oled.print("SMALL Bottle");
oled.display();
servo.write(180);
smallBottle++;
points += 1;
totalWeightPlastic += weight;
objectDetected = true;
delay(1500);
}
else {
oled.clearDisplay();
oled.setCursor(0,0);
oled.print("Unknown !");
oled.display();
objectDetected = true;
// 🔥 دفع للأمام
servoUnknown.write(0); // حركة الدفع
delay(1500);
servoUnknown.write(90); // رجوع للوضع العادي
}
servo.write(90);
// ===== LCD =====
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Pts:");
lcd.print(points);
lcd.setCursor(0,1);
lcd.print("C:");
lcd.print(cans);
lcd.print(" BB:");
lcd.print(bigBottle);
lcd.print(" SB:");
lcd.print(smallBottle);
delay(1000);
}