Tutorial sobre sensores RFID para Arduino, ESP8266 y ESP32

En este tutorial aprenderá cuáles son los componentes de un sistema RFID y cómo se transmiten la energía y los datos, además de cómo leer/escribir desde/a una etiqueta RFID.

En este tutorial aprenderás todo lo que tienes que saber sobre RFID para tu próximo proyecto con un microcontrolador Arduino, ESP8266 o ESP32.

Después de aprender los fundamentos de un sistema RFID, vemos cómo se transfiere la energía y los datos entre el lector RFID y la etiqueta.

Después de la teoría un ejemplo de un contador de café automatizado le muestra el módulo RC522 en acción.

¿Qué es RFID?

RFID significa identificación por radiofrecuencia y es una técnica de comunicación electrónica que se utiliza principalmente para identificar objetos. Además, RFID resume todos los sistemas de identificación que utilizan radiofrecuencia.

Los casos de uso típicos son:

  • Identificar libros en una biblioteca
  • Abra una barrera solo para automóviles específicos
  • Acceda a los empleados a áreas restringidas utilizando un sistema RFID para abrir las puertas.

La ventaja sobre el código de barras es que no se requiere una línea lateral directa entre la etiqueta RFID y el lector.

Componentes en un sistema RFID con microcontrolador

En una configuración RFID general, hay un lector RFID y una etiqueta (transpondedor) que deben identificarse. La siguiente imagen muestra los componentes individuales en detalle.

Componentes de un sistema RFID

El lector consta de tres partes. El generador de señales de radiofrecuencia genera el campo electromagnético a través de una bobina que se envía a las etiquetas de potencia. También hay un receptor de señal y un detector para leer la respuesta de la etiqueta. El microcontrolador es la cabeza del lector y controla otros componentes y procesa más información.

La etiqueta tiene un transpondedor que recibe ondas de radio del lector y también envía datos al lector. El circuito del receptor almacena energía en la etiqueta para alimentar el microcontrolador. El propio microcontrolador está conectado a una memoria donde se almacena la información que se puede transmitir al lector.

Hay dos tipos básicos de sistemas RFID:

  1. Sistema pasivo donde las etiquetas no tienen fuente de alimentación interna y por lo tanto son alimentadas por el lector RFID por ondas de radio.
  2. Sistema activo en el que las etiquetas funcionan con baterías y se pueden leer a una distancia mayor de hasta cientos de metros.

La siguiente tabla muestra las diferencias entre etiquetas pasivas y activas en diferentes categorías:

Comparación de sistemas RFID pasivos y activos

Criterios de RFID pasiva RFID activa

CriteriosRFID pasivaRFID activa
Batería de la etiquetaNoSí
Fuente de alimentación de la etiquetaEnergía transferida desde el lectorInterna a la etiqueta
Disponibilidad de energía de la etiquetaSólo dentro del campo de un lector activadoContinuo
Fuerza de la señal requerida del lector a la etiquetaAlta (debe alimentar la etiqueta)Baja (sólo para transportar información)
Fuerza de la señal disponible de la etiqueta al lectorBajaAlta
Rango de comunicaciónAlcance corto o muy corto (3m o menos)Alcance largo (100m o más)
Vida útil de la etiquetaMuy largaLimitada a la duración de la batería (depende de la estrategia de ahorro de energía)
Tamaño típico de la etiquetaPequeñaGrande
Recogida de múltiples etiquetasRecoge cientos de etiquetas a menos de 3 metros de un solo lector

Recoge 20 etiquetas que se mueven a 8 km/h o menos
Recoge 1000s de etiquetas en una región de 28000 m2 desde un solo lector

Recoge 20 etiquetas que se mueven a más de 160 km/h
Capacidad del sensorCapacidad de leer y transferir los valores del sensor sólo cuando la etiqueta es alimentada por el lector; sin sello de fecha/horaCapacidad de monitorizar y registrar continuamente la entrada del sensor; sello de datos/hora para los eventos del sensor
Almacenamiento de datosPequeño almacenamiento de datos de lectura/escritura (Bytes)Grande almacenamiento de datos de lectura/escritura (KBytes) con sofisticadas capacidades de búsqueda y acceso a datos disponibles
Aplicaciones típicasProcesos empresariales rígidos, movimiento de activos restringido, seguridad básica (detección de eventos de manipulación una vez), impacto sustancial en el proceso empresarial. Etiquetado de artículos individuales, equipaje, cajas, cartones, palés, etiquetas impresasProcesos empresariales dinámicos, movimiento de activos no restringido, seguridad/sensores, almacenamiento/registro de datos Contenedor intermodal, supervisión de la zona de vagones, portales multietiquetas de alta velocidad, aplicaciones sofisticadas de seguridad de la carga (detección continua de manipulaciones, sello de fecha/hora), manifiesto electrónico
CosteBajo (menos de 0,5 dólares )Alto (más de 5 dólares, hasta cientos)

Transmisión de energía para un sistema RFID

En la tabla puede ver que en un sistema RFID pasivo, la etiqueta no tiene fuente de alimentación interna y por lo tanto debe ser alimentada por el lector. El lector envía un campo electromagnético a través de una bobina de antena. Este campo electromagnético se recibe de la bobina del transpondedor de la etiqueta y crea un voltaje de inducción que sirve como fuente de alimentación para el microchip de la etiqueta y se almacena dentro del circuito del receptor.

