#include <ESP32Servo.h>
#include <Ultrasonic.h>  // Librería para el sensor ultrasónico compatible con ESP32

// Pines del sensor ultrasónico para el semáforo 1
#define TRIG_PIN_1 17
#define ECHO_PIN_1 19

// Pines del sensor ultrasónico para el semáforo 2
#define TRIG_PIN_2 18
#define ECHO_PIN_2 21

// Constantes para los LEDs del semáforo 1
const int redLed1 = 13;
const int yellowLed1 = 12;
const int greenLed1 = 14;

// Constantes para los LEDs del semáforo 2
const int redLed2 = 27;
const int yellowLed2 = 26;
const int greenLed2 = 25;

Servo servo1;  // Servomotor para el semáforo 1
Servo servo2;  // Servomotor para el semáforo 2

const int servoPin1 = 15;
const int servoPin2 = 16;

// Inicializamos los sensores ultrasónicos con la librería Ultrasonic
Ultrasonic ultrasonic1(TRIG_PIN_1, ECHO_PIN_1);  // Sensor para el semáforo 1
Ultrasonic ultrasonic2(TRIG_PIN_2, ECHO_PIN_2);  // Sensor para el semáforo 2

unsigned long previousMillis = 0;
unsigned long greenLightDuration = 5000;  // Duración por defecto de la luz verde (5 segundos)

// Simulación de lógica "inteligente" que ajusta la duración de la luz verde
unsigned long predictTraffic(int distance) {
  // Aquí simulamos un modelo que "predice" el tráfico basado en la distancia detectada
  if (distance < 30) {  // Mucho tráfico: distancia muy corta
    Serial.println("Predicción de IA: Alto tráfico. Aumentando el tiempo de luz verde a 15 segundos.");
    return 15000;  // Tiempo alto para manejar el tráfico
  } else if (distance < 60) {  // Tráfico moderado
    Serial.println("Predicción de IA: Tráfico moderado. Aumentando el tiempo de luz verde a 10 segundos.");
    return 10000;  // Tiempo moderado
  } else {  // Poco tráfico
    Serial.println("Predicción de IA: Poco tráfico. Manteniendo tiempo de luz verde en 5 segundos.");
    return 5000;  // Tiempo bajo
  }
}

void setup() {
  // Configuración de los pines de los LEDs como salida
  pinMode(redLed1, OUTPUT);
  pinMode(yellowLed1, OUTPUT);
  pinMode(greenLed1, OUTPUT);

  pinMode(redLed2, OUTPUT);
  pinMode(yellowLed2, OUTPUT);
  pinMode(greenLed2, OUTPUT);

  // Inicializa los servomotores
  servo1.attach(servoPin1);
  servo2.attach(servoPin2);
  
  servo1.write(0);  // Inicialmente barrera cerrada para semáforo 1
  servo2.write(0);  // Inicialmente barrera cerrada para semáforo 2

  Serial.begin(115200);  // Para la depuración
}

void loop() {
  // Leer las distancias de los sensores ultrasónicos
  int distance1 = ultrasonic1.read();  // Distancia detectada por el sensor del semáforo 1
  int distance2 = ultrasonic2.read();  // Distancia detectada por el sensor del semáforo 2
  
  // Simulación de IA ajustando la duración de la luz verde según el tráfico detectado
  unsigned long duration1 = predictTraffic(distance1);
  unsigned long duration2 = predictTraffic(distance2);
  
  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis >= greenLightDuration) {
    previousMillis = currentMillis;
    
    // Cambia el estado del semáforo 1 y 2 en función del ciclo actual
    static int state = 0;
    state = (state + 1) % 4;  // Alterna entre los 4 estados

    switch (state) {
      case 0:  // Semáforo 1 en verde, semáforo 2 en rojo
        digitalWrite(greenLed1, HIGH);
        digitalWrite(yellowLed1, LOW);
        digitalWrite(redLed1, LOW);

        digitalWrite(greenLed2, LOW);
        digitalWrite(yellowLed2, LOW);
        digitalWrite(redLed2, HIGH);
        
        servo1.write(0);   // Barrera cerrada en semáforo 1
        servo2.write(90);  // Barrera abierta en semáforo 2
        greenLightDuration = duration1;  // Ajusta la duración según el tráfico detectado en el semáforo 1
        break;
        
      case 1:  // Semáforo 1 en amarillo, semáforo 2 sigue en rojo
        digitalWrite(greenLed1, LOW);
        digitalWrite(yellowLed1, HIGH);
        digitalWrite(redLed1, LOW);

        digitalWrite(greenLed2, LOW);
        digitalWrite(yellowLed2, LOW);
        digitalWrite(redLed2, HIGH);
        
        servo1.write(0);  
        servo2.write(90);  
        break;

      case 2:  // Semáforo 1 en rojo, semáforo 2 en verde
        digitalWrite(greenLed1, LOW);
        digitalWrite(yellowLed1, LOW);
        digitalWrite(redLed1, HIGH);

        digitalWrite(greenLed2, HIGH);
        digitalWrite(yellowLed2, LOW);
        digitalWrite(redLed2, LOW);
        
        servo1.write(90);  // Barrera abierta en semáforo 1
        servo2.write(0);   // Barrera cerrada en semáforo 2
        greenLightDuration = duration2;  // Ajusta la duración según el tráfico detectado en el semáforo 2
        break;

      case 3:  // Semáforo 1 sigue en rojo, semáforo 2 en amarillo
        digitalWrite(greenLed1, LOW);
        digitalWrite(yellowLed1, LOW);
        digitalWrite(redLed1, HIGH);

        digitalWrite(greenLed2, LOW);
        digitalWrite(yellowLed2, HIGH);
        digitalWrite(redLed2, LOW);
        
        servo1.write(90);  
        servo2.write(0);  
        break;
    }
  }
}
$abcdeabcde151015202530354045505560fghijfghij