Guía Completa del Módulo RFID RC522 con Arduino UNO: Comunicación Inalámbrica y Control de Acceso

La identificación por radiofrecuencia (RFID) es un conjunto de tecnologías diseñadas para leer etiquetas (tags) a distancia de forma inalámbrica. Los lectores RFID pueden ser conectados a un autómata o procesador como Arduino. El módulo RC522 es un módulo RFID popular utilizado para la comunicación e identificación inalámbrica, funcionando a 13.56 MHz y comunicándose con un microcontrolador utilizando el protocolo SPI. Este módulo versátil es perfecto para proyectos que requieren comunicación e identificación inalámbrica, permitiendo tanto leer como escribir etiquetas RFID utilizando la tecnología MIFARE. Hace unos meses, pude comprobar con mis propios ojos cómo esta tecnología se usa en la tienda de deportes Decathlon al lado de mi casa, en una caja donde depositas todos los artículos y automáticamente, como por arte de magia, aparecen todos los productos en la lista. Y qué mejor manera de conocer cómo funciona algo que montarlo por ti mismo.

Diagrama de bloques de un sistema RFID

¿Qué es el RFID y cómo funciona?

El RFID (Identificador por radiofrecuencia) es un conjunto de tecnologías inalámbricas diseñadas para obtener información almacenada en un dispositivo denominado etiqueta (tag). El lector (transceptor) es en realidad un emisor-receptor que, en primer lugar, emite una señal para iniciar la comunicación con las etiquetas (transpondedores). Esta señal es captada por las etiquetas dentro del alcance, las cuales responden transmitiendo la información que almacenada, finalmente captada y decodificada por el lector RFID.

Las etiquetas RFID están disponibles en una gran variedad de formatos, tales como pegatinas adheribles, tarjetas, llaveros, pueden integrarse en un determinado producto o, incluso, insertarse bajo la piel en un animal o humano.

Los RFID son ampliamente empleados, por ejemplo, en sistemas de alarma, aplicaciones comerciales en sustitución de códigos de barras, cerraduras electrónicas, sistemas de pago, tarjetas personales, control de accesos a recintos como gimnasios o piscinas, fichaje en empresas, entre otras muchas aplicaciones. En nuestros proyectos de electrónica con Arduino podemos usar el RFID, por ejemplo, en aplicaciones comerciales para mostrar en una pantalla los datos al acercar un producto, cambiar la luz o iluminación, abrir una puerta con una tarjeta personal, o hacer que un robot se comporte de forma distinta pasándole una tarjeta.

Alimentación y Comunicación Inalámbrica

Algo curioso es cómo funciona un sistema de RFID, sobre todo en el tema de alimentación. La alimentación del lector RFID y de la etiqueta RFID es diferente. Un módulo como el RC522 debe estar conectado a la red eléctrica para funcionar. Las típicas pegatinas RFID que van en muchos productos no tienen ninguna batería o fuente de alimentación. Al contrario de lo que ocurre con los infrarrojos, los dispositivos basados en RFID no tienen que tener visión directa. Cuando esto sucede, el chip alimentado es capaz de enviar la información almacenada en la etiqueta RFID a través de la radiofrecuencia.

Un sistema RFID puede utilizar varias frecuencias dentro del espectro de radiofrecuencia. Las ondas de radio no se comportan igual a todas las frecuencias del espectro radioeléctrico. Sin embargo, el rango de alcance de la baja frecuencia está limitado a unos centímetros. NFC (del inglés Near-Field Communications) es una tecnología de corto alcance que forma parte de las tecnologías RFID de alta frecuencia. Los sistemas RFID basados en la ultra alta frecuencia o UHF (del inglés Ultra High Frequency) generalmente ofrecen un alcance mayor que los tipos LF y HF.

El RFID puede operar en cuatro bandas de frecuencia, siendo la más frecuente 13.56 MHz:

  • Baja frecuencia 125-134.2 kHz: Control de animales, llaves de automóviles…
  • Alta frecuencia 13.56 MHz: Control de accesos, control de artículos en tiendas…
  • Ultra alta frecuencia (UHF) 868 - 956 GHz
  • Microondas, 2.45 GHz

Existen etiquetas RFID de solo lectura, es decir, en las que la información que contienen es grabada durante su fabricación y no puede modificarse, y etiquetas de lectura y escritura, en las que podemos sobreescribir la información de la etiqueta.

Respecto a la alimentación, existen etiquetas RFID activas que disponen de su propia fuente de energía (por ejemplo, una batería). El rango de lectura puede ser de 10m a 100m. Por contra, las etiquetas RFID pasivas obtienen su energía por inducción de la onda electromagnética emitida por el lector. Por lo tanto, no requieren fuente de alimentación. Sin embargo, el alcance de lectura se reduce a unos centímetros.