En el caso de un sistema RFID activo, no hay necesidad de transmisión de energía porque la etiqueta en sí tiene una fuente de alimentación interna.

Transmisión de datos para un sistema RFID

Una vez que la etiqueta es alimentada por el voltaje de inducción del lector RFID, la etiqueta envía datos al lector mediante manipulación de carga. La carga se activa y desactiva en la etiqueta. Debido a que el lector y la etiqueta están acoplados inductivamente, un cambio en la carga en la etiqueta da como resultado un cambio en el consumo de energía de la antena del lector. Este cambio en el consumo está representado por una caída de tensión y se interpreta como 1 y 0.

Otro enfoque para la transmisión de datos es la transmisión de datos mediante acoplamiento retrodispersado. La etiqueta crea un segundo campo electromagnético con energía a través del primer campo. Este segundo campo es recibido por el lector y, a través de cambios en el segundo campo electromagnético, se transmiten los datos.

Normalmente, los primeros datos transmitidos desde la etiqueta al lector son el UID y el tipo de PICC que identifica la etiqueta.

  • UID: el UID es el identificador único de la etiqueta, por ejemplo: «BD 31 15 2B». El UID se almacena en el primer bloque de memoria de baliza y es de solo lectura. Por lo tanto, el identificador no se puede cambiar.
  • PICC: abreviatura de tarjeta de circuito integrado de proximidad. Este es el tipo de etiqueta, como si este auto fuera un Ford. Por ejemplo, una etiqueta RFID de uso frecuente para microcontroladores Arduino o ESP8266 es MIFARE 1KB, que también utilizo en este tutorial.

Bandas de frecuencia RFID

En general, existen diferentes bandas de frecuencia en las que puede operar la aplicación RFID. La siguiente tabla muestra las diferentes bandas de frecuencia.

Regulaciones de banda Rango Velocidad de datos Observaciones

BandasRegulacionesRangoVelocidad de los datosObservaciones
120-150 kHz (LF)No regulado10 cmBajoIdentificación de animales, recogida de datos en fábrica
13,56 MHz (HF)BandaISM en todo el mundo10 cm-1 mBaja a moderadaTarjetas inteligentes, tarjetas de memoria no compatibles con ISO, tarjetas de microprocesador compatibles con ISO
433 MHz (UHF)Dispositivos de corto alcance1-100 mModeradoAplicaciones de defensa, con etiquetas activas
865-868 MHz (Europa)

902-928 MHz (Norteamérica) UHF
BandaISM1-12 mModerada a altaEAN, varios estándares; utilizada por los ferrocarriles
2450-5800 MHzBandaISM1-2 mAlta802.11 WLAN, estándares Bluetooth
3,1-10 GHzBanda ultraanchaHasta 200 mAltaRequiere etiquetas semiactivas o activas

Fuente: https://en.wikipedia.org/wiki/Radio-frequency_identification

Configuración del módulo RFID RC522 con microcontrolador

En este tutorial estoy usando el módulo RC522 como lector y también diferentes etiquetas compatibles con este lector. Normalmente, puede comprar el lector con algunas etiquetas en un paquete para asegurarse de que el lector pueda identificar la etiqueta. Es importante que la frecuencia coincida y que el lector admita el formato de la etiqueta.

El módulo RC522 se basa en la placa Philips MF522-AN-on y admite una frecuencia RFID de 13,56 MHz, así como los siguientes formatos de etiqueta: S50, S70 Ultralight, Pro, DESFire. El RC522 está conectado al microcontrolador Arduino o ESP8266 a través de SPI, lo que permite una velocidad de transmisión entre el lector y el microcontrolador de hasta 10 Mbit / s.

Es muy importante alimentar el módulo RC522 solo con 3.3V y no con 5V.

Si está utilizando un Arduino Pro Mini, entonces solo el modelo de 3.3V.

El consumo de corriente es muy bajo entre 80 µA y 26 mA:

  • Transmisión de datos: 13… 26 mA
  • Estado de reposo: 10… 13 mA
  • Estado de espera: 80 µA

La etiqueta es un transpondedor Mifare con 1 KB de memoria que se divide en 16 sectores, cada sector en 4 bloques y cada bloque puede almacenar 2 bytes de datos. Cada sector tiene dos teclas (A / B) a las que se les pueden asignar derechos para leer y escribir bloques de memoria. El último bloque contiene las claves y los derechos (condiciones de acceso).

La siguiente imagen muestra cómo se construye la memoria en la parte superior:

Información de volcado RFID RC522

Los sectores están numerados del 0 al 15 y el número de bloque para cada bloque (que contiene 2 bytes) se numera en serie del 0 al 63.
La salida de la imagen se llama DumpInfo y es un ejemplo proporcionado con la instalación de la biblioteca MFRC522. Las siguientes imágenes muestran cómo encuentra este ejemplo: Archivo → Ejemplos → MFRC522 → DumpInfo

Arduino IDE DumpInfo

El Mifare clásico tiene un algoritmo patentado «Crypto-1» que no ha sido seguro desde 2008. Hay balizas MIFARE DESFire EV1 y EV2 más recientes que son seguras hasta el día de hoy. Pero para algunos proyectos de bricolaje, la seguridad no es tan importante para mí.

Cableado entre el lector RFID RC522 y el microcontrolador

