Objetivo y caso de uso
Qué construirás: Un prototipo de hardware independiente que lee etiquetas RFID pasivas, obtiene la hora actual de un reloj de tiempo real (RTC) de precisión y registra el evento (UID y marca de tiempo) en un archivo CSV en una tarjeta microSD.
Por qué es importante / Casos de uso
- Seguimiento de asistencia de estudiantes: Automatiza el registro en el aula mediante toques de tarjetas de identificación, eliminando pasar lista manualmente.
- Registro de acceso a equipos de laboratorio: Proporciona un registro de auditoría sin conexión de quién usó exactamente una máquina específica y a qué hora.
- Reloj de control de empleados: Actúa como un sistema básico de entrada/salida para pequeños talleres donde no hay conectividad de red disponible.
- Auditoría de seguridad: Demuestra los principios fundamentales de los sistemas de control de acceso físico registrando los intentos de entrada en una puerta o portón.
Resultado esperado
- Inicialización exitosa de los componentes del bus SPI compartido (microSD y RFID) y los componentes I2C (RTC).
- Salida del monitor serie mostrando los UID de las tarjetas detectadas y las marcas de tiempo en tiempo real (latencia de lectura < 100ms).
- Creación de un archivo
ATTEND.CSVen la tarjeta microSD que contenga entradas de registro separadas por comas y con el formato adecuado.
Audiencia: Desarrolladores de sistemas embebidos y makers; Nivel: Intermedio
Arquitectura/flujo: Toque de etiqueta RFID → Lector RFID SPI → Microcontrolador → Obtención de marca de tiempo RTC I2C → Adición a CSV en microSD SPI
Nota educativa de validación
Antes de publicar este caso, el contenido pasó la puerta automática de validación de Prometeo con estado PASS. El validador comprobó los bloques de código, la estructura del artículo, los comandos copiables y la coherencia con el catálogo de dispositivos soportados.
Evidencia de validación publicada
- Resultado automático: PASS.
- Estructura parseada: 3 apartados, 5 tablas y 2 bloques de código detectados antes de publicar.
- Código comprobado: 2 Arduino/arduino-cli compile.
- Catálogo soportado: el texto se contrastó contra los perfiles de dispositivo validables de Prometeo y los stacks no soportados bloquean la publicación.
- Hallazgos del informe: sin hallazgos bloqueantes.
Esta validación confirma compatibilidad sintáctica y de herramientas para el material publicado, pero no sustituye la prueba física sobre tu hardware, cableado y entorno exactos.
Nota educativa de seguridad
Este proyecto construye un prototipo educativo destinado al aprendizaje de la integración de hardware, el uso compartido del bus SPI y el registro de datos. No es un sistema de control de acceso seguro. Las etiquetas MIFARE Classic utilizadas comúnmente con el MFRC522 tienen vulnerabilidades criptográficas bien documentadas y
Diagrama de bloques conceptual
Vista de alto nivel: qué entra, qué procesa cada bloque y qué sale del sistema.
Arquitectura funcional
Flujo conceptual de señales y responsabilidades entre bloques del dispositivo.
Ruta de validación
Resumen conceptual de las herramientas usadas para comprobar el material publicado.
Requisitos previos
Para completar con éxito este tutorial, necesitas:
* Comprensión básica de la programación en C++ y la estructura de un sketch de Arduino (setup() y loop()).
* Familiaridad con la comunicación serie y la lectura de las salidas del monitor serie.
* Una computadora con el arduino-cli (Interfaz de línea de comandos de Arduino) instalado y agregado al path de tu sistema.
* Una tarjeta microSD (32GB o menor) formateada en FAT32.
* Un cable USB Tipo-A a Tipo-B para programar y alimentar el Arduino UNO.
Materiales
- Arduino UNO R3 (ATmega328P) + módulo RFID MFRC522 + módulo microSD SPI + RTC DS3231 (Hardware objetivo exacto).
- Etiquetas o tarjetas RFID pasivas (13.56 MHz, compatibles con MFRC522, típicamente MIFARE Classic).
- Protoboard y cables puente premium macho-macho y macho-hembra.
- Tarjeta microSD (formateada en FAT32).
Configuración/Conexión
Este proyecto requiere un cableado cuidadoso porque dos módulos diferentes (el MFRC522 y el módulo microSD) deben compartir el único bus SPI de hardware del Arduino. El bus SPI utiliza líneas compartidas para datos (MOSI, MISO) y reloj (SCK), pero requiere pines de selección de chip (CS) únicos para cada dispositivo. El RTC DS3231 utiliza el bus I2C, que opera en pines separados.
Advertencia de distribución de energía
- MFRC522: Debe ser alimentado con 3.3V. Aplicar 5V al pin VCC del MFRC522 lo dañará.
- Módulo microSD: La mayoría de los módulos microSD estándar para Arduino tienen un regulador de voltaje y un cambiador de nivel integrados. Estos deben ser alimentados con 5V.
- DS3231: Puede operar de manera segura a 5V.
Tablas de cableado
1. Módulo RFID MFRC522 (Bus SPI 1 – Lógica 3.3V)
| Pin MFRC522 | Pin Arduino UNO R3 | Función / Nota |
|---|---|---|
| 3.3V | 3.3V | CRÍTICO: No conectar a 5V |
| RST | Pin 9 | Control de reinicio |
| GND | GND | Tierra común |
| IRQ | Sin conectar | No se usa en esta implementación de sondeo |
| MISO | Pin 12 | Master In Slave Out (SPI compartido) |
| MOSI | Pin 11 | Master Out Slave In (SPI compartido) |
| SCK | Pin 13 | Reloj serie (SPI compartido) |
| SDA (CS) | Pin 10 | Selección de chip para RFID |
2. Módulo de Tarjeta MicroSD (Bus SPI 2 – Lógica 5V)
| Pin MicroSD | Pin Arduino UNO R3 | Función / Nota |
|---|---|---|
| VCC | 5V | Alimentación para el regulador integrado |
| GND | GND | Tierra común |
| MISO | Pin 12 | Master In Slave Out (SPI compartido) |
| MOSI | Pin 11 | Master Out Slave In (SPI compartido) |
| SCK | Pin 13 | Reloj serie (SPI compartido) |
| CS | Pin 4 | Selección de chip para tarjeta SD |
3. Módulo RTC DS3231 (Bus I2C)
| Pin DS3231 | Pin Arduino UNO R3 | Función / Nota |
|---|---|---|
| VCC | 5V | Alimentación |
| GND | GND | Tierra común |
| SDA | Pin A4 | Datos I2C |
| SCL | Pin A5 | Reloj I2C |
Código validado
El proyecto utiliza dos archivos de código separados. El primero es un sketch de utilidad para configurar la fecha y hora actuales en tu RTC DS3231. El segundo es la aplicación principal de registro de asistencia.
Sketch de utilidad: set_rtc_time.ino
Ejecuta este sketch una vez para programar el RTC con la hora de compilación actual de tu computadora.
/*
* Utility: Set DS3231 RTC Time
* This sketch sets the RTC to the date & time the sketch was compiled.
*/
#include <Wire.h>
#include <RTClib.h>
RTC_DS3231 rtc;
void setup() {
Serial.begin(9600);
while (!Serial) { delay(10); } // Wait for serial console
Serial.println("Initializing RTC...");
if (!rtc.begin()) {
Serial.println("Couldn't find RTC. Check wiring.");
while (1) { delay(10); } // Halt
}
if (rtc.lostPower()) {
Serial.println("RTC lost power, let's set the time!");
}
// Set the RTC to the date & time this sketch was compiled
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
Serial.println("RTC time has been successfully updated!");
Serial.print("Current time set to: ");
DateTime now = rtc.now();
Serial.print(now.year(), DEC);
Serial.print('/');
Serial.print(now.month(), DEC);
Serial.print('/');
Serial.print(now.day(), DEC);
Serial.print(" ");
Serial.print(now.hour(), DEC);
Serial.print(':');
Serial.print(now.minute(), DEC);
Serial.print(':');
Serial.println(now.second(), DEC);
Serial.println("You can now flash the main attendance logger sketch.");
}
void loop() {
// Nothing to do here
}
Aplicación principal: attendance_logger.ino
Este es el firmware principal del prototipo. Inicializa el bus SPI compartido, gestiona los pines de selección de chip, sondea tarjetas RFID y añade registros a la tarjeta SD.
Vista pública parcial del archivo validado. El código completo se muestra a miembros y en PDF/Print.
/*
* Project: RFID Attendance SD Logger
* Target: Arduino UNO R3 + MFRC522 + MicroSD + DS3231
* Description: Reads RFID tag UIDs, fetches timestamp from RTC,
* and logs the data to ATTEND.CSV on the SD card.
*/
#include <SPI.h>
#include <MFRC522.h>
#include <SD.h>
#include <Wire.h>
#include <RTClib.h>
// --- Pin Definitions ---
#define SD_CS_PIN 4
#define RFID_CS_PIN 10
#define RFID_RST_PIN 9
// --- Object Instantiation ---
MFRC522 mfrc522(RFID_CS_PIN, RFID_RST_PIN);
RTC_DS3231 rtc;
// --- Global Variables ---
const char* logFileName = "ATTEND.CSV";
void setup() {
// Initialize serial communications
Serial.begin(9600);
while (!Serial) { delay(10); } // Wait for serial port to connect
Serial.println(F("--- RFID Attendance Logger Initialization ---"));
// 1. Initialize SPI Bus
SPI.begin();
// 2. Initialize DS3231 RTC (I2C)
if (!rtc.begin()) {
Serial.println(F("ERROR: Couldn't find RTC."));
while (1) { delay(10); }
}
if (rtc.lostPower()) {
Serial.println(F("WARNING: RTC lost power. Time may be inaccurate."));
} else {
Serial.println(F("RTC initialized successfully."));
}
// 3. Initialize MicroSD Card (SPI)
// Disable RFID SPI temporarily to ensure clean SD init
pinMode(RFID_CS_PIN, OUTPUT);
digitalWrite(RFID_CS_PIN, HIGH);
Serial.print(F("Initializing SD card..."));
if (!SD.begin(SD_CS_PIN)) {
Serial.println(F("ERROR: SD card initialization failed!"));
Serial.println(F("Check formatting (FAT32), wiring, and CS pin."));
while (1) { delay(10); } // Halt if SD fails
}
Serial.println(F("SD card initialized."));
// Write CSV Header if file doesn't exist
if (!SD.exists(logFileName)) {
File dataFile = SD.open(logFileName, FILE_WRITE);
if (dataFile) {
dataFile.println(F("Timestamp,UID"));
dataFile.close();
Serial.println(F("Created new ATTEND.CSV with headers."));
} else {
Serial.println(F("ERROR: Could not create file on SD card."));
}
// .../*
* Project: RFID Attendance SD Logger
* Target: Arduino UNO R3 + MFRC522 + MicroSD + DS3231
* Description: Reads RFID tag UIDs, fetches timestamp from RTC,
* and logs the data to ATTEND.CSV on the SD card.
*/
#include <SPI.h>
#include <MFRC522.h>
#include <SD.h>
#include <Wire.h>
#include <RTClib.h>
// --- Pin Definitions ---
#define SD_CS_PIN 4
#define RFID_CS_PIN 10
#define RFID_RST_PIN 9
// --- Object Instantiation ---
MFRC522 mfrc522(RFID_CS_PIN, RFID_RST_PIN);
RTC_DS3231 rtc;
// --- Global Variables ---
const char* logFileName = "ATTEND.CSV";
void setup() {
// Initialize serial communications
Serial.begin(9600);
while (!Serial) { delay(10); } // Wait for serial port to connect
Serial.println(F("--- RFID Attendance Logger Initialization ---"));
// 1. Initialize SPI Bus
SPI.begin();
// 2. Initialize DS3231 RTC (I2C)
if (!rtc.begin()) {
Serial.println(F("ERROR: Couldn't find RTC."));
while (1) { delay(10); }
}
if (rtc.lostPower()) {
Serial.println(F("WARNING: RTC lost power. Time may be inaccurate."));
} else {
Serial.println(F("RTC initialized successfully."));
}
// 3. Initialize MicroSD Card (SPI)
// Disable RFID SPI temporarily to ensure clean SD init
pinMode(RFID_CS_PIN, OUTPUT);
digitalWrite(RFID_CS_PIN, HIGH);
Serial.print(F("Initializing SD card..."));
if (!SD.begin(SD_CS_PIN)) {
Serial.println(F("ERROR: SD card initialization failed!"));
Serial.println(F("Check formatting (FAT32), wiring, and CS pin."));
while (1) { delay(10); } // Halt if SD fails
}
Serial.println(F("SD card initialized."));
// Write CSV Header if file doesn't exist
if (!SD.exists(logFileName)) {
File dataFile = SD.open(logFileName, FILE_WRITE);
if (dataFile) {
dataFile.println(F("Timestamp,UID"));
dataFile.close();
Serial.println(F("Created new ATTEND.CSV with headers."));
} else {
Serial.println(F("ERROR: Could not create file on SD card."));
}
}
// 4. Initialize MFRC522 RFID (SPI)
mfrc522.PCD_Init();
// Optional: Increase antenna gain if tags are hard to read
// mfrc522.PCD_SetAntennaGain(mfrc522.RxGain_max);
Serial.println(F("MFRC522 initialized successfully."));
Serial.println(F("--- System Ready. Waiting for RFID tags ---"));
}
void loop() {
// Look for new RFID cards
if (!mfrc522.PICC_IsNewCardPresent()) {
return;
}
// Select one of the cards
if (!mfrc522.PICC_ReadCardSerial()) {
return;
}
// Get Current Time from RTC
DateTime now = rtc.now();
// Format Timestamp: YYYY-MM-DD HH:MM:SS
char timeBuffer[20];
snprintf(timeBuffer, sizeof(timeBuffer), "%04d-%02d-%02d %02d:%02d:%02d",
now.year(), now.month(), now.day(),
now.hour(), now.minute(), now.second());
// Format UID to Hex String
String uidString = "";
for (byte i = 0; i < mfrc522.uid.size; i++) {
if (mfrc522.uid.uidByte[i] < 0x10) {
uidString += "0";
}
uidString += String(mfrc522.uid.uidByte[i], HEX);
}
uidString.toUpperCase();
// Print to Serial Monitor
Serial.print(F("Scanned: "));
Serial.print(timeBuffer);
Serial.print(F(" | UID: "));
Serial.println(uidString);
// Log to SD Card
File dataFile = SD.open(logFileName, FILE_WRITE);
if (dataFile) {
dataFile.print(timeBuffer);
dataFile.print(F(","));
dataFile.println(uidString);
dataFile.close();
Serial.println(F(" -> Logged to SD card successfully."));
} else {
Serial.println(F(" -> ERROR: Failed to open ATTEND.CSV for writing."));
}
// Halt PICC to prevent reading the same card repeatedly in a single tap
mfrc522.PICC_HaltA();
// Stop encryption on PCD
mfrc522.PCD_StopCrypto1();
// Brief delay to prevent rapid-fire multiple reads
delay(1000);
}
Comandos de compilación/flasheo/ejecución
Utiliza arduino-cli para compilar y subir tu código.
Tabla de referencia de comandos
| Tarea | Comando |
|---|---|
| Actualizar índice de core | arduino-cli core update-index |
| Instalar core AVR | arduino-cli core install arduino:avr |
| Instalar dependencias | arduino-cli lib install "MFRC522" "RTClib" "SD" |
| Compilar sketch | arduino-cli compile --fqbn arduino:avr:uno <Sketch_Folder> |
| Subir al UNO | arduino-cli upload --fqbn arduino:avr:uno --port <PORT> <Sketch_Folder> |
| Monitor serie | arduino-cli monitor --port <PORT> --config baudrate=9600 |
Flujo de trabajo numerado
- Encuentra tu puerto: Conecta el Arduino UNO a tu computadora. Ejecuta
arduino-cli board listpara identificar el<PORT>(ej.,COM3en Windows,/dev/ttyACM0en Linux). - Instala las bibliotecas: Asegúrate de que las bibliotecas de terceros requeridas estén instaladas:
arduino-cli lib install "MFRC522" "RTClib" "SD" - Configura la hora del RTC:
- Guarda el primer bloque de código en una carpeta llamada
set_rtc_time. - Compilar:
arduino-cli compile --fqbn arduino:avr:uno set_rtc_time - Subir:
arduino-cli upload --fqbn arduino:avr:uno --port <PORT> set_rtc_time - Monitor:
arduino-cli monitor --port <PORT> --config baudrate=9600para verificar que se configuró la hora.
- Guarda el primer bloque de código en una carpeta llamada
- Flashea el registrador principal:
- Guarda el segundo bloque de código en una carpeta llamada
attendance_logger. - Compilar:
arduino-cli compile --fqbn arduino:avr:uno attendance_logger - Subir:
arduino-cli upload --fqbn arduino:avr:uno --port <PORT> attendance_logger - Monitor:
arduino-cli monitor --port <PORT> --config baudrate=9600para ver el sistema en vivo.
- Guarda el segundo bloque de código en una carpeta llamada
Validación paso a paso
Utiliza estos puntos de control mientras monitoreas la salida serie para asegurarte de que tu prototipo sea completamente funcional.
- Punto de control: Inicialización del RTC
- Acción: Reinicia el Arduino y observa el monitor serie.
- Observación esperada: El monitor imprime «RTC initialized successfully.»
- Condición de éxito: El sistema no se detiene con «ERROR: Couldn’t find RTC.»
- Punto de control: Montaje de la tarjeta SD
- Acción: Continúa observando el monitor serie durante el arranque.
- Observación esperada: El monitor imprime «Initializing SD card…» seguido de «SD card initialized.»
- Condición de éxito: El sistema monta con éxito el sistema de archivos FAT32 y no se detiene.
- Punto de control: Inicialización del módulo RFID
- Acción: Observa los mensajes de arranque finales.
- Observación esperada: El monitor imprime «MFRC522 initialized successfully.» y «— System Ready. Waiting for RFID tags —«.
- Condición de éxito: Ambos dispositivos SPI (SD y RFID) se han inicializado sin causar conflictos en el bus.
- Punto de control: Escaneo y registro de etiquetas
- Acción: Toca la antena del MFRC522 con una etiqueta RFID de 13.56 MHz.
- Observación esperada: El monitor serie muestra «Scanned: [Fecha/Hora] | UID: [Cadena Hexadecimal]» seguido de » -> Logged to SD card successfully.»
- Condición de éxito: El UID coincide con tu tarjeta, la marca de tiempo es precisa y la escritura en la SD reporta éxito.
- Punto de control: Verificación de datos CSV
- Acción: Apaga el Arduino, retira la tarjeta microSD y léela en tu computadora.
- Observación esperada: Existe un archivo llamado
ATTEND.CSV. Al abrirlo, se revela una fila de encabezado (Timestamp,UID) y una fila por cada toque de tarjeta. - Condición de éxito: Los datos están correctamente separados por comas y son legibles para un humano en una aplicación de hoja de cálculo.
Solución de problemas
| Síntoma | Causa probable | Solución |
|---|---|---|
Couldn't find RTC | Problema de cableado I2C. | Verifica que SDA esté en A4 y SCL en A5. Asegúrate de que el módulo tenga 5V y GND. |
SD card initialization failed! | Formato incorrecto o pin CS. | Asegúrate de que la tarjeta SD esté formateada en FAT32 (no exFAT ni NTFS). Verifica que CS esté conectado al Pin 4. |
| La SD falla solo cuando el RFID está conectado | Conflicto MISO SPI (módulos SD económicos). | Algunos módulos SD no liberan la línea MISO cuando su CS está en ALTO. Intenta alimentar el módulo SD desde una fuente de 5V separada o añade un búfer triestado a la línea MISO de la SD. |
| El RFID no detecta tarjetas | Fuente de alimentación o cableado SPI. | Asegúrate de que el VCC del MFRC522 sea 3.3V, NO 5V. Verifica MOSI (11), MISO (12), SCK (13), SDA (10) y RST (9). |
| La marca de tiempo se reinicia a 2000-01-01 | Batería del RTC agotada. | Reemplaza la batería CR2032 en el módulo DS3231 y vuelve a ejecutar el sketch set_rtc_time. |
Mejoras
Una vez que el registrador básico esté funcionando, considera estas mejoras temáticas para un prototipo más robusto:
- Mecanismos de retroalimentación para el usuario:
- Añade un zumbador piezoeléctrico para proporcionar un «pitido» audible tras un escaneo y registro exitosos.
- Integra un LED bicolor (verde para un registro exitoso, rojo para un error de la tarjeta SD) para que el dispositivo pueda usarse sin un monitor serie conectado.
- Gestión e integridad de datos:
- Implementa un sistema de rotación diaria de archivos (ej.,
LOG_1024.CSVpara el 24 de octubre) para evitar que un solo archivo CSV se vuelva demasiado grande para analizarlo rápidamente. - Añade una base de datos de UID conocidos en la memoria flash del Arduino (usando
PROGMEM) para rechazar tarjetas desconocidas y registrar solo usuarios autorizados.
- Implementa un sistema de rotación diaria de archivos (ej.,
- Energía e implementación:
- Añade una rutina de modo de suspensión para apagar los periféricos SPI y poner el ATmega328P a dormir cuando no haya ninguna tarjeta presente, despertando mediante una interrupción de hardware (si usas un módulo RFID diferente que soporte el despertar por IRQ).
Encuentra este producto y/o libros sobre este tema en Amazon
Como afiliado de Amazon, gano con las compras que cumplan los requisitos. Si compras a través de este enlace, ayudas a mantener este proyecto.




