#include <LiquidCrystal.h>
#include <Servo.h>

#define t1 10
#define t2 9
#define t3 8
#define t4 7
#define v1 14
#define v2 16
#define v3 18
#define v4 20 //al reves
#define r1 15
#define r2 17
#define r3 19
#define r4 21 //al reves
#define SERVO_PIN 6
#define BUZZER_PIN 22

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
LiquidCrystal lcd2(42, 43, 44, 45, 46, 47);

Servo servoMotor;
int distanciaLimite = 100;
int contadorEntradas = 0;
int contadorSalidas = 0;

uint8_t pacman[8] = {
  0b00000,
  0b00000,
  0b01110,
  0b11011,
  0b00111,
  0b01110,
  0b00000,
  0b00000
};

uint8_t pacmanOpen[8] = {
  0b00000,
  0b00000,
  0b01110,
  0b11011,
  0b11100,
  0b01110,
  0b00000,
  0b00000
};

void setup() {
  lcd.begin(20, 4);
  lcd2.begin(20, 4);
  lcd.createChar(1, pacman);
  lcd.createChar(2, pacmanOpen);
  pinMode(v1, OUTPUT);
  pinMode(v2, OUTPUT);
  pinMode(v3, OUTPUT);
  pinMode(v4, OUTPUT);
  pinMode(r1, OUTPUT);
  pinMode(r2, OUTPUT);
  pinMode(r3, OUTPUT);
  pinMode(r4, OUTPUT);
  pinMode(BUZZER_PIN, OUTPUT);
  servoMotor.attach(SERVO_PIN);
}

long medirDistancia(int triggerPin, int echoPin) {
  pinMode(triggerPin, OUTPUT);
  digitalWrite(triggerPin, LOW);
  delayMicroseconds(2);
  digitalWrite(triggerPin, HIGH);
  delayMicroseconds(5);
  digitalWrite(triggerPin, LOW);
  pinMode(echoPin, INPUT);
  long duracion = pulseIn(echoPin, HIGH);
  return duracion / 58.2; // Convertir a cm
}

void controlarLEDs(float distancia, int ledVerdePin, int ledRojoPin) {
  if (distancia >= distanciaLimite) {
    digitalWrite(ledVerdePin, HIGH);
    digitalWrite(ledRojoPin, LOW);
  } else {
    digitalWrite(ledRojoPin, HIGH);
    digitalWrite(ledVerdePin, LOW);
  }
}

void mostrarEnLCD() {
  // Mostrar bienvenida y número de entradas y salidas en el primer LCD
  lcd.setCursor(0, 0);
  lcd.print("\2 Parqueadero UdeA \1");
  lcd.setCursor(0, 1);
  lcd.print("Entradas: ");
  lcd.print(contadorEntradas);
  lcd.setCursor(0, 2);
  lcd.print("Salidas: ");
  lcd.print(contadorSalidas);

  // Mostrar estado de cada puesto de estacionamiento en el segundo LCD
  lcd2.clear(); // Limpiar el segundo LCD
  lcd2.setCursor(0, 0);
  lcd2.print("Puesto 1: ");
  if (digitalRead(v1) == HIGH)
    lcd2.print("Libre");
  else
    lcd2.print("Ocupado");

  lcd2.setCursor(0, 1);
  lcd2.print("Puesto 2: ");
  if (digitalRead(v2) == HIGH)
    lcd2.print("Libre");
  else
    lcd2.print("Ocupado");

  lcd2.setCursor(0, 2);
  lcd2.print("Puesto 3: ");
  if (digitalRead(v3) == HIGH)
    lcd2.print("Libre");
  else
    lcd2.print("Ocupado");

  lcd2.setCursor(0, 3);
  lcd2.print("Puesto 4: ");
  if (digitalRead(v4) == HIGH)
    lcd2.print("Libre");
  else
    lcd2.print("Ocupado");
}

void registrarEntradaSalida(float distanciaActual, float distanciaAnterior) {
  if (distanciaActual < distanciaLimite && distanciaAnterior >= distanciaLimite) {
    contadorEntradas++;
    tone(BUZZER_PIN, 1000, 500); // Alerta sonora por 500ms
  } else if (distanciaActual >= distanciaLimite && distanciaAnterior < distanciaLimite) {
    contadorSalidas++;
    tone(BUZZER_PIN, 500, 500); // Alerta sonora por 500ms
  }
}

void loop() {
  static float d1_anterior = distanciaLimite;
  static float d2_anterior = distanciaLimite;
  static float d3_anterior = distanciaLimite;
  static float d4_anterior = distanciaLimite;

  float d1 = medirDistancia(t1, t1);
  float d2 = medirDistancia(t2, t2);
  float d3 = medirDistancia(t3, t3);
  float d4 = medirDistancia(t4, t4);

  // Control del servo motor
  if (d4 > distanciaLimite || d3 > distanciaLimite || d2 > distanciaLimite || d1 > distanciaLimite) {
    servoMotor.write(90); // Abrir la barrera
  } else {
    servoMotor.write(0); // Cerrar la barrera
  }

  // Control de los LEDs
  controlarLEDs(d1, v1, r1);
  controlarLEDs(d2, v2, r2);
  controlarLEDs(d3, v3, r3);
  controlarLEDs(d4, v4, r4);

  // Actualizar la pantalla LCD
  mostrarEnLCD();

  // Registrar entrada y salida de vehículos
  registrarEntradaSalida(d1, d1_anterior);
  registrarEntradaSalida(d2, d2_anterior);
  registrarEntradaSalida(d3, d3_anterior);
  registrarEntradaSalida(d4, d4_anterior);

  // Guardar las distancias anteriores para la próxima iteración
  d1_anterior = d1;
  d2_anterior = d2;
  d3_anterior = d3;
  d4_anterior = d4;

  delay(300);
}
$abcdeabcde151015202530fghijfghij