Las siguientes imágenes muestran el cableado entre el módulo lector RFID RC522 y varias placas de microcontroladores Arduino, ESP8266 y ESP32. La conexión entre el microcontrolador y el módulo RC522 es la misma para todos los siguientes ejemplos de este artículo.

Precaución eléctrica y consideraciones de diseño en RFID RC522

  • Peligro crítico de destrucción por 5 V (VCC estricto a 3,3 V): El circuito integrado NXP MFRC522 opera exclusivamente en un rango de 2,5 V a 3,6 V DC. Si conectas el pin VCC del módulo al raíl de 5 V de una placa Arduino Uno o Mega, perforarás la capa de óxido de silicio del receptor de radiofrecuencia, destruyendo el módulo de forma instantánea e irreversible. Conecta siempre el pin VCC a la salida de 3,3 V.
  • Tolerancia de 5 V en las líneas de datos SPI: Según el datasheet de NXP, los pines de entrada lógica del MFRC522 (SCK, MOSI, SDA, RST) toleran 5 V lógicos cuando el chip está alimentado a 3,3 V, mientras que la salida MISO entrega 3,3 V (que un microcontrolador de 5 V reconoce correctamente como nivel ALTO por encima del umbral de 2,6 V). No obstante, en cables de más de 15 cm, las reflexiones inductivas pueden superar los 5,5 V. Si experimentas lecturas inestables con Arduino Uno, intercala resistencias en serie de 1 kΩ en SCK y MOSI o un desplazador de nivel bidireccional.
  • Picos de consumo en emisión de radiofrecuencia (13,56 MHz): Al emitir el campo magnético para energizar la tarjeta pasiva por acoplamiento inductivo, el transmisor de potencia del RC522 consume pulsos rápidos de hasta 30 mA. En clones de Arduino Nano con reguladores lineales de 3,3 V deficientes (integrados en chips USB CH340 de apenas 30-50 mA), la tensión de alimentación cae momentáneamente por debajo de 2,7 V, provocando el clásico error «WARNING: Communication failure, is the MFRC522 properly connected?». Solución: suelda un condensador cerámico de 100 nF en paralelo con un electrolítico de 10 μF directamente entre los pines 3.3V y GND del módulo lector.
  • Riesgo de bucle de masa (PE) con la antena del osciloscopio: La antena del RC522 es una bobina balanceada conectada a las salidas diferenciales TX1 y TX2 con un filtro pasa bajos LC. Nunca conectes la pinza de masa de una sonda de osciloscopio de sobremesa puesta a tierra de protección (PE) a los terminales de la antena ni al cristal oscilador de 27,12 MHz; hazlo siempre a la línea GND común para evitar derivar a tierra las señales de RF y desintonizar la antena.
Pin RC522 Señal SPI Arduino Uno / Nano Arduino Mega 2560 ESP32 (VSPI por defecto) ESP8266 (NodeMCU / D1) Función y notas técnicas
SDA (SS) Slave Select (CS) Pin D10 Pin D53 GPIO 5 (o GPIO 15) Pin D8 (GPIO 15) Habilitación de esclavo SPI (activo en nivel BAJO).
SCK Serial Clock Pin D13 Pin D52 GPIO 18 Pin D5 (GPIO 14) Reloj síncrono del bus SPI (hasta 10 MHz en el MFRC522).
MOSI Master Out Slave In Pin D11 Pin D51 GPIO 23 Pin D7 (GPIO 13) Transmisión de comandos y datos hacia el lector RFID.
MISO Master In Slave Out Pin D12 Pin D50 GPIO 19 Pin D6 (GPIO 12) Línea de respuesta del lector; entrega niveles nativos de 3,3 V.
IRQ Interrupt Request No conectado No conectado No conectado No conectado Interrupción por presencia de tarjeta (opcional, no requerida por la librería).
GND Tierra / Referencia 0 V Pin GND Pin GND Pin GND Pin GND Referencia de potencial común obligatoria.
RST Reset / Power Down Pin D9 Pin D5 GPIO 22 (o GPIO 4) Pin D3 (GPIO 0) Reinicio por hardware y control de modo reposo (Sleep).
3.3V (VCC) Alimentación DC Pin 3.3V (¡Nunca 5V!) Pin 3.3V (¡Nunca 5V!) Pin 3V3 Pin 3V3 Alimentación directa del chip NXP MFRC522 (tensión estricta: 2,5 a 3,6 V DC).

Validación de una etiqueta RFID con identificador único

En el primer ejemplo queremos leer la identificación de la etiqueta y cuando la identificación es válida queremos imprimirla en el monitor de serie. Por tanto, la variable válida se define en el código del programa.

He separado el código del programa Arduino en 4 partes, porque la explicación de cada parte es más fácil de entender. Solo necesita copiar cada parte una debajo de la otra para obtener el código completo del programa.

C++ / ARDUINO & ESP32 (INICIALIZACIÓN SPI Y PINES RC522)
#include "SPI.h"
#include "MFRC522.h"

// For Arduino Microcontroller
#define RST_PIN         9
#define SS_PIN          10

// For ESP8266 Microcontroller
//#define RST_PIN         D0
//#define SS_PIN          D8

// For ESP32 Microcontroller
//#define RST_PIN         27
//#define SS_PIN          15


MFRC522 mfrc522(SS_PIN, RST_PIN);   // Create MFRC522 instance.
MFRC522::MIFARE_Key key;

