#include <LiquidCrystal_I2C.h>
#include <Keypad.h>
// --- Configuración de Hardware ---
#define DIRECCION_LCD 0x27
#define ANCHO_LCD 16
#define ALTO_LCD 2
// --- Configuración del Keypad ---
const byte FILAS = 4;
const byte COLS = 4;
char teclas[FILAS][COLS] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};
// Pines para STM32/Arduino
byte pinesFilas[FILAS] = {6, 5, 4, 3};
byte pinesCols[COLS] = {2, A5, A4, A3};
Keypad teclado = Keypad(makeKeymap(teclas), pinesFilas, pinesCols, FILAS, COLS);
// --- Configuración de Dispositivos ---
LiquidCrystal_I2C pantalla(DIRECCION_LCD, ANCHO_LCD, ALTO_LCD);
const int SERVO_PIN = 9;
const int LED_STATUS = 8;
const int BTN_INPUT = 7;
// --- Lógica de Seguridad ---
String claveSecreta = "1234";
String claveIngresada = "";
bool estaAbierta = false;
void setup() {
pinMode(SERVO_PIN, OUTPUT);
pinMode(LED_STATUS, OUTPUT);
pinMode(BTN_INPUT, INPUT_PULLUP);
pantalla.init();
pantalla.backlight();
actualizarPantalla("SISTEMA ACTIVO", "INGRESE CLAVE:");
accionarMecanismo(0); // Cerrado al iniciar
digitalWrite(LED_STATUS, LOW);
}
void loop() {
char teclaPresionada = teclado.getKey();
if (teclaPresionada) {
if (teclaPresionada == '#') { // Usamos # para borrar o resetear
claveIngresada = "";
actualizarPantalla("CLAVE BORRADA", "NUEVO INTENTO");
}
else if (teclaPresionada == '*') { // Usamos * para confirmar cierre manual
cerrarPuerta();
}
else {
claveIngresada += teclaPresionada;
pantalla.setCursor(claveIngresada.length() - 1, 1);
pantalla.print('*'); // Ocultar clave con asteriscos
if (claveIngresada.length() == claveSecreta.length()) {
if (claveIngresada == claveSecreta) {
abrirPuerta();
} else {
actualizarPantalla("CLAVE ERRADA", "REINTENTE");
delay(1000);
actualizarPantalla("SISTEMA ACTIVO", "INGRESE CLAVE:");
}
claveIngresada = ""; // Limpiar despues de comparar
}
}
}
// El botón físico sirve para alternar el estado rápidamente
if (digitalRead(BTN_INPUT) == LOW) {
delay(50);
if (digitalRead(BTN_INPUT) == LOW) {
if (estaAbierta) cerrarPuerta();
else abrirPuerta();
while (digitalRead(BTN_INPUT) == LOW);
}
}
}
void abrirPuerta() {
estaAbierta = true;
accionarMecanismo(90);
digitalWrite(LED_STATUS, HIGH);
actualizarPantalla("ACCESO TOTAL", "PUERTA ABIERTA");
}
void cerrarPuerta() {
estaAbierta = false;
accionarMecanismo(0);
digitalWrite(LED_STATUS, LOW);
actualizarPantalla("BLOQUEADO", "PUERTA CERRADA");
delay(1000);
actualizarPantalla("SISTEMA ACTIVO", "INGRESE CLAVE:");
}
void actualizarPantalla(String lin1, String lin2) {
pantalla.clear();
pantalla.setCursor(0, 0);
pantalla.print(lin1);
pantalla.setCursor(0, 1);
pantalla.print(lin2);
}
void accionarMecanismo(int grados) {
int anchoPulso = map(grados, 0, 180, 500, 2400);
for (int ciclo = 0; ciclo < 50; ciclo++) {
digitalWrite(SERVO_PIN, HIGH);
delayMicroseconds(anchoPulso);
digitalWrite(SERVO_PIN, LOW);
delay(20 - (anchoPulso / 1000));
}
}