#include <Wire.h>
#include <SPI.h>
#include <Servo.h>
#include <Keypad.h>
#include <MFRC522.h>
#include <LiquidCrystal_I2C.h>
//==================================================
// DEFINICIÓN DE PINES
//==================================================
// Servo
const byte PIN_SERVO = 9;
// Buzzer
const byte PIN_BUZZER = 38;
// LEDs
const byte PIN_LED_VERDE = 40;
const byte PIN_LED_ROJO = 42;
// RFID
const byte RFID_SS = 53;
const byte RFID_RST = 49;
//==================================================
// CONFIGURACIÓN DEL SISTEMA
//==================================================
// Servo
const int ANGULO_CERRADO = 0;
const int ANGULO_ABIERTO = 90;
// Seguridad
const byte MAX_INTENTOS = 3;
const unsigned long TIEMPO_BLOQUEO = 30000; // 30 segundos
//==================================================
// OBJETOS
//==================================================
// Pantalla LCD
LiquidCrystal_I2C lcd(0x27, 20, 4);
// Servo
Servo servoPuerta;
// RFID
MFRC522 rfid(RFID_SS, RFID_RST);
//==================================================
// KEYPAD
//==================================================
const byte FILAS = 4;
const byte COLUMNAS = 4;
char teclas[FILAS][COLUMNAS] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};
byte pinesFilas[FILAS] = {22, 24, 26, 28};
byte pinesColumnas[COLUMNAS] = {30, 32, 34, 36};
Keypad teclado = Keypad(
makeKeymap(teclas),
pinesFilas,
pinesColumnas,
FILAS,
COLUMNAS
);
//==================================================
// ESTRUCTURA DE USUARIOS
//==================================================
struct Usuario {
String nombre;
byte uid[4];
String pin;
bool administrador;
};
//==================================================
// BASE DE DATOS DE USUARIOS
//==================================================
Usuario usuarios[] = {
{
"Administrador",
{0x01, 0x02, 0x03, 0x04},
"1234",
true
},
{
"Usuario 1",
{0x00, 0x00, 0x00, 0x00},
"5678",
false
},
{
"Usuario 2",
{0x00, 0x00, 0x00, 0x00},
"9012",
false
}
};
const byte TOTAL_USUARIOS = sizeof(usuarios) / sizeof(usuarios[0]);
//==================================================
// PROTOTIPOS DE FUNCIONES
//==================================================
// Interfaz
void mostrarEsperaRFID();
void mostrarAccesoConcedido(String nombre);
void mostrarTarjetaNoRegistrada();
void mostrarSolicitarPIN(String nombre);
// RFID
bool leerTarjeta(byte uid[]);
Usuario* buscarUsuarioPorUID(byte uid[]);
bool compararUID(byte uid1[], byte uid2[]);
void leerPIN();
void beepCorto();
void beepExito();
void beepError();
void beepBloqueo();
void mostrarMenuAdminInicio();
//==================================================
// VARIABLES RFID
//==================================================
byte uidLeido[4];
//==================================================
// ESTADOS DEL SISTEMA
//==================================================
enum EstadoSistema {
ESPERANDO_RFID,
ESPERANDO_PIN,
MENU_ADMIN,
ACCESO_CONCEDIDO,
ACCESO_DENEGADO,
SISTEMA_BLOQUEADO
};
EstadoSistema estadoActual = ESPERANDO_RFID;
//==================================================
// VARIABLES DE AUTENTICACIÓN
//==================================================
Usuario* usuarioActual = nullptr;
String pinIngresado = "";
byte intentos = 0;
unsigned long inicioBloqueo = 0;
bool pantallaBloqueoMostrada = false;
//==================================================
// SETUP
//==================================================
void setup() {
// Comunicación serial
Serial.begin(9600);
// LCD
lcd.init();
lcd.backlight();
// Servo
servoPuerta.attach(PIN_SERVO);
servoPuerta.write(ANGULO_CERRADO);
// RFID
SPI.begin();
rfid.PCD_Init();
// LEDs
pinMode(PIN_LED_VERDE, OUTPUT);
pinMode(PIN_LED_ROJO, OUTPUT);
digitalWrite(PIN_LED_VERDE, LOW);
digitalWrite(PIN_LED_ROJO, LOW);
// Buzzer
pinMode(PIN_BUZZER, OUTPUT);
digitalWrite(PIN_BUZZER, LOW);
// Pantalla de inicio
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("CONTROL DE ACCESO");
lcd.setCursor(2, 2);
lcd.print("Inicializando...");
delay(2000);
lcd.clear();
lcd.setCursor(2, 0);
lcd.print("Escanee tarjeta");
lcd.setCursor(1, 2);
lcd.print("Esperando RFID...");
}
//==================================================
// LOOP
//==================================================
void loop() {
switch (estadoActual) {
case ESPERANDO_RFID:
if (leerTarjeta(uidLeido)) {
usuarioActual = buscarUsuarioPorUID(uidLeido);
if (usuarioActual != nullptr) {
pinIngresado = "";
mostrarSolicitarPIN(usuarioActual->nombre);
estadoActual = ESPERANDO_PIN;
}
else {
mostrarTarjetaNoRegistrada();
delay(2000);
mostrarEsperaRFID();
}
}
break;
case ESPERANDO_PIN:
leerPIN();
break;
case MENU_ADMIN:
lcd.clear();
lcd.setCursor(0,0);
lcd.print("MENU ADMIN");
while (true);
break;
case ACCESO_CONCEDIDO:
beepExito();
mostrarAccesoConcedido(usuarioActual->nombre);
digitalWrite(PIN_LED_VERDE, HIGH);
servoPuerta.write(ANGULO_ABIERTO);
delay(3000);
servoPuerta.write(ANGULO_CERRADO);
digitalWrite(PIN_LED_VERDE, LOW);
mostrarEsperaRFID();
pinIngresado = "";
usuarioActual = nullptr;
intentos = 0;
estadoActual = ESPERANDO_RFID;
break;
case ACCESO_DENEGADO:
beepError();
lcd.clear();
lcd.setCursor(2,0);
lcd.print("PIN Incorrecto");
digitalWrite(PIN_LED_ROJO, HIGH);
delay(2000);
digitalWrite(PIN_LED_ROJO, LOW);
mostrarSolicitarPIN(usuarioActual->nombre);
pinIngresado = "";
estadoActual = ESPERANDO_PIN;
break;
case SISTEMA_BLOQUEADO:
if (!pantallaBloqueoMostrada) {
lcd.clear();
lcd.setCursor(0,0);
lcd.print("SISTEMA");
lcd.setCursor(0,1);
lcd.print("BLOQUEADO");
beepBloqueo();
digitalWrite(PIN_LED_ROJO, HIGH);
pantallaBloqueoMostrada = true;
}
if (millis() - inicioBloqueo >= TIEMPO_BLOQUEO) {
digitalWrite(PIN_LED_ROJO, LOW);
intentos = 0;
pinIngresado = "";
usuarioActual = nullptr;
pantallaBloqueoMostrada = false;
mostrarEsperaRFID();
estadoActual = ESPERANDO_RFID;
}
break;
}
}
//==================================================
// FUNCIONES DE INTERFAZ
//==================================================
// Pantalla de espera
void mostrarEsperaRFID() {
lcd.clear();
lcd.setCursor(2, 0);
lcd.print("Escanee tarjeta");
lcd.setCursor(1, 2);
lcd.print("Esperando RFID...");
}
// Pantalla de acceso concedido
void mostrarAccesoConcedido(String nombre) {
lcd.clear();
lcd.setCursor(2, 0);
lcd.print("Bienvenido");
lcd.setCursor(0, 2);
lcd.print(nombre);
}
// Pantalla de tarjeta no registrada
void mostrarTarjetaNoRegistrada() {
lcd.clear();
lcd.setCursor(1, 0);
lcd.print("Tarjeta NO");
lcd.setCursor(2, 2);
lcd.print("Registrada");
}
// Pantalla para solicitar PIN
void mostrarSolicitarPIN(String nombre) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Hola ");
lcd.print(nombre);
lcd.setCursor(0, 2);
lcd.print("Ingrese PIN:");
}
void mostrarMenuAdminInicio() {
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Hola Admin");
lcd.setCursor(0,1);
lcd.print("A = Menu");
lcd.setCursor(0,2);
lcd.print("# = Acceder");
}
//==================================================
// FUNCIONES RFID
//==================================================
bool compararUID(byte uid1[], byte uid2[]) {
for (byte i = 0; i < 4; i++) {
if (uid1[i] != uid2[i]) {
return false;
}
}
return true;
}
Usuario* buscarUsuarioPorUID(byte uid[]) {
for (byte i = 0; i < TOTAL_USUARIOS; i++) {
if (compararUID(uid, usuarios[i].uid)) {
return &usuarios[i];
}
}
return nullptr;
}
bool leerTarjeta(byte uid[]) {
if (!rfid.PICC_IsNewCardPresent()) {
return false;
}
if (!rfid.PICC_ReadCardSerial()) {
return false;
}
for (byte i = 0; i < 4; i++) {
uid[i] = rfid.uid.uidByte[i];
}
rfid.PICC_HaltA();
rfid.PCD_StopCrypto1();
return true;
}
void leerPIN() {
char tecla = teclado.getKey();
if (!tecla) return;
beepCorto();
// Números
if (tecla >= '0' && tecla <= '9') {
if (pinIngresado.length() < 4) {
pinIngresado += tecla;
lcd.setCursor(pinIngresado.length() - 1, 3);
lcd.print("*");
}
return;
}
// Confirmar PIN
if (tecla == '#') {
if (pinIngresado == usuarioActual->pin) {
if (usuarioActual->administrador) {
estadoActual = MENU_ADMIN;
}
else {
estadoActual = ACCESO_CONCEDIDO;
}
} else {
intentos++;
if (intentos >= MAX_INTENTOS) {
inicioBloqueo = millis();
pantallaBloqueoMostrada = false;
estadoActual = SISTEMA_BLOQUEADO;
}
else {
estadoActual = ACCESO_DENEGADO;
}
}
}
// Borrar PIN
if (tecla == '*') {
pinIngresado = "";
lcd.setCursor(0,3);
lcd.print(" ");
}
}
//==================================================
// SONIDOS
//==================================================
// Beep corto (teclado)
void beepCorto() {
tone(PIN_BUZZER, 2000);
delay(50);
noTone(PIN_BUZZER);
}
// Acceso concedido
void beepExito() {
tone(PIN_BUZZER, 2500);
delay(150);
noTone(PIN_BUZZER);
}
// Error
void beepError() {
tone(PIN_BUZZER, 1200);
delay(120);
noTone(PIN_BUZZER);
delay(80);
tone(PIN_BUZZER, 1200);
delay(120);
noTone(PIN_BUZZER);
}
// Sistema bloqueado
void beepBloqueo() {
tone(PIN_BUZZER, 800);
delay(1000);
noTone(PIN_BUZZER);
}