Al comienzo del script, necesitamos incluir la biblioteca SPI para habilitar la comunicación SPI entre el microcontrolador y el módulo RC522. La segunda biblioteca es la MFRC522 que facilita el manejo del módulo RFID. Puede encontrar información detallada sobre la biblioteca MFRC522 de miguelbalboa en su repositorio de github.

Si no sabe cómo instalar una biblioteca en su IDE de Arduino, puede encontrar un tutorial paso a paso aquí.

Después de incluir las bibliotecas, definimos el pin de reinicio y la selección del esclavo SPI. Puede ver en mis impresionantes bocetos que estoy eligiendo los pines 9 y 10 para el microcontrolador Arduino. Si está utilizando un microcontrolador ESP8266 o ESP32, puede descomentar las líneas de código del microcontrolador y comentar las dos líneas del código Arduino.

También creamos una instancia de MFRC522 y una clave.

C++ / ARDUINO (FUNCIÓN DUMP_BYTE_ARRAY EN HEX/DEC)
void dump_byte_array(byte *buffer, byte bufferSize) {
    for (byte i = 0; i < bufferSize; i++) {
        Serial.print(buffer[i] < 0x10 ? " 0" : " ");
        Serial.print(buffer[i], HEX);
    }
}

void get_UID(String content) {
  for (byte i = 0; i < mfrc522.uid.size; i++) 
  {
     content.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "));
     content.concat(String(mfrc522.uid.uidByte[i], HEX));
  }
  content.toUpperCase();
  if (content.substring(1) == "E3 26 92 03")
  {
    Serial.println("This is the right tag");
  }
 else   {
    Serial.println("Wrong tag");
  }
}

En la función de configuración, primero establecemos la velocidad en baudios en 9600, que debe coincidir con la velocidad en baudios de su monitor en serie. Esperamos a que la comunicación de línea serie esté lista e inicializamos el bus SPI y la instancia MFRC522 que creamos antes.

Ahora configuramos las teclas A y B en FFFFFFFFFFFFh, que es el valor de la clave de error. Debido a que solo podemos descargar matrices en formato HEX, tenemos que usar una función de creación propia llamada dump_byte_array que obtiene una matriz de bytes y la longitud de la matriz y la transfiere a HEX.

C++ / ARDUINO (BUCLE PRINCIPAL Y LECTURA DE UID)
void loop() {
    // Reset the loop if no new card present on the sensor/reader. This saves the entire process when idle.
    if ( ! mfrc522.PICC_IsNewCardPresent())
        return;

    // Select one of the cards
    if ( ! mfrc522.PICC_ReadCardSerial())
        return;

    // Show some details of the PICC (that is: the tag/card)
    Serial.print(F("Card UID:"));
    dump_byte_array(mfrc522.uid.uidByte, mfrc522.uid.size);
    Serial.println();
    Serial.print(F("PICC type: "));
    MFRC522::PICC_Type piccType = mfrc522.PICC_GetType(mfrc522.uid.sak);
    Serial.println(mfrc522.PICC_GetTypeName(piccType));
   

    // Check for compatibility
    if (    piccType != MFRC522::PICC_TYPE_MIFARE_MINI
        &&  piccType != MFRC522::PICC_TYPE_MIFARE_1K
        &&  piccType != MFRC522::PICC_TYPE_MIFARE_4K) {
        Serial.println(F("No valid tag"));
        return;
    }
    
    MFRC522::StatusCode status;
   
    String content= "";
    get_UID(content);
    
    // Halt PICC
    mfrc522.PICC_HaltA();
    // Stop encryption on PCD
    mfrc522.PCD_StopCrypto1();
}

La función de bucle de retorno comienza verificando si hay una etiqueta RFID disponible. De lo contrario, comenzamos de nuevo con la función loop. Si se reconoce una etiqueta, se selecciona la etiqueta.

A continuación, queremos mostrar el tipo de UID y PICC de la etiqueta en el monitor en serie. Por lo tanto, también usamos la función dump_byte_array y la función de biblioteca MFRC522 mfrc522.uid.uidByte. Para obtener el tipo PICC, usamos otra función de la biblioteca llamada mfrc522.PICC_GetType.

Una vez que conocemos el UID y el tipo de PICC, debemos verificar la compatibilidad. El tipo de PICC debe ser uno de los siguientes tipos:

  • MINI MIFARE
  • MIFARE 1K
  • MIFARE 4K

Debido a que la etiqueta que estoy usando es 1K MIFARE, es válida en este momento.

Ahora queremos verificar si la tarjeta que estamos leyendo actualmente es la que tiene la identificación que configuramos como válida. Primero queremos asegurarnos de que la tarjeta todavía esté disponible y recuperar el estado actual con la función MFRC522 :: Status StatusCode.

Para comprobar si esta es la tarjeta correcta, usamos una segunda función autoescrita llamada get_UID que tiene una cadena como argumento. La función vuelve a leer el UID pero no muestra el ID en el monitor en serie, pero comprueba si el ID es «E3 26 92 03». Si es el mismo ID, imprimimos el resultado en el monitor de serie y si es el ID incorrecto, imprimimos que es la etiqueta incorrecta.

Al final de la función de bucle, detenemos el cifrado PICC y PCD.

C++ / ARDUINO (FORMATEO DE DATOS EN HEXADECIMAL)
void dump_byte_array(byte *buffer, byte bufferSize) {
    for (byte i = 0; i < bufferSize; i++) {
        Serial.print(buffer[i] < 0x10 ? " 0" : " ");
        Serial.print(buffer[i], HEX);
    }
}