Espectro de frecuencias RFID

El Módulo Lector RFID RC522

El módulo lector RFID RC522 está basado en el circuito integrado MFRC522 de la empresa NXP. Normalmente viene integrado en un módulo cuyo coste varía dependiendo de la tienda online donde lo adquieras. Podemos encontrar kits que incluyen el MFRC522, con una tarjeta y un llavero MIFARE CLASSIC S50 por precios muy asequibles. Si lo que queremos son más etiquetas receptoras podemos encontrar tarjetas o llaveros por unos céntimos cada una, o etiquetas adhesivas por unos céntimos.

El lector MFRC522 opera en la frecuencia de 13.56MHz y tiene una distancia de lectura de 0 a 60mm. El módulo RC522 tiene un alcance máximo de 5 cm. Algo muy interesante es que este módulo viene con un pin de interrupción muy útil.

Características del Módulo RC522

  • Modelo: MF522-ED.
  • Voltaje de operación: 2.5V a 3.3V. El voltaje de operación es de 2,5V a 3,3V. No conectes el pin VCC al pin de 5V de cualquier placa ¡Esto puede hacer que el módulo se rompa! Conecta el pin VCC al pin de 3,3V de Arduino y el pin GND al pin GND de Arduino.
  • Corriente de operación: 13-26mA a 3.3V.
  • Corriente máx. VCC: pin de alimentación del lector RFID RC522.
  • Isb de stand by: 10-13mA a 3.3V.
  • Ism de sleep-mode: <80uA.
  • Im máxima: 30mA.
  • Frecuencia de operación: 13.56MHz (Banda ISM de 13,56 MHz).
  • Distancia de lectura: 0 a 60mm.
  • Protocolo de comunicación: SPI/I2C/UART. La comunicación entre Arduino y el lector RFID RC522 es bastante compleja a nivel de programación.
  • Velocidad de datos máxima: 10Mbit/s.
  • Máxima velocidad de SPI: 10Mbit/s.
  • Dimensiones: 40 x 60 mm.
  • Temperatura de operación: -20 a 80ºC.
  • Humedad de operación: 5%-95%.
  • Incluye pines, llavero y tarjeta.

Módulo RFID RC522 con tarjeta y llavero

Pines del Módulo RC522

  • VCC: pin de alimentación del lector RFID RC522. Admite un voltaje de alimentación entre 2,5V y 3,3V.
  • RST: es un pin para encender y apagar el módulo. Mientras el pin esté en estado LOW se mantendrá apagado sin apenas consumir. Cuando el estado cambia a HIGH el RC522 se reinicia. El pin RST del RC522 se puede conectar a cualquier pin de Arduino; en mi caso, lo he conectado al pin 9.
  • GND: pin de tierra o GND.
  • IRQ: pin de interrupción que alerta al microcontrolador cuando una etiqueta RFID se acerca al lector RFID RC522.
  • MISO/SCL/TX: este pin tiene tres funciones. Cuando la interfaz SPI está habilitada funciona como salida de esclavo y entrada de máster.

Conexión con Arduino UNO

La conexión es sencilla. Simplemente alimentamos el módulo desde Arduino mediante 3.3V y GND. Por otro lado, conectamos los pines del bus SPI a los correspondientes de Arduino.

La conexión de los pines SPI dependerá de la placa que estés utilizando. La conexión vista desde el lado de Arduino quedaría así:

  • VCC: Conectar al pin 3.3V de Arduino.
  • RST: Conectar a un pin digital de Arduino (ej. Pin 9).
  • GND: Conectar al pin GND de Arduino.
  • SPI (MOSI, SCK, MISO): Conectar a los pines SPI correspondientes de Arduino UNO (Pin 11 para MOSI, Pin 13 para SCK, Pin 12 para MISO).
  • SDA/RX: No se utiliza en la configuración SPI.

Verificar que vuestra placa es tolerante a un bus de 5V antes de conectarla a Arduino. Si no, tendréis que usar un adaptador de nivel lógico.

Esquema de conexión RC522 Arduino UNO

Pines SPI en Arduino UNO

Los pines SPI indicados son válidos para los modelos de Arduino Uno, Nano y Mini Pro. Para otros modelos de Arduino, consultar el esquema de patillaje correspondiente.

  • MOSI (Master Out Slave In): Pin digital 11 en Arduino UNO.
  • SCK (Serial Clock): Pin digital 13 en Arduino UNO.
  • MISO (Master In Slave Out): Pin digital 12 en Arduino UNO.
  • SS (Slave Select) / CS (Chip Select): Este pin se utiliza para seleccionar el dispositivo SPI con el que se quiere comunicar. En el caso del RC522, se puede conectar a cualquier pin digital disponible, por ejemplo, el pin 10 de Arduino UNO.

