Gracias a la tecnología RFID, se acabaron los días en los que la gente esperaba en largas colas para pagar en el supermercado. Con una solución de caja automática basada en RFID, puedes llenar tu cesta y salir directamente por la puerta. Ya no tendrá que esperar a que alguien haga sonar cada artículo uno por uno; ahora, con la ayuda de las etiquetas RFID adheridas a los artículos, cada artículo de la cesta será detectado y sonará casi al instante.

Para la mayoría de nuestros proyectos Arduino basados en RFID, el módulo lector/grabador RFID RC522 es una gran elección. Es de bajo consumo, bajo coste, muy robusto, fácil de interconectar y extremadamente popular entre los aficionados.

¿Qué es la tecnología RFID y cómo funciona?

Un sistema RFID o de identificación por radiofrecuencia consta de dos componentes principales: una etiqueta adherida al objeto que se desea identificar y un lector que lee la etiqueta.

El lector consta de un módulo de radiofrecuencia y una antena que genera un campo electromagnético de alta frecuencia. Mientras que la etiqueta suele ser un dispositivo pasivo (no tiene batería). Consta de un microchip que almacena y procesa la información, y una antena para recibir y transmitir una señal.

Cuando la etiqueta se acerca al lector, éste genera un campo electromagnético. Esto hace que los electrones se muevan a través de la antena de la etiqueta y, posteriormente, alimenten el chip.

El chip responde enviando su información almacenada al lector en forma de otra señal de radio. Esto se llama retrodispersión. El lector detecta e interpreta esta retrodispersión y envía los datos a un ordenador o microcontrolador.

Visión general del hardware

El módulo RFID RC522 basado en el CI MFRC522 de NXP es una de las opciones de RFID más baratas que se pueden conseguir en Internet. Normalmente viene con una etiqueta de tarjeta RFID y una etiqueta de llavero con 1KB de memoria. Y lo mejor es que puede escribir una etiqueta, lo que significa que puede almacenar cualquier mensaje en ella.

El módulo lector RFID RC522 está diseñado para crear un campo electromagnético de 13,56MHz y comunicarse con las etiquetas RFID (etiquetas estándar ISO 14443A).

El lector puede comunicarse con un microcontrolador a través de un SPI de 4 pines con una velocidad máxima de datos de 10 Mbps. También soporta la comunicación a través de los protocolos I2C y UART.

El módulo RFID RC522 puede ser programado para generar una interrupción, lo que permite al módulo alertarnos cuando una etiqueta se acerca a él, en lugar de preguntar constantemente al módulo “¿Hay una tarjeta cerca?”.

El voltaje de funcionamiento del módulo oscila entre 2,5 y 3,3V, pero la buena noticia es que los pines lógicos son tolerantes a 5 voltios, por lo que podemos conectarlo fácilmente a un Arduino o a cualquier microcontrolador lógico de 5V sin necesidad de utilizar un convertidor de nivel lógico.

Especificaciones técnicas

Aquí están las especificaciones:

Para más detalles, consulte la siguiente hoja de datos.

Pinout del módulo RFID RC522

El módulo RC522 tiene un total de 8 pines que lo conectan con el mundo exterior. Las conexiones son las siguientes:

VCC suministra energía al módulo. Puede ser de 2,5 a 3,3 voltios. Puedes conectarlo a la salida de 3,3V de tu Arduino. Pero recuerda que si lo conectas al pin de 5V probablemente dañarás tu módulo.

RST es una entrada para el reinicio y el apagado. Cuando este pin se pone bajo, el módulo entra en modo de apagado. En el cual el oscilador se apaga y los pines de entrada se desconectan del mundo exterior. Mientras que el módulo se reinicia en el flanco ascendente de la señal.

GND es el pin de tierra y necesita ser conectado al pin GND en el Arduino.

IRQ es un pin de interrupción que avisa al microcontrolador cuando una etiqueta RFID está cerca.

El pin MISO / SCL / Tx actúa como master-in-slave-out cuando la interfaz SPI está habilitada, como reloj serie cuando la interfaz I2C está habilitada y como salida de datos serie cuando la interfaz UART está habilitada.

MOSI (Master Out Slave In) es la entrada SPI al módulo RC522.

SCK (Serial Clock) acepta los pulsos de reloj proporcionados por el maestro del bus SPI, es decir, Arduino.

El pin SS / SDA / Rx actúa como entrada de señal cuando la interfaz SPI está habilitada, como datos serie cuando la interfaz I2C está habilitada y como entrada de datos serie cuando la interfaz UART está habilitada. Este pin se suele marcar encerrando el pin en un cuadrado para que pueda ser utilizado como referencia para identificar otros pines.

Cableado de un módulo RFID RC522 a un Arduino.

Ahora que sabemos todo sobre el módulo, ¡comencemos a conectarlo a nuestro Arduino!

Primero conecta el pin VCC del módulo a 3,3V y el pin GND a tierra en el Arduino. El pin RST se puede conectar a cualquier pin digital del Arduino. En nuestro caso, está conectado al pin digital #5. El pin IRQ se deja sin conectar porque la librería de Arduino que vamos a utilizar no lo soporta.

Ahora nos quedan los pines que se utilizan para la comunicación SPI. Como los módulos RC522 requieren mucha transferencia de datos, darán el mejor rendimiento cuando se conecten a los pines SPI del hardware del microcontrolador.

Ten en cuenta que cada placa Arduino tiene diferentes pines SPI que deben ser conectados en consecuencia. Comprueba la siguiente tabla para una rápida comprensión.

Si estás utilizando un Arduino diferente a las placas mencionadas anteriormente, consulta la documentación oficial del Arduino antes de continuar

Una vez que hayas conectado todo, estarás listo para empezar.

Instalación de la librería

Comunicarse con un módulo RFID RC522 es un montón de trabajo, pero por suerte para nosotros hay una biblioteca llamada MFRC522 library que hace que la lectura y la escritura de etiquetas RFID sea sencilla.

Esta biblioteca no está incluida en el IDE de Arduino, así que tendrás que instalarla primero.

Para instalar la biblioteca navega a Sketch > Incluir Bibliotecas > Gestionar Bibliotecas… Espera a que Library Manager descargue el índice de bibliotecas y actualice la lista de bibliotecas instaladas.

Filtra tu búsqueda escribiendo ‘mfrc522’. Busca la biblioteca de GithubCommunity. Haz clic en esa entrada y luego selecciona Instalar.

Código Arduino – Lectura de una etiqueta RFID

Una vez instalada la librería, abre el submenú Ejemplos y elije MFRC522 > DumpInfo example sketch.

Este sketch sólo lee la etiqueta y muestra la información almacenada en ella, puede ser muy útil antes de probar cualquier etiqueta nueva.

Ve al principio del sketch y asegúrate de que RST_PIN está inicializado correctamente, en nuestro caso estamos usando el pin digital #5 así que cámbialo a 5.

Ahora sube el sketch y abre Serial Monitor. Al acercar el tag al módulo, obtendrás algo como lo siguiente. No muevas el tag hasta que se muestre toda la información.

Muestra toda la información útil sobre la etiqueta, incluyendo el ID único (UID) de la etiqueta, el tamaño de la memoria y la memoria 1K completa.

Mapa de memoria de MIFARE 1K Classic

La memoria de 1K de la etiqueta está organizada en 16 sectores (del 0 al 15). Cada sector se divide a su vez en 4 bloques (bloques 0 a 3). Y cada bloque puede almacenar 16 bytes de datos (de 0 a 15).

16 sectors x 4 blocks x 16 bytes of data = 1024 bytes = 1K memory

Todo el 1K de memoria, junto con los sectores, los bloques y los datos, están resaltado a continuación.

Esta es la representación en 3D de la disposición del mapa de memoria de MIFARE Classic 1K

El último bloque de cada sector se denomina Sector trailer. Contiene información llamada Access Bits que proporcionan acceso de lectura y escritura a los bloques restantes del sector. Esto significa que sólo 3 bloques de cada sector (Bloques #0, #1 y #2) son realmente escribibles, en otras palabras, sólo 48 bytes por sector están disponibles para su uso.

Además, el bloque #0 del sector #0 se denomina Manufacturer Block y contiene los datos del fabricante del CI y el identificador único (UID). El bloque del fabricante está resaltado en rojo.

Advertencia:

Recuerda que sobrescribir el bloque del fabricante es muy arriesgado y puede bloquear la tarjeta permanentemente.

Código Arduino – Escribir una etiqueta RFID

Asumiendo que has leído con éxito una etiqueta RFID, pasaremos a nuestro siguiente experimento. El siguiente sketch demuestra la escritura de datos personalizados en una etiqueta RFID. Antes de comenzar un análisis detallado del mismo, prueba el Sketch.

#include <SPI.h>      //include the SPI bus library
#include <MFRC522.h>  //include the RFID reader library

#define SS_PIN 10  //slave select pin
#define RST_PIN 5  //reset pin

MFRC522 mfrc522(SS_PIN, RST_PIN);  // instatiate a MFRC522 reader object.
MFRC522::MIFARE_Key key;          //create a MIFARE_Key struct named 'key', which will hold the card information

//this is the block number we will write into and then read.
int block=2;  

byte blockcontent[16] = {"Last-Minute-Engg"};  //an array with 16 bytes to be written into one of the 64 card blocks is defined
//byte blockcontent[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};  //all zeros. This can be used to delete a block.

//This array is used for reading out a block.
byte readbackblock[18];

void setup() 
{
    Serial.begin(9600);        // Initialize serial communications with the PC
    SPI.begin();               // Init SPI bus
    mfrc522.PCD_Init();        // Init MFRC522 card (in case you wonder what PCD means: proximity coupling device)
    Serial.println("Scan a MIFARE Classic card");
  
  // Prepare the security key for the read and write functions.
  for (byte i = 0; i < 6; i++) {
    key.keyByte[i] = 0xFF;  //keyByte is defined in the "MIFARE_Key" 'struct' definition in the .h file of the library
  }
}

void loop()
{  
  // Look for new cards
  if ( ! mfrc522.PICC_IsNewCardPresent()) {
    return;
  }
  
  // Select one of the cards
  if ( ! mfrc522.PICC_ReadCardSerial()) 
  {
    return;
  }
    Serial.println("card selected");
         
   //the blockcontent array is written into the card block
   writeBlock(block, blockcontent);
   
   //read the block back
   readBlock(block, readbackblock);
   //uncomment below line if you want to see the entire 1k memory with the block written into it.
   //mfrc522.PICC_DumpToSerial(&(mfrc522.uid));
   
   //print the block contents
   Serial.print("read block: ");
   for (int j=0 ; j<16 ; j++)
   {
     Serial.write (readbackblock[j]);
   }
   Serial.println("");
}



//Write specific block    
int writeBlock(int blockNumber, byte arrayAddress[]) 
{
  //this makes sure that we only write into data blocks. Every 4th block is a trailer block for the access/security info.
  int largestModulo4Number=blockNumber/4*4;
  int trailerBlock=largestModulo4Number+3;//determine trailer block for the sector
  if (blockNumber > 2 && (blockNumber+1)%4 == 0){Serial.print(blockNumber);Serial.println(" is a trailer block:");return 2;}
  Serial.print(blockNumber);
  Serial.println(" is a data block:");
  
  //authentication of the desired block for access
  byte status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, trailerBlock, &key, &(mfrc522.uid));
  if (status != MFRC522::STATUS_OK) {
         Serial.print("PCD_Authenticate() failed: ");
         Serial.println(mfrc522.GetStatusCodeName(status));
         return 3;//return "3" as error message
  }
  
  //writing the block 
  status = mfrc522.MIFARE_Write(blockNumber, arrayAddress, 16);
  //status = mfrc522.MIFARE_Write(9, value1Block, 16);
  if (status != MFRC522::STATUS_OK) {
           Serial.print("MIFARE_Write() failed: ");
           Serial.println(mfrc522.GetStatusCodeName(status));
           return 4;//return "4" as error message
  }
  Serial.println("block was written");
}



//Read specific block
int readBlock(int blockNumber, byte arrayAddress[]) 
{
  int largestModulo4Number=blockNumber/4*4;
  int trailerBlock=largestModulo4Number+3;//determine trailer block for the sector

  //authentication of the desired block for access
  byte status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, trailerBlock, &key, &(mfrc522.uid));

  if (status != MFRC522::STATUS_OK) {
         Serial.print("PCD_Authenticate() failed (read): ");
         Serial.println(mfrc522.GetStatusCodeName(status));
         return 3;//return "3" as error message
  }

//reading a block
byte buffersize = 18;//we need to define a variable with the read buffer size, since the MIFARE_Read method below needs a pointer to the variable that contains the size... 
status = mfrc522.MIFARE_Read(blockNumber, arrayAddress, &buffersize);//&buffersize is a pointer to the buffersize variable; MIFARE_Read requires a pointer instead of just a number
  if (status != MFRC522::STATUS_OK) {
          Serial.print("MIFARE_read() failed: ");
          Serial.println(mfrc522.GetStatusCodeName(status));
          return 4;//return "4" as error message
  }
  Serial.println("block was read");
}

La salida en el monitor serie se verá algo así

Explicación del código:

El sketch comienza incluyendo las librerías MFRC522 y SPI, definiendo los pines de Arduino a los que se conecta el RC522, e instanciando el objeto lector MFRC522.

#include <SPI.h>//include the SPI bus library
#include <MFRC522.h>//include the RFID reader library

#define SS_PIN 10  //slave select pin
#define RST_PIN 5  //reset pin
MFRC522 mfrc522(SS_PIN, RST_PIN);        // instatiate a MFRC522 reader object.
MFRC522::MIFARE_Key key;//create a MIFARE_Key struct named 'key', which will hold the card information

Después de esto definimos un bloque en el que vamos a almacenar nuestros datos. Aquí se selecciona el sector #0 bloque #2. Recuerda que nunca debes seleccionar el bloque #3 de ningún sector. Escribir en un bloque ‘Sector Trailer’ puede inutilizar el bloque.

//this is the block number we will write into and then read.
int block=2;

A continuación, definimos un array de 16 bytes llamado blockcontent, que contiene el mensaje que queremos escribir en el bloque. Cuando quieras borrar un bloque puedes poner blockcontent a 0.

byte blockcontent[16] = {"Last-Minute-Engg"};  //an array with 16 bytes to be written into one of the 64 card blocks is defined
//byte blockcontent[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};  //all zeros. This can be used to delete a block.

A continuación, definimos un array de 18 bytes llamado readbackblock. Lo utilizaremos para leer el contenido escrito. Espera… ¿18 bytes? ¿No deberían ser 16 bytes? La respuesta es No. El método MIFARE_Read de la librería MFRC522 requiere un buffer de al menos 18 bytes que contenga 16 bytes de un bloque.

//This array is used for reading out a block.
byte readbackblock[18];

En la configuración, inicializamos la comunicación serie, la biblioteca SPI y el objeto MFRC522. También preparamos una clave de seguridad para las operaciones de lectura y escritura. Aquí los seis bytes de la clave se establecen en 0xFF.

Recuerda que las tarjetas más nuevas tienen los seis bytes de la clave establecidos en 0xFF. Si tienes una tarjeta que ha sido programada por otra persona, necesitarás conocer la clave para poder acceder a la tarjeta. Guarda esa clave en una variable llamada clave.

Serial.begin(9600);        // Initialize serial communications with the PC
SPI.begin();               // Init SPI bus
mfrc522.PCD_Init();        // Init MFRC522 card (in case you wonder what PCD means: proximity coupling device)
Serial.println("Scan a MIFARE Classic card");
  
// Prepare the security key for the read and write functions.
for (byte i = 0; i < 6; i++) {
   key.keyByte[i] = 0xFF;  //keyByte is defined in the "MIFARE_Key" 'struct' definition in the .h file of the library

En el bucle, buscamos la nueva tarjeta y la seleccionamos para escribir y leer

// Look for new cards
  if ( ! mfrc522.PICC_IsNewCardPresent()) {
    return;
  }
  
  // Select one of the cards
  if ( ! mfrc522.PICC_ReadCardSerial()) 
  {
    return;
  }
  Serial.println("card selected");

Escribir bloques es ahora mucho más fácil. Sólo tenemos que llamar a una función personalizada llamada writeBlock() que toma dos parámetros: un número de bloque en el que nos interesa escribir los datos y los propios datos.

//the blockcontent array is written into the card block
writeBlock(block, blockcontent);

Para comprobar si la operación de escritura ha tenido éxito, leemos el contenido del bloque. Para esto usamos una función personalizada llamada readBlock() que de nuevo toma dos parámetros – el número de bloque y el array para almacenar el contenido del bloque. Si quieres ver toda la memoria de 1k puedes llamar a la función PICC_DumpToSerial().

//read the block back
readBlock(block, readbackblock);
//uncomment below line if you want to see the entire 1k memory with the block written into it.
//mfrc522.PICC_DumpToSerial(&(mfrc522.uid));

Por último, imprimimos el contenido de readbackblock en el monitor serie utilizando un bucle for.

//print the block contents
 Serial.print("read block: ");
 for (int j=0 ; j<16 ; j++)
 {
   Serial.write (readbackblock[j]);
 }
 Serial.println("");

Proyecto Arduino – Sistema de control de acceso a puertas basado en RFID

Vamos a crear rápidamente un proyecto Arduino para demostrar cómo un simple módulo lector RC522 RFID puede ser utilizado para construir un sistema de control de acceso de puertas.

El programa que se muestra a continuación escanea el ID único de cada etiqueta RFID. Si el UID de la etiqueta coincide con un valor predefinido (etiqueta maestra) que está almacenado en la memoria del Arduino, se permite el acceso. Para las etiquetas desconocidas, el acceso es denegado. Es increíble. ¿cierto?

Este es el aspecto de la salida.

Por supuesto, este proyecto puede ampliarse para abrir puertas, conmutar relés, iluminar LEDs o cualquier otra cosa que se te ocurra.

Cableado

Antes de cargar el código y empezar a escanear las etiquetas, veamos el cableado del proyecto.

Probemos el siguiente sketch:

#include <SPI.h>
#include <MFRC522.h>
#include <LiquidCrystal.h>

#define RST_PIN 9
#define SS_PIN 10

byte readCard[4];
String MasterTag = "20C3935E";	// REPLACE this Tag ID with your Tag ID!!!
String tagID = "";

// Create instances
MFRC522 mfrc522(SS_PIN, RST_PIN);
LiquidCrystal lcd(7, 6, 5, 4, 3, 2); //Parameters: (rs, enable, d4, d5, d6, d7) 

void setup() 
{
  // Initiating
  SPI.begin(); // SPI bus
  mfrc522.PCD_Init(); // MFRC522
  lcd.begin(16, 2); // LCD screen

  lcd.clear();
  lcd.print(" Access Control ");
  lcd.setCursor(0, 1);
  lcd.print("Scan Your Card>>");
}

void loop() 
{
  
  //Wait until new tag is available
  while (getID()) 
  {
    lcd.clear();
    lcd.setCursor(0, 0);
    
    if (tagID == MasterTag) 
    {
      
      lcd.print(" Access Granted!");
      // You can write any code here like opening doors, switching on a relay, lighting up an LED, or anything else you can think of.
    }
    else
    {
      lcd.print(" Access Denied!");
    }
    
      lcd.setCursor(0, 1);
      lcd.print(" ID : ");
      lcd.print(tagID);
      
    delay(2000);

    lcd.clear();
    lcd.print(" Access Control ");
    lcd.setCursor(0, 1);
    lcd.print("Scan Your Card>>");
  }
}

//Read new tag if available
boolean getID() 
{
  // Getting ready for Reading PICCs
  if ( ! mfrc522.PICC_IsNewCardPresent()) { //If a new PICC placed to RFID reader continue
  return false;
  }
  if ( ! mfrc522.PICC_ReadCardSerial()) { //Since a PICC placed get Serial and continue
  return false;
  }
  tagID = "";
  for ( uint8_t i = 0; i < 4; i++) { // The MIFARE PICCs that we use have 4 byte UID
  //readCard[i] = mfrc522.uid.uidByte[i];
  tagID.concat(String(mfrc522.uid.uidByte[i], HEX)); // Adds the 4 bytes in a single String variable
  }
  tagID.toUpperCase();
  mfrc522.PICC_HaltA(); // Stop reading
  return true;
}

Explicación del código:

El programa es bastante sencillo. Al principio incluimos las librerías necesarias, definimos los pines de Arduino, creamos instancias de los objetos LCD y MFRC522 y definimos la etiqueta maestra

#include <SPI.h>
#include <MFRC522.h>
#include <LiquidCrystal.h>

#define RST_PIN 9
#define SS_PIN 10

byte readCard[4];
String MasterTag = "20C3935E";	// REPLACE this Tag ID with your Tag ID!!!
String tagID = "";

// Create instances
MFRC522 mfrc522(SS_PIN, RST_PIN);
LiquidCrystal lcd(7, 6, 5, 4, 3, 2); //Parameters: (rs, enable, d4, d5, d6, d7)

En la configuración, inicializamos la interfaz SPI, el objeto MFRC522 y el LCD. Después imprimimos el mensaje de bienvenida en el LCD

void setup() 
{
  // Initiating
  SPI.begin(); // SPI bus
  mfrc522.PCD_Init(); // MFRC522
  lcd.begin(16, 2); // LCD screen

  lcd.clear();
  lcd.print(" Access Control ");
  lcd.setCursor(0, 1);
  lcd.print("Scan Your Card>>");
}

En el bucle, esperamos hasta que se escanee la nueva etiqueta. Tras el escaneo, comparamos el ID de la etiqueta desconocida con el ID maestro. Si ambos coinciden, se concede el acceso, si no, se deniega.

void loop() 
{
  
  //Wait until new tag is available
  while (getID()) 
  {
    lcd.clear();
    lcd.setCursor(0, 0);
    
    if (tagID == MasterTag) 
    {
      
      lcd.print(" Access Granted!");
      // You can write any code here like opening doors, switching on a relay, lighting up an LED, or anything else you can think of.
    }
    else
    {
      lcd.print(" Access Denied!");
    }
      lcd.setCursor(0, 1);
      lcd.print(" ID : ");
      lcd.print(tagID);
      
    delay(2000);

    lcd.clear();
    lcd.print(" Access Control ");
    lcd.setCursor(0, 1);
    lcd.print("Scan Your Card>>");
  }
}

El código más importante aquí es la función personalizada getID(). Una vez que escanea la nueva tarjeta, dentro del bucle for convierte los 4 bytes del uid en una cadena y los concatena para formar una sola cadena

boolean getID() 
{
  // Getting ready for Reading PICCs
  if ( ! mfrc522.PICC_IsNewCardPresent()) { //If a new PICC placed to RFID reader continue
  return false;
  }
  if ( ! mfrc522.PICC_ReadCardSerial()) { //Since a PICC placed get Serial and continue
  return false;
  }
  tagID = "";
  for ( uint8_t i = 0; i < 4; i++) { // The MIFARE PICCs that we use have 4 byte UID
  //readCard[i] = mfrc522.uid.uidByte[i];
  tagID.concat(String(mfrc522.uid.uidByte[i], HEX)); // Adds the 4 bytes in a single String variable
  }
  tagID.toUpperCase();
  mfrc522.PICC_HaltA(); // Stop reading
  return true;
}

What is RFID? How it Works?Interface RC522 RFID Module with Arduino. Last Minute Engineers. https://lastminuteengineers.com/how-rfid-works-rc522-arduino-tutorial/