void get_UID(String content) {
  for (byte i = 0; i < mfrc522.uid.size; i++) 
  {
     content.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "));
     content.concat(String(mfrc522.uid.uidByte[i], HEX));
  }
  content.toUpperCase();
  if (content.substring(1) == "E3 26 92 03")
  {
    Serial.println("This is the right tag");
  }
 
 else   {
    Serial.println("Wrong tag");
  }
}

La siguiente imagen muestra que he intentado obtener acceso dos veces con una etiqueta con el ID de «39 3F 50 A2» y el código del programa funciona bien, indicándome que es el ID incorrecto. El tercer intento fue la etiqueta válida y obtuve acceso.

UID de validación RFID

Proyecto práctico: Registro y control de acceso RFID con microcontrolador

En este segundo ejemplo, no solo queremos leer un bloque específico de memoria de la etiqueta, también queremos escribir en ese bloque. En este ejemplo, creamos una lista de cafés donde cada vez que un empleado toma un café, el lector escanea su etiqueta. El lector aumenta lo poco que elegimos para contar cafés y reescribe el contador aumentado en la etiqueta.

También queremos tener una etiqueta principal que permita que el contador de café se restablezca a 0. Si alguien paga la factura, el lector identifica la etiqueta principal y se restablecerá el contador de la siguiente etiqueta.

Gran parte del código del programa es idéntico al primer ejemplo. Por lo tanto, solo estoy describiendo los cambios y las líneas de código adicionales. Para obtener el código de programa final que se ejecuta en su microcontrolador Arduino, ESP8266 o ESP32, copie cada parte del código una debajo de la otra o use el botón de descarga al final de esta sección para descargar el archivo Arduino completo.

C++ / ARDUINO & ESP32 (CONFIGURACIÓN DE LIBRERÍA Y SECTOR)
#include "SPI.h"
#include "MFRC522.h"

// For Arduino Microcontroller
#define RST_PIN         9
#define SS_PIN          10

// For ESP8266 Microcontroller
//#define RST_PIN         D0
//#define SS_PIN          D8

// For ESP32 Microcontroller
//#define RST_PIN         27
//#define SS_PIN          15


MFRC522 mfrc522(SS_PIN, RST_PIN);   // Create MFRC522 instance.
MFRC522::MIFARE_Key key;

byte sector         = 1;  //  Number of sector to write
byte blockAddr      = 4;  // Number of block to write
byte dataBlock[]    = {
    0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00};

byte reset_counter = 0;

byte trailerBlock = 7;  // Block address
byte buffer[18];

En la primera sección, necesitamos agregar algunas variables más:

  • byte sector: queremos escribir nuestro contador de café en el primer sector.
  • byte blockAddr: en el primer sector, elegimos el cuarto bloque para el contador.
  • byte dataBlock: es la matriz que se escribe en el cuarto bloque del primer sector y se define como HEX.
  • byte reset_counter: es una bandera que establecemos al leer la etiqueta principal. Este indicador indica si reiniciar el contador o no.
  • byte trailerBlock: define el bloque en el que se almacenan la clave A y la clave B.
  • búfer de bytes: es la matriz que se llena cuando leemos el bloque 4 de la memoria de etiquetas.
C++ / ARDUINO & ESP32 (CONFIGURACIÓN SETUP SPI Y PUERTO SERIE)
void setup() {
    Serial.begin(9600); // Initialize serial communications with the PC
    while (!Serial);    // Do nothing if no serial port is opened (added for Arduinos based on ATMEGA32U4)
    SPI.begin();        // Init SPI bus
    mfrc522.PCD_Init(); // Init MFRC522 card

    // Prepare the key (used both as key A and as key B)
    // using FFFFFFFFFFFFh which is the default at chip delivery from the factory
    for (byte i = 0; i < 6; i++) {
        key.keyByte[i] = 0xFF;
    }
    dump_byte_array(key.keyByte, MFRC522::MF_KEY_SIZE);
    Serial.println();
}

La función de configuración es 1: 1 idéntica a la del ejemplo anterior.