Programación con la Librería MFRC522

Para realizar la lectura del RC522 usaremos la librería desarrollada por Miguel Balboa, disponible en este enlace. La librería proporciona ejemplos de código, que resulta aconsejable revisar. Esta librería está programada y mantenida por Miguel Balboa y es una de las más populares para programar un lector RFID RC522.

Lectura de Datos de una Etiqueta RFID

Este programa no escribe ningún dato en la etiqueta RFID. El código que se abre es el siguiente. Carga el código a la placa, abre el monitor serie y pasa la tarjeta que viene con el lector RFID RC522. Tienes que dejar la tarjeta junto al lector RFID RC522 hasta que se muestre toda la información por el monitor serie. El código de ejemplo proporcionado mostrará el ID/UID, tipo y cualquier bloque de datos que pueda leer.

#include <SPI.h>#include <MFRC522.h>#define SS_PIN 10#define RST_PIN 9MFRC522 mfrc522(SS_PIN, RST_PIN);void setup() { Serial.begin(9600); while (!Serial); // Espera a que el puerto serie se inicialice SPI.begin(); // Inicializa el bus SPI mfrc522.PCD_Init(); // Inicializa el módulo MFRC522 Serial.println(F("Escanee su tarjeta o llavero RFID")); Serial.println(F("Para leer su UID:"));}void loop() { // Busca nuevas tarjetas if ( ! mfrc522.PICC_IsNewCardPresent()) { return; } // Selecciona una tarjeta if ( ! mfrc522.PICC_ReadCardSerial()) { return; } // Muestra UID de la tarjeta Serial.print(F("Tarjeta detectada: ")); for (byte i = 0; i < mfrc522.uid.size; i++) { Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "); Serial.print(mfrc522.uid.uidByte[i], HEX); } Serial.println(); // Muestra el tipo de tarjeta Serial.print(F("Tipo de tarjeta: ")); MFRC522::PICC_Type piccType = mfrc522.PICC_GetType(mfrc522.uid.uidByte[0]); Serial.println(mfrc522.PICC_GetTypeName(piccType)); // Opcional: Leer y mostrar datos de los bloques (para tarjetas MIFARE Classic) // Esto requiere autenticación con claves // for (byte sector = 0; sector < mfrc522.size; sector++) { // if (mfrc522.PICC_IsNewCardPresent()) { // if (mfrc522.PICC_ReadCardSerial()) { // MFRC522::PICC_Type piccType = mfrc522.PICC_GetType(mfrc522.uid.uidByte[0]); // if (piccType == MFRC522::PICC_TYPE_MIFARE_CLASSIC) { // // Autenticar sector // byte blockAddr = sector * 4; // Primer bloque del sector // byte keyA[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; // Clave A por defecto // if (mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, blockAddr, keyA, mfrc522.uid.uidByte)) { // byte buffer[16]; // if (mfrc522.MIFARE_Read(blockAddr, buffer, &data)) { // Serial.print(F("Bloque ")); // Serial.print(blockAddr); // Serial.print(F(": ")); // for (byte i = 0; i < 16; i++) { // Serial.print(buffer[i] < 0x10 ? " 0" : " "); // Serial.print(buffer[i], HEX); // } // Serial.println(); // } // } // } // } // } // } delay(4000); // Espera 4 segundos antes de la siguiente lectura}

Verificar que vuestra placa es tolerante a un bus de 5V antes de conectarla a Arduino.

Para ver la salida, usa "Herramientas", "Monitor Serie" de la IDE (presiona Ctrl+Shft+M). El monitor serie mostrará el UID, tipo y cualquier dato que pueda leer.

Escritura de Datos y Cambio de Claves

El módulo RC522 permite tanto leer como escribir etiquetas RFID. Para escribir datos en una etiqueta RFID, puedes usar la función PICC_Write en la biblioteca MFRC522.

Las tarjetas o etiquetas RFID que utiliza el lector RC522 tienen una memoria de 1K organizada en 16 sectores (del 0 al 15). Cada sector se divide en 4 bloques (del 0 al 3). Utilizan la tecnología MIFARE Classics. De estos 4 bloques de cada sector, solo se pueden utilizar 3 bloques para almacenar memoria. Los 16 bytes del último bloque se utilizan para guardar las claves de cifrado y los permisos para acceder a ese sector. Dentro de este bloque, los 16 bytes que pertenecen al trailer se dividen en dos claves para cifrar el contenido (Key A y Key B) que ocupan 6 bytes cada una, y 3 bytes para establecer las condiciones y permisos de acceso al sector (Access Conditions).

