#define I2C_ADDR 0x27 // Dirección I2C de la LCD
#define LCD_COLUMNS 16 // Número de columnas de la LCD
#define LCD_LINES 2 // Número de filas de la LCD
#include <Keypad.h> // Librería para el teclado matricial
#include <Wire.h> // Librería para comunicación I2C
#include <LiquidCrystal_I2C.h> // Librería para la LCD I2C
#include <ESP32Servo.h> // Librería para el servo motor con ESP32
// Define el layout del teclado y los pines de conexión
const byte ROWS = 4; // Número de filas del teclado
const byte COLS = 4; // Número de columnas del teclado
char keys[ROWS][COLS] = { // Matriz con los caracteres de las teclas
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};
byte rowPins[ROWS] = {15, 2, 4, 5}; // Pines conectados a las filas del teclado
byte colPins[COLS] = {18, 19, 27, 23}; // Pines conectados a las columnas del teclado
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS); // Crea el objeto teclado
// Define el servo motor y el pin de conexión
Servo myServo; // Objeto para el servo motor
const int servoPin = 14; // Pin conectado al servo motor
const int unlockPosition = -90; // Posición del servo para desbloquear la puerta
const int lockPosition = 90; // Posición del servo para bloquear la puerta
// Define la LCD y sus ajustes
LiquidCrystal_I2C lcd(I2C_ADDR, LCD_COLUMNS, LCD_LINES); // Objeto para la LCD I2C
// Variables globales
bool locked = true; // Estado de la cerradura (true: bloqueada, false: desbloqueada)
char enteredCode[5]; // Array para almacenar el código ingresado (4 dígitos + '\0')
int codeIndex = 0; // Índice para el array enteredCode
const char correctCode[] = "1234"; // Código de acceso correcto
void setup() {
Serial.begin(9600); // Inicializa la comunicación serial a 9600 baudios
Serial.println("Inicializando Sistema de Cerradura...");
// Inicializa el servo motor
myServo.attach(servoPin); // Asigna el pin al objeto servo
myServo.write(lockPosition); // Establece la posición inicial del servo (bloqueado)
Serial.println("Servo motor inicializado en posición de bloqueo.");
// Inicializa la LCD
Wire.begin(); // Inicializa la comunicación I2C
lcd.init(); // Inicializa la LCD
lcd.backlight(); // Enciende la luz de fondo de la LCD
Serial.println("LCD inicializada.");
updateLockStatus(); // Actualiza y muestra el estado inicial de la cerradura en la LCD
Serial.println("Sistema de cerradura listo.");
}
void loop() {
char key = keypad.getKey(); // Obtiene la tecla presionada del teclado
if (key) { // Si se presionó una tecla
Serial.print("Tecla presionada: ");
Serial.println(key);
handleKeypadInput(key); // Llama a la función para manejar la entrada del teclado
}
delay(50); // Pequeño delay para evitar lecturas múltiples de la misma tecla
}
// Función para actualizar el estado de la cerradura y mostrarlo en la LCD
void updateLockStatus() {
lcd.clear(); // Limpia la LCD
lcd.setCursor(0, 0); // Establece el cursor en la primera fila, primera columna
if (locked) {
lcd.print("Puerta Bloqueada"); // Muestra "Puerta Bloqueada"
Serial.println("Estado: Puerta Bloqueada");
} else {
lcd.print("Puerta Desbloq."); // Muestra "Puerta Desbloqueada"
Serial.println("Estado: Puerta Desbloqueada");
}
}
// Función para manejar la entrada del teclado
void handleKeypadInput(char key) {
if (locked) { // Si la puerta está bloqueada (esperando código)
if (key == '#' && codeIndex > 0) { // Si se presiona '#' (Enter) y se ha ingresado al menos un dígito
enteredCode[codeIndex] = '\0'; // Termina la cadena del código ingresado
Serial.print("Código ingresado: ");
Serial.println(enteredCode);
if (strcmp(enteredCode, correctCode) == 0) { // Compara el código ingresado con el correcto
Serial.println("Código Correcto!");
unlockDoor(); // Llama a la función para desbloquear la puerta
} else {
Serial.println("Código Incorrecto!");
lcd.clear();
lcd.print("PIN Incorrecto");
delay(2000);
updateLockStatus();
}
codeIndex = 0; // Reinicia el índice del código
memset(enteredCode, 0, sizeof(enteredCode)); // Limpia el array enteredCode
} else if (key == 'C' && codeIndex > 0) { // Si se presiona 'C' (Borrar) y hay dígitos ingresados
lcd.setCursor(codeIndex - 1, 1); // Mueve el cursor un lugar a la izquierda en la LCD
lcd.print(' '); // Borra el carácter en la LCD
codeIndex--; // Decrementa el índice del código
enteredCode[codeIndex] = '\0'; // Borra el último carácter del array
} else if (key != '#' && key != 'C' && codeIndex < sizeof(enteredCode) - 1) { // Si es un dígito y hay espacio en el array
enteredCode[codeIndex] = key; // Agrega el dígito al array
lcd.setCursor(codeIndex, 1); // Establece el cursor en la posición correspondiente en la LCD
lcd.print('*'); // Muestra un '*' en la LCD para ocultar el dígito
codeIndex++; // Incrementa el índice del código
}
} else { // Si la puerta está desbloqueada
if (key == '*') { // Si se presiona '*' (Bloquear)
lockDoor(); // Llama a la función para bloquear la puerta
}
}
}
// Función para desbloquear la puerta
void unlockDoor() {
locked = false; // Actualiza el estado de la cerradura
myServo.write(unlockPosition); // Mueve el servo a la posición de desbloqueo
Serial.println("Puerta Desbloqueada");
updateLockStatus(); // Actualiza el estado en la LCD
}
// Función para bloquear la puerta
void lockDoor() {
locked = true; // Actualiza el estado de la cerradura
myServo.write(lockPosition); // Mueve el servo a la posición de bloqueo
Serial.println("Puerta Bloqueada");
updateLockStatus(); // Actualiza el estado en la LCD
codeIndex = 0;
memset(enteredCode, 0, sizeof(enteredCode));
}