C++ / ARDUINO & ESP32 (VALIDACIÓN DE ACCESO POR UID Y REINICIO)
void loop() {
    // Reset the loop if no new card present on the sensor/reader. This saves the entire process when idle.
    if ( ! mfrc522.PICC_IsNewCardPresent())
        return;

    // Select one of the cards
    if ( ! mfrc522.PICC_ReadCardSerial())
        return;


    byte size = sizeof(buffer);

    // Show some details of the PICC (that is: the tag/card)
    Serial.print(F("Card UID:"));
    dump_byte_array(mfrc522.uid.uidByte, mfrc522.uid.size);
    Serial.println();
    Serial.print(F("PICC type: "));
    MFRC522::PICC_Type piccType = mfrc522.PICC_GetType(mfrc522.uid.sak);
    Serial.println(mfrc522.PICC_GetTypeName(piccType));
   

    // Check for compatibility
    if (    piccType != MFRC522::PICC_TYPE_MIFARE_MINI
        &&  piccType != MFRC522::PICC_TYPE_MIFARE_1K
        &&  piccType != MFRC522::PICC_TYPE_MIFARE_4K) {
        Serial.println(F("This sample only works with MIFARE Classic cards."));
        return;
    }
    
    MFRC522::StatusCode status;

    authenticate_key_A();
    
    read_sector(size);
    
    compute_coffee_counter();
    
    authenticate_key_B();

    write_block();

    check_block();

    
    String content= "";
    reset_counter_function(content);
    

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

La función de bucle comienza y termina de la misma manera que en el primer ejemplo. Solo se recalcula cada vez la longitud de la matriz de búfer porque esta longitud puede cambiar al escribir en la etiqueta. En la parte central, realizamos algunas funciones más que describo en la siguiente sección de este tutorial:

  • authenticate_key_A (): antes de que podamos leer los valores en el bloque 4, necesitamos autenticarnos con la clave A.
  • read_sector (): después de la autenticación, leemos el bloque 4.
  • compute_coffee_counter (): aumente el contador de café en el bloque 4 o reinicie el contador.
  • authenticate_key_B (): entonces necesitamos otra autenticación con la clave B antes de que podamos escribir los valores modificados en el bloque 4.
  • write_block (): escribe el nuevo contenido en el bloque 4.
  • check_block (): Comprueba si el bloque fue escrito correctamente o si la transmisión fue interrumpida.
C++ / ARDUINO (VOLCADO COMPACTO DE BYTES)
void dump_byte_array(byte *buffer, byte bufferSize) {
    for (byte i = 0; i < bufferSize; i++) {
        Serial.print(buffer[i] < 0x10 ? " 0" : " ");
        Serial.print(buffer[i], HEX);
    }
}

La función dump_byte_array es la misma que en el primer ejemplo.

C++ / ARDUINO (REINICIO DE CONTADOR SEGÚN TARJETA MAESTRA)
void reset_counter_function(String content) {
  for (byte i = 0; i < mfrc522.uid.size; i++) 
  {
     content.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "));
     content.concat(String(mfrc522.uid.uidByte[i], HEX));
  }
  content.toUpperCase();
  if (content.substring(1) == "E3 26 92 03")
  {
    reset_counter = 1;
  }
 
 else   {
    reset_counter = 0;
  }
}

La función de reinicio del contador es casi la misma que en el primer ejemplo para decidir si el UID es válido o no. Pero en este ejemplo, cambiamos la variable reset_counter a 1 si queremos poner a cero el contador para la siguiente etiqueta o si dejamos la variable en 0, lo que indica que el contador debe incrementarse en 1.

C++ / ARDUINO (CÁLCULO E INCREMENTO DE CONTADOR DE CAFÉ)
void compute_coffee_counter() {
  // Read current coffee counter and increase the counter or reset to 0
  int coffee_counter = buffer[0];
  Serial.print("Your old coffee counter is: ");
  Serial.println(coffee_counter);
  
  Serial.print("Status reset: ");
  Serial.println(reset_counter);

  if (reset_counter == 1) {
    dataBlock[0] = 0;
    reset_counter = 0;
  }
  else {
    dataBlock[0] = coffee_counter+1;
  }

  Serial.print("Your new coffee counter is: ");
  Serial.println(dataBlock[0]);
}

Ahora queremos cambiar el contador. Por lo tanto, leemos el primer elemento de la matriz de búfer y almacenamos ese valor en la variable coffee_counter como un número entero. Imprimimos el valor del contador anterior en el monitor en serie y evaluamos la variable reset_counter como se mencionó anteriormente. Si reset_counter es 1, la etiqueta de lectura anterior era la etiqueta principal y establecemos el contador en 0 y también restablecemos la variable reset_counter. Si no había baliza maestra, aumentamos el contador en 1.

C++ / ARDUINO (AUTENTICACIÓN CON CLAVE A EN SECTOR MIFARE)
void authenticate_key_A() {
  // Authenticate using key A
  Serial.println(F("Authenticating using key A..."));
  MFRC522::StatusCode 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;
  }
}

void authenticate_key_B() {
  // Authenticate using key B
  Serial.println(F("Authenticating again using key B..."));
  MFRC522::StatusCode status = (MFRC522::StatusCode) mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_B, trailerBlock, &key, &(mfrc522.uid));
  if (status != MFRC522::STATUS_OK) {
      Serial.print(F("PCD_Authenticate() failed: "));
      Serial.println(mfrc522.GetStatusCodeName(status));
      return;
  }
}

Ambas funciones de autenticación utilizan la función mfrc522.PCD_Authenticate de la biblioteca. Después de la autenticación, podemos leer o escribir en diferentes bloques de memoria.

C++ / ARDUINO (LECTURA DE BLOQUE DE DATOS DEL SECTOR)
void read_sector(byte size) {
  // Show the whole sector as it currently is
  Serial.println(F("Current data in sector:"));
  mfrc522.PICC_DumpMifareClassicSectorToSerial(&(mfrc522.uid), &key, sector);
  Serial.println();

  // Read data from the block
  Serial.print(F("Reading data from block ")); Serial.print(blockAddr);
  Serial.println(F(" ..."));
  MFRC522::StatusCode 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(":"));
  dump_byte_array(buffer, 16);
  Serial.println();
}

La siguiente función lee datos del sector de memoria y usa la función de biblioteca mfrc522.MIFARE_Read con la dirección del bloque, la matriz para guardar los datos del bloque y el tamaño de la matriz como argumento.