Para cifrar el contenido se puede utilizar o la clave Key A o la clave Key B. Por supuesto, para que todo funcione correctamente, el lector necesita conocer la clave que se está utilizando.

El problema que existe actualmente es que la seguridad a través de este sistema de cifrado presenta deficiencias. No hace falta hacer una gran inversión para hackear MIFARE.

Reescribiendo Claves de Cifrado

El proceso de reescribir las claves de cifrado se hace realmente en la función cambiarKeys(). Lo primero que hacemos dentro de esta función es calcular el bloque Trailer con una sencilla fórmula: multiplicas el sector por 4 y sumas 3. Esto te da el último bloque del sector. Lo siguiente es comprobar que realmente las claves Key-A y Key-B actuales son válidas. Eso se hace llamando a la función PCD_Authenticate() de la clase MFRC522. Esta función es importante, ya que la utilizaremos para leer cualquier bloque de la tarjeta. Por último, hay que escribir las nuevas claves de cifrado en el bloque Trailer del sector correspondiente. El programa está esperando a que acerques una tarjeta al lector RFID RC522. Eso quiere decir que se han actualizado las claves de cifrado. Y una vez cambiadas las claves, ya podemos trabajar con más seguridad.

El siguiente código cambia las claves Key-A y Key-B en el sector indicado por la variable sector. En este caso, es el sector 15.

// ... (código anterior) ...void cambiarKeys(byte sector) { byte blockAddr = sector * 4 + 3; // Bloque Trailer del sector byte keyA[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; // Nueva Clave A byte keyB[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; // Nueva Clave B // Autenticar con la clave actual para poder escribir if (mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, blockAddr, keyA, mfrc522.uid.uidByte)) { byte buffer[18]; // 16 bytes para datos + 2 bytes de control buffer[0] = 0xFF; buffer[1] = 0xFF; buffer[2] = 0xFF; buffer[3] = 0xFF; buffer[4] = 0xFF; buffer[5] = 0xFF; // Nueva Key A buffer[6] = 0x00; buffer[7] = 0x00; buffer[8] = 0x00; // Control de acceso (ejemplo) buffer[9] = 0x00; buffer[10] = 0x00; buffer[11] = 0x00; // Control de acceso (ejemplo) buffer[12] = 0xFF; buffer[13] = 0xFF; buffer[14] = 0xFF; buffer[15] = 0xFF; buffer[16] = 0xFF; buffer[17] = 0xFF; // Nueva Key B if (mfrc522.MIFARE_Write(blockAddr, buffer, 18) == MFRC522::STATUS_OK) { Serial.println(F("Claves de cifrado actualizadas correctamente.")); } else { Serial.println(F("Error al escribir las nuevas claves.")); } } else { Serial.println(F("Error de autenticación con la clave actual.")); } mfrc522.PICC_HaltA(); // Detiene la comunicación con la tarjeta}// ... (resto del código) ...

Importante: Una vez actualices las claves de cifrado, estos datos se deben modificar.

Simulación de Tarjetas de Transporte Recargables

La idea en esta última parte de este tutorial es simular las típicas tarjetas de transporte público que pueden ser recargadas con un número de viajes para gastarlas en el autobús o tranvía. Esta es la típica tarjeta que te dan.

El bloque 0 del sector 0 contiene el UID, un identificador único que MIFARE asigna a cada etiqueta RFID.

Para simular una tarjeta de transporte, podemos utilizar un bloque específico (por ejemplo, dentro del sector 15) para almacenar el número de viajes. El byte 0 de este bloque se utilizará para almacenar el número de viajes que tiene la tarjeta.

Código de Recarga de Viajes

