// Incluir librerías necesarias
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <MFRC522.h>
#include <SPI.h>
// Configurar pantalla LCD I2C
LiquidCrystal_I2C lcd(0x27, 16, 2); // Dirección del LCD, tamaño 16x2
// Pines para el RFID (conexiones SPI estándar en Arduino UNO)
#define SDA_PIN 10 // Pin SS del RFID
#define SCK_PIN 13 // Pin SCK del RFID
#define MOSI_PIN 11 // Pin MOSI del RFID
#define MISO_PIN 12 // Pin MISO del RFID
#define RST_PIN 9 // Pin de reset del RFID
MFRC522 rfid(SDA_PIN, RST_PIN); // Inicializar lector RFID
// Pines del motor paso a paso 1 (ULN2003)
#define IN1_PIN 4
#define IN2_PIN 5
#define IN3_PIN 6
#define IN4_PIN 7
// Pines del motor paso a paso 2 (ULN2003)
#define IN1_PIN A0
#define IN2_PIN A1
#define IN3_PIN A2
#define IN4_PIN A3
// Variables para controlar las plazas
int plazasTotales = 20; // Plazas totales del parqueadero
int plazasDisponibles = 20; // Plazas disponibles inicialmente
// Variables para el motor paso a paso
int pasosPorRevolucion = 500; // Pasos por revolución del motor (ajustar si es necesario)
bool puertaAbierta = false; // Estado de la puerta (abierta o cerrada)
// Variable para almacenar el UID de la tarjeta que se usó para entrar
byte ultimoUID[4];
bool tarjetaEnUso = false; // Indica si la tarjeta ya está registrada como "entrada"
// Variable para controlar la velocidad del segundo motor
int velocidadMotor2 = 10; // Velocidad inicial del segundo motor
// Configuración inicial
void setup() {
Serial.begin(9600); // Iniciar comunicación serial
// Iniciar pantalla LCD
lcd.init();
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print("BIENVENIDO");
// Iniciar RFID
SPI.begin(); // Inicializar comunicación SPI
rfid.PCD_Init(); // Inicializar el módulo RFID
// Configurar pines del motor 1 como salida
pinMode(IN1_PIN_M1, OUTPUT);
pinMode(IN2_PIN_M1, OUTPUT);
pinMode(IN3_PIN_M1, OUTPUT);
pinMode(IN4_PIN_M1, OUTPUT);
// Configurar pines del motor 2 como salida
pinMode(IN1_PIN_M2, OUTPUT);
pinMode(IN2_PIN_M2, OUTPUT);
pinMode(IN3_PIN_M2, OUTPUT);
pinMode(IN4_PIN_M2, OUTPUT);
// Mostrar plazas disponibles
mostrarPlazasDisponibles();
// Mostrar mensaje inicial para acercar tarjeta
lcd.setCursor(0, 0);
lcd.print("Acerca tu tarjeta");
}
// Bucle principal
void loop() {
// Comprobar si una tarjeta ha sido detectada
if (rfid.PICC_IsNewCardPresent() && rfid.PICC_ReadCardSerial()) {
// Comprobar si es la misma tarjeta
if (comprobarMismaTarjeta(rfid.uid.uidByte)) {
// Si es la misma tarjeta, se considera como una "salida"
if (tarjetaEnUso) {
plazasDisponibles++; // Aumentar el número de plazas disponibles
mostrarPlazasDisponibles(); // Actualizar el número de plazas en la pantalla
abrirPuerta(); // Abrir la puerta
delay(10000); // Esperar 10 segundos antes de cerrar
cerrarPuerta(); // Cerrar la puerta
tarjetaEnUso = false; // La tarjeta ya no está en uso
}
} else {
// Si no es la misma tarjeta, se considera como una "entrada"
if (plazasDisponibles > 0) {
plazasDisponibles--; // Reducir el número de plazas disponibles
mostrarPlazasDisponibles(); // Actualizar el número de plazas en la pantalla
abrirPuerta(); // Abrir la puerta
delay(10000); // Esperar 10 segundos antes de cerrar
cerrarPuerta(); // Cerrar la puerta
tarjetaEnUso = true; // Registrar la tarjeta como en uso
guardarUID(rfid.uid.uidByte); // Guardar el UID de la tarjeta
// Aumentar la velocidad del segundo motor al detectar una nueva tarjeta
velocidadMotor2 = max(1, velocidadMotor2 - 1); // Disminuir el retardo (aumentar la velocidad)
moverMotor2(1, velocidadMotor2); // Mover el segundo motor con la nueva velocidad
} else {
// Si no hay plazas, mostrar mensaje en la pantalla
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Sin plazas");
lcd.setCursor(1, 1);
lcd.print("disponibles");
delay(3000);
mostrarPlazasDisponibles(); // Volver a mostrar plazas
}
}
rfid.PICC_HaltA(); // Detener la lectura de la tarjeta
}
}
// Función para mostrar plazas disponibles en la pantalla
void mostrarPlazasDisponibles() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Quedan ");
lcd.print(plazasDisponibles);
lcd.setCursor(0, 1);
lcd.print("Plazas disponibles");
}
// Función para abrir la puerta
void abrirPuerta() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Abriendo puerta");
for (int i = 0; i < pasosPorRevolucion; i++) {
moverMotor(1); // Girar en una dirección para abrir la puerta
delay(10); // Ajustar el retardo si es necesario
}
puertaAbierta = true;
}
// Función para cerrar la puerta
void cerrarPuerta() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Cerrando puerta");
for (int i = 0; i < pasosPorRevolucion; i++) {
moverMotor(-1); // Girar en la dirección contraria para cerrar la puerta
delay(10); // Ajustar el retardo si es necesario
}
puertaAbierta = false;
}
// Función para mover el motor paso a paso 1 en una dirección específica
void moverMotor(int sentido) {
if (sentido > 0) { // Abrir puerta (sentido horario)
digitalWrite(IN1_PIN_M1, HIGH);
digitalWrite(IN2_PIN_M1, LOW);
digitalWrite(IN3_PIN_M1, LOW);
digitalWrite(IN4_PIN_M1, LOW);
delay(10);
digitalWrite(IN1_PIN_M1, LOW);
digitalWrite(IN2_PIN_M1, HIGH);
delay(10);
digitalWrite(IN2_PIN_M1, LOW);
digitalWrite(IN3_PIN_M1, HIGH);
delay(10);
digitalWrite(IN3_PIN_M1, LOW);
digitalWrite(IN4_PIN_M1, HIGH);
delay(10);
digitalWrite(IN4_PIN_M1, LOW);
} else { // Cerrar puerta (sentido antihorario)
digitalWrite(IN4_PIN_M1, HIGH);
delay(10);
digitalWrite(IN4_PIN_M1, LOW);
digitalWrite(IN3_PIN_M1, HIGH);
delay(10);
digitalWrite(IN3_PIN_M1, LOW);
digitalWrite(IN2_PIN_M1, HIGH);
delay(10);
digitalWrite(IN2_PIN_M1, LOW);
digitalWrite(IN1_PIN_M1, HIGH);
delay(10);
digitalWrite(IN1_PIN_M1, LOW);
}
}
// Función para mover el segundo motor paso a paso en una dirección específica con velocidad ajustable
void moverMotor2(int sentido, int velocidad) {
if (sentido > 0) { // Sentido horario
digitalWrite(IN1_PIN_M2, HIGH);
digitalWrite(IN2_PIN_M2, LOW);
digitalWrite(IN3_PIN_M2, LOW);
digitalWrite(IN4_PIN_M2, LOW);
delay(velocidad);
digitalWrite(IN1_PIN_M2, LOW);
digitalWrite(IN2_PIN_M2, HIGH);
delay(velocidad);
digitalWrite(IN2_PIN_M2, LOW);
digitalWrite(IN3_PIN_M2, HIGH);
delay(velocidad);
digitalWrite(IN3_PIN_M2, LOW);
digitalWrite(IN4_PIN_M2, HIGH);
delay(velocidad);
digitalWrite(IN4_PIN_M2, LOW);
}
}
// Función para comparar el UID de la tarjeta
bool comprobarMismaTarjeta(byte* nuevoUID) {
for (byte i = 0; i < 4; i++) {
if (nuevoUID[i] != ultimoUID[i]) return false;
}
return true;
}
// Función para guardar el UID de la última tarjeta
void guardarUID(byte* nuevoUID) {
for (byte i = 0; i < 4; i++) {
ultimoUID[i] = nuevoUID[i];
}
}