C++ / ARDUINO (ESCRITURA DE DATOS EN BLOQUE MIFARE)
void write_block(){
  // Write data to the block
  Serial.print(F("Writing data into block ")); Serial.print(blockAddr);
  Serial.println(F(" ..."));
  dump_byte_array(dataBlock, 16);
  Serial.println();
  MFRC522::StatusCode status = (MFRC522::StatusCode) mfrc522.MIFARE_Write(blockAddr, dataBlock, 16);
  if (status != MFRC522::STATUS_OK) {
      Serial.print(F("MIFARE_Write() failed: "));
      Serial.println(mfrc522.GetStatusCodeName(status));
  }
  Serial.println();
}

El bloque para escribir en la memoria no es muy diferente de la función de lectura, pero se usa la función de biblioteca mfrc522.MIFARE_Write en lugar de leer.

C++ / ARDUINO (VERIFICACIÓN Y VALIDACIÓN DEL BLOQUE ESCRITO)
void check_block(){
  // Check that data in block is what we have written
  // by counting the number of bytes that are equal
  Serial.println(F("Checking result..."));
  byte count = 0;
  for (byte i = 0; i < 16; i++) {
      // Compare buffer (= what we've read) with dataBlock (= what we've written)
      if (buffer[i] == dataBlock[i])
          count++;
  }
  Serial.print(F("Number of bytes that match = ")); Serial.println(count);
  if (count == 16) {
      Serial.println(F("Success :-)"));
  } else {
      Serial.println(F("Failure, no match :-("));
      Serial.println(F("  perhaps the write didn't work properly..."));
  }
  Serial.println();

  // Dump the sector data
  Serial.println(F("Current data in sector:"));
  mfrc522.PICC_DumpMifareClassicSectorToSerial(&(mfrc522.uid), &key, sector);
  Serial.println();
}

La última función check_block () compara el búfer elemento por elemento, así como el tamaño del búfer. Si los datos no se escribieron correctamente, los datos se vacían y debe comenzar a escribir la lista de café nuevamente.

Haga clic aquí para descargar archivos Arduino

La siguiente imagen del monitor en serie muestra cómo aumento el contador de café y también restablezco el contador de 4 a cero. También es posible no poner a cero el contador sino reducirlo en 1 si el lector ha detectado previamente la etiqueta maestra.

Contador de café RFID

Espero que disfrutes de este tutorial y si tienes alguna pregunta, usa la sección de comentarios a continuación para hacer preguntas. Les respondo en forma de comentario lo antes posible.

Diagnóstico y verificación del lector RFID RC522 con osciloscopio

Precaución de laboratorio: Bucles de masa a tierra (PE) y desintonización capacitiva de la antena a 13,56 MHz
  • Evita cortocircuitos francos por la masa BNC del osciloscopio: la masa exterior de las sondas pasivas estándar de laboratorio está acoplada internamente a la toma de tierra física de protección (PE) del edificio. Si alimentas el Arduino o ESP32 mediante el puerto USB de un ordenador conectado a la red eléctrica y conectas por descuido la pinza de cocodrilo de masa a una línea de alimentación o a un pin SPI en estado ALTO, generarás un cortocircuito masivo que fundirá pistas de la PCB o destruirá el puerto USB del PC. Conecta la pinza de masa exclusivamente a GND y verifica la equipotencialidad antes de medir.
  • Prohibido tocar directamente la antena con sondas estándar (efecto de carga capacitiva): el circuito resonante LC sintonizado de la antena RFID a 13,56 MHz posee un alto factor de calidad (Q). La capacitancia de entrada de una sonda pasiva estándar (entre 15 pF y 100 pF) desintoniza la frecuencia de resonancia y atenúa drásticamente el campo electromagnético, impidiendo que el lector detecte las tarjetas. Para visualizar la portadora senoidal y la modulación ASK sin alterar el circuito, utiliza exclusivamente el método de captación inductiva sin contacto mediante un lazo cerrado con el cable de masa (sonda de campo cercano) a 1 o 2 cm de la placa.

Cuando un lector RFID MFRC522 no responde o falla al aproximar una tarjeta MIFARE, los mensajes de error por el monitor serie son genéricos: la librería MFRC522.h simplemente devuelve 0x00 o 0xFF como versión del firmware. El osciloscopio es la única herramienta de banco que permite discernir con total certeza si el fallo proviene del bus digital SPI, de la portadora de radiofrecuencia a 13,56 MHz o del acoplamiento magnético con el tag:

1. Inspección de la portadora de radiofrecuencia a 13,56 MHz en la antena