// ... (código anterior) ...void recargarViajes(byte sector, byte bloque, int viajesAAgregar) { byte blockAddr = bloque; int viajesActuales = 0; // Autenticar el sector byte keyA[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; // Clave A por defecto if (mfrc522.PICC_IsNewCardPresent()) { if (mfrc522.PICC_ReadCardSerial()) { if (mfrc522.PICC_GetType(mfrc522.uid.uidByte[0]) == MFRC522::PICC_TYPE_MIFARE_CLASSIC) { if (mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, sector * 4, keyA, mfrc522.uid.uidByte)) { byte buffer[16]; if (mfrc522.MIFARE_Read(blockAddr, buffer, &data)) { viajesActuales = buffer[0]; // El primer byte almacena el número de viajes int nuevosViajes = viajesActuales + viajesAAgregar; buffer[0] = (byte)nuevosViajes; // Actualiza el número de viajes if (mfrc522.MIFARE_Write(blockAddr, buffer, 16) == MFRC522::STATUS_OK) { Serial.print(F("Se han añadido ")); Serial.print(viajesAAgregar); Serial.print(F(" viajes. Total: ")); Serial.print(nuevosViajes); Serial.println(F(".")); } else { Serial.println(F("Error al escribir los viajes.")); } } else { Serial.println(F("Error al leer el bloque de viajes.")); } } else { Serial.println(F("Error de autenticación para leer viajes.")); } } } }}// En el setup o loop, llamar a recargarViajes(15, 0, 10); para añadir 10 viajes al bloque 0 del sector 15.

Carga el código a la placa, abre el monitor serie y acerca la tarjeta al lector. Puedes comprobar cómo tenía 0 viajes y se añaden 10 viajes a la tarjeta RFID. Por lo tanto, ya tenemos una tarjeta repleta de viajes.

Código de Consumo de Viajes

El código para ir consumiendo los viajes de uno en uno con el lector RFID es muy parecido (por no decir igual) al código de la recarga.

// ... (código anterior) ...void consumirViaje(byte sector, byte bloque) { byte blockAddr = bloque; int viajesActuales = 0; // Autenticar el sector byte keyA[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; // Clave A por defecto if (mfrc522.PICC_IsNewCardPresent()) { if (mfrc522.PICC_ReadCardSerial()) { if (mfrc522.PICC_GetType(mfrc522.uid.uidByte[0]) == MFRC522::PICC_TYPE_MIFARE_CLASSIC) { if (mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, sector * 4, keyA, mfrc522.uid.uidByte)) { byte buffer[16]; if (mfrc522.MIFARE_Read(blockAddr, buffer, &data)) { viajesActuales = buffer[0]; // El primer byte almacena el número de viajes if (viajesActuales > 0) { viajesActuales--; buffer[0] = (byte)viajesActuales; // Actualiza el número de viajes if (mfrc522.MIFARE_Write(blockAddr, buffer, 16) == MFRC522::STATUS_OK) { Serial.print(F("Viaje consumido. Viajes restantes: ")); Serial.println(viajesActuales); } else { Serial.println(F("Error al escribir los viajes restantes.")); } } else { Serial.println(F("No quedan viajes en la tarjeta.")); } } else { Serial.println(F("Error al leer el bloque de viajes.")); } } else { Serial.println(F("Error de autenticación para leer viajes.")); } } } }}// En el setup o loop, llamar a consumirViaje(15, 0); para consumir un viaje del bloque 0 del sector 15.

Ahora que los viajes están en la tarjeta, hay que gastarlos en el autobús.

🔑🔒Realiza Tu Control De Acceso RFID Con Arduino y Lector RFID-RC522🔐 ✅

Consideraciones de Seguridad

Cuidado en las aplicaciones de seguridad, como cerraduras. Las tarjetas que emplearemos en nuestros proyectos caseros NO SON CONSIDERADAS SEGURAS y no pueden formar parte de un auténtico sistema de seguridad. Las tarjetas MIFARE Classic emplean un sistema de cifrado propio de NXP que, en la actualidad, no es considerado seguro. Lamentablemente, las tarjetas MIFARE Classic emplean el estándar ISO/IEC 14443 Type A, que el foro NFC decidió dejar de soportar en 2014. Por ese motivo, los móviles más modernos no serán capaces de leer este tipo de tarjetas.

NFC: Un Subconjunto del RFID

La tecnología RFID puede tener alcances de 10-100m. Esto tiene importantes consideraciones sobre la seguridad y privacidad. Por ejemplo, imaginemos los peligros de poder leer información de personal o de pagos a estas distancias.

El NFC (Near Field Communication) es un subconjunto de la tecnología RFID que por diseño establece métodos para limitar la distancia de transmisión a menos de 10 cm. El NFC está experimentando un gran desarrollo debido a la inclusión en los smartphones, y posibles formas de pago. Sin embargo, aunque íntimamente relacionados, no hay que confundir RFID y NFC. En particular, no todos los sistemas RFID y NFC serán compatibles, es decir, que no siempre vamos a poder leer una tarjeta RFID con el lector NFC de un smartphone.

En resumen, el módulo RC522 con Arduino UNO es una plataforma potente y accesible para explorar el mundo de la identificación por radiofrecuencia, abriendo un abanico de posibilidades para proyectos interactivos y automatizados.

tags: #rfid #rc522a #arduino #uno