#include "esp_camera.h"
#include <WiFi.h>
#define CAMERA_MODEL_AI_THINKER
#include "camera_pins.h"
const char* ssid = "Naimish AirFiber";
const char* password = "*N@!m!$h123*";
#define IR_SENSOR_PIN 2 // IR sensor
#define SERVO_PIN 14 // Servo PWM
#define MOTOR_IN1 12 // DC motor control
#define MOTOR_IN2 13 // DC motor control
WiFiServer server(80);
int lastIrState = HIGH;
void setup() {
Serial.begin(115200);
Serial.setDebugOutput(true);
Serial.println("Booting...");
pinMode(IR_SENSOR_PIN, INPUT_PULLUP);
pinMode(MOTOR_IN1, OUTPUT);
pinMode(MOTOR_IN2, OUTPUT);
// Servo via LEDC PWM
ledcSetup(0, 50, 16); // Channel 0, 50 Hz, 16-bit resolution
ledcAttachPin(SERVO_PIN, 0); // Attach pin to channel
delay(5000); // Sensor stabilization
camera_config_t config;
config.ledc_channel = LEDC_CHANNEL_0;
config.ledc_timer = LEDC_TIMER_0;
config.pin_d0 = Y2_GPIO_NUM;
config.pin_d1 = Y3_GPIO_NUM;
config.pin_d2 = Y4_GPIO_NUM;
config.pin_d3 = Y5_GPIO_NUM;
config.pin_d4 = Y6_GPIO_NUM;
config.pin_d5 = Y7_GPIO_NUM;
config.pin_d6 = Y8_GPIO_NUM;
config.pin_d7 = Y9_GPIO_NUM;
config.pin_xclk = XCLK_GPIO_NUM;
config.pin_pclk = PCLK_GPIO_NUM;
config.pin_vsync = VSYNC_GPIO_NUM;
config.pin_href = HREF_GPIO_NUM;
config.pin_sccb_sda = SIOD_GPIO_NUM;
config.pin_sccb_scl = SIOC_GPIO_NUM;
config.pin_pwdn = PWDN_GPIO_NUM;
config.pin_reset = RESET_GPIO_NUM;
config.xclk_freq_hz = 20000000;
config.frame_size = FRAMESIZE_QVGA;
config.pixel_format = PIXFORMAT_RGB565;
config.grab_mode = CAMERA_GRAB_WHEN_EMPTY;
config.fb_location = CAMERA_FB_IN_PSRAM;
config.jpeg_quality = 10;
config.fb_count = 2;
if (!psramFound()) {
config.frame_size = FRAMESIZE_SVGA;
config.fb_location = CAMERA_FB_IN_DRAM;
}
if (esp_camera_init(&config) != ESP_OK) {
Serial.println("ā Camera init failed");
return;
}
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nā
WiFi connected");
Serial.print("š¶ IP address: http://");
Serial.println(WiFi.localIP());
server.begin();
}
void moveServo(int angle) {
int duty = map(angle, 0, 180, 1638, 8192); // Convert to 16-bit
ledcWrite(0, duty);
delay(500); // Allow movement
}
void loop() {
int irState = digitalRead(IR_SENSOR_PIN);
delay(100);
if (lastIrState == HIGH && irState == LOW) {
Serial.println("š Object Detected! Capturing and analyzing...");
// Start conveyor motor
digitalWrite(MOTOR_IN1, HIGH);
digitalWrite(MOTOR_IN2, LOW);
delay(800); // Wait for fruit to align
camera_fb_t *fb = esp_camera_fb_get();
if (!fb) {
Serial.println("ā Camera capture failed");
} else {
int greenPixels = 0;
int totalPixels = fb->width * fb->height;
for (int i = 0; i < fb->len; i += 2) {
uint16_t pixel = fb->buf[i] | (fb->buf[i + 1] << 8);
int red = (pixel >> 11) & 0x1F;
int green = (pixel >> 5) & 0x3F;
int blue = pixel & 0x1F;
if (green > red + blue) greenPixels++;
}
float greenRatio = (float)greenPixels / totalPixels;
Serial.printf("š Green Ratio: %.2f\n", greenRatio);
if (greenRatio > 0.5) {
Serial.println("ā
Green fruit detected ā Moving servo to 90°");
moveServo(90);
} else {
Serial.println("ā Not a green fruit ā Moving servo to 0°");
moveServo(0);
}
esp_camera_fb_return(fb);
}
// Stop conveyor motor
digitalWrite(MOTOR_IN1, LOW);
digitalWrite(MOTOR_IN2, LOW);
delay(3000); // Cooldown delay
}
lastIrState = irState;
WiFiClient client = server.available();
if (client) {
String request = client.readStringUntil('\r');
client.read();
client.println("HTTP/1.1 200 OK\nContent-Type: text/html\n");
client.println("<html><body><h2>Fruit Scanner Online</h2>");
client.println("<p>Check Serial Monitor for real-time classification.</p>");
client.println("</body></html>");
client.stop();
}
}