El estándar ISO/IEC 14443 Tipo A opera mediante acoplamiento inductivo en campo cercano a la frecuencia industrial, científica y médica (ISM) de 13,56 MHz:

  • Método de captación sin contacto (Sonda de campo cercano casera): Para no desintonizar el circuito resonante LC de la antena con la capacitancia de entrada de la sonda (~15 pF), conecta el clip de masa de la sonda directamente a su propia punta formando un bucle cerrado de 2 a 3 cm. Acerca este bucle a 1 cm de la antena PCB del RC522.
  • Verificación de la forma de onda y período: Ajusta la base de tiempos a 20 ns/div o 50 ns/div. Observarás una onda sinusoidal limpia a 13,56 MHz cuyo período medido debe ser exactamente T = 1 / 13.560.000 pprox 73,75  ext{ns . Si la señal no aparece o su amplitud es inferior a 1 Vpk en acoplamiento inductivo, el oscilador de cuarzo de 27,12 MHz del módulo o los transistores de salida del chip están dañados.

2. Detección de la modulación ASK y acoplamiento con la tarjeta (Tag MIFARE)

Al aproximar una tarjeta o llavero RFID a la antena del lector:

  • Modulación por variación de carga (Load Modulation): El chip interno del tag MIFARE no genera portadora propia; modula la señal de 13,56 MHz transmitida por el lector variando su consumo interno de corriente mediante una subportadora de 848 kHz (ASK modificada con pausas de modulación al 100 %).
  • Captura de la ráfaga de interrogación: Configura el trigger del osciloscopio en modo Single Sweep con acoplamiento en AC y base de tiempos a 500 μs/div. Al acercar la tarjeta, observarás cómo la envolvente de la señal de 13,56 MHz presenta muescas y caídas de amplitud correspondientes a la trama de sincronismo anticolición (Anticollision Loop) y solicitud de UID (REQA / WUPA). Si la envolvente permanece plana, la tarjeta opera en otra frecuencia (ej. 125 kHz EM4100) o su antena interna está rota.

3. Decodificación y comprobación de integridad en el bus SPI

Para verificar la comunicación digital entre el microcontrolador y el chip MFRC522, conecta los canales del osciloscopio a las líneas SPI:

  • Canal 1 (Reloj SCK) y Canal 2 (Selección SDA/CS): Verifica que el pin SDA cae a nivel BAJO (0 V) antes de que comiencen los pulsos de reloj SCK. La librería configura el bus SPI en Modo 0 (CPOL=0, CPHA=0) a frecuencias habituales de 4 a 10 MHz (período de reloj de 100 a 250 ns).
  • Canal 3 (MOSI) y Canal 4 (MISO): Durante la inicialización (mfrc522.PCD_Init()), el microcontrolador escribe en el registro de comando a través de MOSI y solicita la lectura del registro VersionReg (dirección 0x37). El chip RC522 debe responder por MISO entregando 0x92 (chip v2.0 estándar) o 0x91 (chip v1.0). Si MISO permanece permanentemente en nivel BAJO (0x00) o en nivel ALTO (0xFF), el osciloscopio te mostrará si la línea MISO carece de datos o si el chip no está recibiendo el pulso de reset RST en nivel ALTO.

Para depurar módulos RFID de 13,56 MHz, decodificar buses SPI de alta velocidad y monitorizar niveles lógicos en laboratorio, estos son los 4 osciloscopios de referencia recomendados para banco de trabajo:

Modelo recomendado Formato / Arquitectura Ancho de banda / Muestreo Canales y Memoria Función clave para RFID 13,56 MHz y Bus SPI Oferta
Sobremesa digital laboratorio 50 MHz (ampliable) / 1 GSa/s 4 canales / 24 Mpts 4 canales analógicos simultáneos para decodificar las 4 líneas del bus SPI (CS, SCK, MOSI, MISO) o correlacionar SPI con la portadora RF VER MEJOR PRECIO
Sobremesa con tecnología SPO (Super Fósforo) 200 MHz / 1 GSa/s 2 canales / 14 Mpts Ancho de banda de 200 MHz para capturar con total fidelidad la forma de onda sinusoidal pura a 13,56 MHz y sus armónicos de conmutación VER MEJOR PRECIO
Módulo USB con aislamiento galvánico de hardware 25 MHz / 100 MSa/s 2 canales / 5 Kpts Aislamiento óptico y de transformador hasta 400 Vpk que elimina bucles de masa entre el ordenador y bancos de prueba de control de accesos VER MEJOR PRECIO
Sobremesa de banco clásico 100 MHz / 1 GSa/s 2 canales / 40 Kpts 100 MHz de ancho de banda y pantalla de 7 pulgadas para verificar niveles lógicos SPI y presencia de señal portadora a precio accesible VER MEJOR PRECIO

Si buscas el equipo más completo para analizar buses digitales SPI/I2C y señales de radiofrecuencia con 4 canales de laboratorio y memoria profunda:

Para profundizar en buses serie, comunicación de sensores y análisis de señales en banco de trabajo, consulta nuestras guías especializadas: Diagnóstico de buses I2C y SPI con osciloscopio, Cómo elegir un osciloscopio para proyectos con Arduino y ESP32, Osciloscopio con Arduino, Arduino Uno Pinout y conexiones SPI y nuestra comparativa de osciloscopios digitales, osciloscopios portátiles y osciloscopios USB para PC.

Preguntas frecuentes y diagnóstico de fallos en el lector RFID RC522

¿Por qué el monitor serie muestra «WARNING: Communication failure, is the MFRC522 properly connected?» (0x00 o 0xFF)?

Cuando DumpVersionToSerial() devuelve 0x00 o 0xFF, el microcontrolador no logra leer el registro interno del RC522 por SPI. En el 90 % de los casos se debe a tres causas: pines MOSI/MISO/SCK permutados (recuerda que en Arduino Mega van en los pines 50, 51, 52 y 53, no en 10-13), soldaduras frías en la tira de pines del módulo o cableado demasiado largo en protoboard.

¿Por qué el lector RC522 no lee algunas tarjetas de acceso o de transporte público?

El módulo RC522 trabaja exclusivamente en alta frecuencia (HF 13,56 MHz, norma ISO/IEC 14443 A). Muchas llaves de garaje o fichas de control de presencia antiguas son de baja frecuencia (LF 125 kHz, como los chips EM4100 o T5577), las cuales requieren un lector de 125 kHz como el RDM6300.

Deja un comentario