Parking con barrera automática y funciones modernas de seguridad

Código

#include <LiquidCrystal.h>
#include <IRremote.h>
#include <Stepper.h>

/* ───────── Pines ───────── */
const int RECV_PIN = 2;
const int LED_OK = A0;
const int LED_FAIL = A1;
const int BUZZER_PIN = A2;

const int TRIG_PIN = A5;
const int ECHO_PIN = A4;

const int IN1 = 3, IN2 = 4, IN3 = 5, IN4 = 6;

const int LED_LIBRE = 7;     // verde
const int LED_OCUPADO = A3;  // rojo

/* ───────── Contraseñas ───────── */
const int CODE_IN[4] = { 1, 1, 1, 1 };   // Entrada
const int CODE_OUT[4] = { 0, 0, 0, 0 };  // Salida

/* ───────── Variables ───────── */
String inputCode = "";
byte digitsRead = 0;

bool barreraAbierta = false;
bool modoAlerta = false;
int intentosFallidos = 0;

unsigned long ultimoBuzzer = 0;
bool buzzerEstado = false;

unsigned long ultimoPing = 0;
long distanciaCM = 999;

/* ───────── Objetos ───────── */
LiquidCrystal lcd(8, 9, 10, 11, 12, 13);
IRrecv receiver(RECV_PIN);
Stepper motor(2500, IN1, IN3, IN2, IN4);

/* ───────── Prototipos ───────── */
void pedirClave(const char* etiqueta);
long medirDistancia();
void actualizarSensorYLeds();
bool claveCorrecta(const int clave[4]);
void abrirBarrera(bool esEntrada);

/* ───────── Setup ───────── */
void setup() {
  lcd.begin(16, 2);

  pinMode(LED_OK, OUTPUT);
  pinMode(LED_FAIL, OUTPUT);
  pinMode(BUZZER_PIN, OUTPUT);

  pinMode(TRIG_PIN, OUTPUT);
  pinMode(ECHO_PIN, INPUT);

  pinMode(LED_LIBRE, OUTPUT);
  pinMode(LED_OCUPADO, OUTPUT);

  receiver.enableIRIn();
  motor.setSpeed(10);

  actualizarSensorYLeds();
  pedirClave("Entrada/Salida");
}

/* ───────── Funciones ───────── */
void pedirClave(const char* etiqueta) {
  lcd.clear();
  lcd.print("Insert ");
  lcd.print(etiqueta);
  lcd.setCursor(0, 1);
  lcd.print("Clave: ");

  inputCode = "";
  digitsRead = 0;
}

/* ---------- HC‑SR04 ---------- */
long medirDistancia() {  // cm
  digitalWrite(TRIG_PIN, LOW);
  delayMicroseconds(2);
  digitalWrite(TRIG_PIN, HIGH);
  delayMicroseconds(10);
  digitalWrite(TRIG_PIN, LOW);
  long dur = pulseIn(ECHO_PIN, HIGH, 30000);  // 30 ms máx.
  return dur * 0.034 / 2;
}

void actualizarSensorYLeds() {
  if (millis() - ultimoPing >= 60) {  // ≤ 16 Hz
    ultimoPing = millis();
    distanciaCM = medirDistancia();
  }
  bool cochePresente = (distanciaCM <= 4);
  digitalWrite(LED_LIBRE, cochePresente ? LOW : HIGH);
  digitalWrite(LED_OCUPADO, cochePresente ? HIGH : LOW);
}

bool claveCorrecta(const int clave[4]) {
  return (inputCode[0] - '0' == clave[0] && inputCode[1] - '0' == clave[1] && inputCode[2] - '0' == clave[2] && inputCode[3] - '0' == clave[3]);
}

/* esEntrada = true  -> clave CODE_IN
 * esEntrada = false -> clave CODE_OUT
 */
void abrirBarrera(bool esEntrada) {
  barreraAbierta = true;

  lcd.clear();
  lcd.print(esEntrada ? "Coche entrando..." : "Coche saliendo...");
  digitalWrite(LED_OK, HIGH);

  motor.step(512);  // abre 1/4 vuelta
  delay(500);

  unsigned long t0 = millis();
  if (esEntrada) {
    while (millis() - t0 < 8000) {
      actualizarSensorYLeds();
      if (distanciaCM <= 4) break;  // coche detectado
      delay(100);
    }
  } else {
    while (millis() - t0 < 8000) {
      actualizarSensorYLeds();
      if (distanciaCM > 8) break;  // coche se fue
      delay(100);
    }
  }

  motor.step(-512);  // cierra
  digitalWrite(LED_OK, LOW);
  barreraAbierta = false;
}

/* ───────── Loop ───────── */
void loop() {
  /* —— Alarma —— */
  if (modoAlerta) {
    if (millis() - ultimoBuzzer >= 1000) {
      ultimoBuzzer = millis();
      buzzerEstado = !buzzerEstado;
      digitalWrite(BUZZER_PIN, buzzerEstado);
    }
  }

  /* —— Lectura IR —— */
  if (receiver.decode()) {
    int code = receiver.decodedIRData.command;
    char digit = '\0';

    if (code == 12) digit = '1';
    if (code == 24) digit = '2';
    if (code == 94) digit = '3';
    if (code == 8) digit = '4';
    if (code == 28) digit = '5';
    if (code == 90) digit = '6';
    if (code == 66) digit = '7';
    if (code == 82) digit = '8';
    if (code == 74) digit = '9';
    if (code == 22) digit = '0';

    if (digit != '\0' && digitsRead < 4) {
      inputCode += digit;
      lcd.setCursor(7 + digitsRead, 1);  // tras "Clave: "
      lcd.print('*');                    // oculta dígitos
      digitsRead++;
    }
    receiver.resume();
  }

  /* —— Tras 4 dígitos —— */
  if (digitsRead == 4) {
    delay(100);
    bool estabaEnAlerta = modoAlerta;  // recordar si había alarma

    if (claveCorrecta(CODE_IN)) {  // Entrada
      intentosFallidos = 0;
      modoAlerta = false;
      digitalWrite(BUZZER_PIN, LOW);
      if (estabaEnAlerta) {
        lcd.clear();
        lcd.print("ALARMA DESACTIVADA");
        delay(1000);
      }
      abrirBarrera(true);

    } else if (claveCorrecta(CODE_OUT)) {  // Salida
      intentosFallidos = 0;
      modoAlerta = false;
      digitalWrite(BUZZER_PIN, LOW);
      if (estabaEnAlerta) {
        lcd.clear();
        lcd.print("ALARMA DESACTIVADA");
        delay(1000);
      }
      abrirBarrera(false);

    } else {  // Incorrecta
      intentosFallidos++;
      lcd.clear();
      lcd.print("CLAVE ERRONEA");
      digitalWrite(LED_FAIL, HIGH);
      delay(1000);
      digitalWrite(LED_FAIL, LOW);
      if (intentosFallidos >= 3) modoAlerta = true;
    }

    pedirClave("Entrada/Salida");
  }

  actualizarSensorYLeds();
}

También te podría gustar...

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *