arduino-rfid-mifare-rc522

Lectura de tarjetas RFID con Arduino y lector MIFARE RC522

¿Qué es el RFID?

El RFID (Identificador por radiofrecuencia) 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.

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 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

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.

Precio

En el mundo de la electrónica doméstica y los proyectos de Arduino es muy común el lector/grabador MFRC522.

Podemos encontrar kits que incluyen el MFRC522, con una tarjeta y un llavero MIFARE CLASSIC S50 por 1.45€, buscando en vendedores internacionales en eBay o AliExpress.

arduino-rfid-rc522-componente

Si lo que queremos son más etiquetas receptoras podemos encontrar tarjetas o llaveros por unos 0.25€ cada una, o etiquetas adhesivas por unos 0.15€.

¿Cómo funciona el RFID?

El RFID es un conjunto de tecnologías inalámbricas diseñadas para obtener una 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 cuál responden transmitiendo la información que almacenada que, finalmente, es captada y decodificada por el lector RFID.

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 sólo 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 sobreeescribir 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 tanto, no requieren fuente de alimentación. Sin embargo el alcance de lectura se reduce a unos centímetros.

El NFC, un subconjunto del RFID

La tecnología RFID puede tener alcances de 10-100m. Esto tiene importante 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 smartphone, y posible 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.

El lector MIFARE MFRC522

MIFARE es una tecnología de tarjetas inalámbricas propiedad de NXP Semiconductores. Es uno de los estándares más implantados como tarjetas inteligentes sin contacto (TSIC).

El Mifare MFRC522 es un lector de tarjetas RFID que incorpora comunicación por bus SPI, bus I2C y UART, por lo que es sencillo de conectar con Arduino. El MFRC522 soporta las tarjetas Mifate S50, Mifare S70, Mifare UltraLight, Mifare Pro y Mifare Desfire.

El lector MFRC522 opera en la frecuencia de 13.56Mhz y tiene una distancia de lectura de 0 a 60. El MFRC522 tiene un consumo de 13-26 mA durante la escritura, 10-13mA en stanby e inferior a 80uA en modo sleep. La tensión de alimentación es de 3.3V.

El MFRC522 suele suministrarse con tarjetas o llaveros MIFARE Classic 1K. Este tipo de tarjetas son, esencialmente, un sistema de almacenamiento donde la memoria está dividida en bloques, con mecanismos simple para el acceso a la información.

El MIFARE Classic 1K dispone de 1024 bytes de memoria divididos en 16 sectores de 64 bytes, cada uno protegido por dos claves llamadas A y B. Cada una puede ser programada individualmente para permitir o bloquear operaciones lectura o escritura.

Cada sector reserva una cierta memoria para las claves A y B, por lo que este espacio normalmente no puede ser empleado para guardar datos, lo que reduce la cantidad de memoria disponible en una MIFARE Classic 1K a 752 bytes.

La memoria EEPROM de las tarjetas MIFARE Classic puede soportar más de 100.000 ciclos de escritura, y pueden mantener la memoria durante más de 10 años sin recibir alimentación.

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.

Las tarjetas MIFARE Classic emplean un sistema de cifrado propio de NXP que, en la actualidad, no es considerado seguro.

Esquema de montaje

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.

arduino-rfid-rc522-esquema

Mientras que la conexión vista desde el lado de Arduino quedaría así.

arduino-rfid-rc522-conexion

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 patillaje correspondiente.

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.

Ejemplos de código

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. Los siguientes ejemplos son modificaciones a partir de los disponibles en la librería.

Mostrar el ID de la tarjeta

El siguiente ejemplo detecta una tarjeta RFID, y muestra su identificador por puerto serie.

//RST          D9
//SDA(SS)      D10
//MOSI         D11
//MISO         D12
//SCK          D13

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

const int RST_PIN = 9;        // Pin 9 para el reset del RC522
const int SS_PIN = 10;        // Pin 10 para el SS (SDA) del RC522
MFRC522 mfrc522(SS_PIN, RST_PIN);   // Crear instancia del MFRC522

void printArray(byte *buffer, byte bufferSize) {
  for (byte i = 0; i < bufferSize; i++) {
    Serial.print(buffer[i] < 0x10 ? " 0" : " ");
    Serial.print(buffer[i], HEX);
  }
}

void setup()
{
  Serial.begin(9600);    //Inicializa la velocidad de Serial
  SPI.begin();      //Función que inicializa SPI
  mfrc522.PCD_Init();     //Función  que inicializa RFID
}

void loop()
{
  // Detectar tarjeta
  if (mfrc522.PICC_IsNewCardPresent())
  {
    if (mfrc522.PICC_ReadCardSerial())
    {
      Serial.print(F("Card UID:"));
      printArray(mfrc522.uid.uidByte, mfrc522.uid.size);
      Serial.println();

      // Finalizar lectura actual
      mfrc522.PICC_HaltA();
    }
  }
  delay(250);
}

Validad el ID de la tarjeta

El siguiente ejemplo lee una tarjeta y comprueba el ID para determinar si la tarjeta es aceptada o no.

//RST          D9
//SDA(SS)      D10
//MOSI         D11
//MISO         D12
//SCK          D13

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

const int RST_PIN = 9;        // Pin 9 para el reset del RC522
const int SS_PIN = 10;        // Pin 10 para el SS (SDA) del RC522
MFRC522 mfrc522(SS_PIN, RST_PIN);   // Crear instancia del MFRC522

byte validKey1[4] = { 0xA0, 0xB1, 0xC2, 0xD3 };  // Ejemplo de clave valida

//Función para comparar dos vectores
bool isEqualArray(byte* arrayA, byte* arrayB, int length)
{
  for (int index = 0; index < length; index++)
  {
    if (arrayA[index] != arrayB[index]) return false;
  }
  return true;
}

void setup() {
  Serial.begin(9600); // Iniciar serial
  SPI.begin();        // Iniciar SPI
  mfrc522.PCD_Init(); // Iniciar MFRC522
}

void loop() {
  // Detectar tarjeta
  if (mfrc522.PICC_IsNewCardPresent())
  {
    //Seleccionamos una tarjeta
    if (mfrc522.PICC_ReadCardSerial())
    {
      // Comparar ID con las claves válidas
      if (isEqualArray(mfrc522.uid.uidByte, validKey1, 4))
        Serial.println("Tarjeta valida");
      else
        Serial.println("Tarjeta invalida");

      // Finalizar lectura actual
      mfrc522.PICC_HaltA();
    }
  }
  delay(250);

}

Escritura de datos

En el último ejemplo empleamos las funciones de escritura y lectura para grabar una cadena de texto en la memoria de la tarjeta Mifare.

//RST          D9
//SDA(SS)      D10
//MOSI         D11
//MISO         D12
//SCK          D13

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

const int RST_PIN = 9;
const int SS_PIN = 10;

//Declaracion de cadena de caracteres
unsigned char data[16] = { 'T','E','S','T',' ','R','F','I','D',' ','M','F','R', '5','5','2'}; 
unsigned char *writeData = data; 
unsigned char *str;

MFRC522 mfrc522(SS_PIN, RST_PIN);

MFRC522::MIFARE_Key key;

void printArray(byte *buffer, byte bufferSize) {
  for (byte i = 0; i < bufferSize; i++) {
    Serial.print(buffer[i] < 0x10 ? " 0" : " ");
    Serial.print(buffer[i], HEX);
  }
}

void setup()
{
  Serial.begin(9600);
  SPI.begin();
  mfrc522.PCD_Init();

  for (byte i = 0; i < 6; i++) {
    key.keyByte[i] = 0xFF;
  }
}

void loop()
{
  if (!mfrc522.PICC_IsNewCardPresent())
    return;

  if (!mfrc522.PICC_ReadCardSerial())
    return;

  MFRC522::StatusCode status;
  byte trailerBlock = 7;
  byte sector = 1;
  byte blockAddr = 4;

  status = (MFRC522::StatusCode) mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, trailerBlock, &key, &(mfrc522.uid));
  if (status != MFRC522::STATUS_OK) {
    Serial.print(F("PCD_Authenticate() failed: "));
    Serial.println(mfrc522.GetStatusCodeName(status));
    return;
  }

  // Write data to the block
  Serial.print(F("Escribir datos en sector "));
  Serial.print(blockAddr);
  Serial.println(F(" ..."));
  printArray((byte*)data, 16); Serial.println();
  status = (MFRC522::StatusCode) mfrc522.MIFARE_Write(blockAddr, (byte*)data, 16);
  if (status != MFRC522::STATUS_OK) {
    Serial.print(F("MIFARE_Write() failed: "));
    Serial.println(mfrc522.GetStatusCodeName(status));
  }
  Serial.println();

  byte buffer[18];
  byte size = sizeof(buffer);

  // Read data from the block (again, should now be what we have written)
  Serial.print(F("Leer datos del sector ")); Serial.print(blockAddr);
  Serial.println(F(" ..."));
  status = (MFRC522::StatusCode) mfrc522.MIFARE_Read(blockAddr, buffer, &size);
  if (status != MFRC522::STATUS_OK) {
    Serial.print(F("MIFARE_Read() failed: "));
    Serial.println(mfrc522.GetStatusCodeName(status));
  }
  Serial.print(F("Data in block ")); Serial.print(blockAddr); Serial.println(F(":"));
  printArray(buffer, 16); Serial.println();

  // Halt PICC
  mfrc522.PICC_HaltA();
  // Stop encryption on PCD
  mfrc522.PCD_StopCrypto1();
}

Descarga el código

Todo el código de esta entrada está disponible para su descarga en Github. github-full