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 etiquetaNo
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í.

La siguiente tabla le brinda una descripción general de todos los componentes y partes que utilicé para los siguientes ejemplos. Recibo comisiones por compras realizadas a través de los enlaces de esta tabla.

Arduino NanoAmazonAliExpress
Arduino Pro MiniAmazonAliExpress
Arduino UnoAmazonAliExpress
Arduino MegaAmazonAliExpress
ESP32 ESP-WROOM-32AmazonAliExpress
ESP8266 NodeMCUAmazonAliExpress
ESP8266 WeMos D1 MiniAmazonAliExpress
Kit RFID RC522AmazonAliExpress

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.

Dado que el lector RFID utiliza comunicación SPI, necesita conocer los pines SPI de su microcontrolador. Si no está seguro acerca de los pines SPI de su microcontrolador, le recomiendo que descargue mi libro electrónico gratuito con la hoja de datos del microcontrolador, donde encontrará pines detallados, incluidos los pines para la comunicación SPI.

Cableado entre el lector RFID RC522 y el microcontrolador Arduino

El cableado entre el lector RFID RC522 y diferentes placas Arduino se muestra en la siguiente tabla, así como en diferentes imágenes de fritzing para cada placa Arduino. Dado que el voltaje operativo máximo del módulo RC522 es 3.3V, no podemos usar los pines de 5V de la placa Arduino, sino los pines de 3.3V en su lugar.

Lector RFID RC522 Arduino Nano, Pro Mini 3.3V, Uno Arduino Mega

SDAdiezSS
SCK13SCK
MOSI11MOSI
MISO12MISO
IRQno conectadono conectado
GNDGNDGND
RST99
3,3 V3V33V3
  • Arduino Nano
  • Arduino Pro Mini 3.3V
  • Arduino Uno
  • Arduino Mega

Arduino Nano

RFID RC522 Arduino Nano

Para obtener más información sobre Arduino Nano, visite el tutorial de Arduino Nano.

Arduino Pro Mini 3.3V

RFID RC522 Arduino Pro Mini 3.3V

Arduino Uno

RFID RC522 Arduino Uno

Para obtener más información sobre Arduino Uno, visite el tutorial de Arduino Uno.

Arduino Mega

RFID RC522 Arduino Mega

Para obtener más información sobre Arduino Mega, visite el tutorial de Arduino Mega.

Cableado entre el lector RFID RC522 y el microcontrolador ESP8266

La siguiente tabla e imágenes muestran el cableado entre el lector RFID RC522 y diferentes placas de microcontroladores ESP8266. Para la alimentación, usamos los pines de 3.3V del ESP8266 NodeMCU y el ESP8266 WeMos D1 Mini.

Debido a que la interfaz SPI con ID 0 se usa para la comunicación del chip flash, cuando descarga un programa desde su PC a la placa ESP8266 conectada a través de USB, siempre uso la interfaz HSPI.

Lector RFID RC522 ESP8266

SDAD8
SCKD5
MOSID7
MISOD6
IRQno conectado
GNDGND
RSTD0
3,3 V3V3
  • ESP8266 NodeMCU
  • ESP8266 WeMos D1 Mini

ESP8266 NodeMCU

RFID RC522 ESP8266 NodeMCU

ESP8266 WeMos D1 Mini

RFID RC522 ESP32 WeMos D1 Mini

Cableado entre el lector RFID RC522 y el microcontrolador ESP32

El microcontrolador ESP32 y el módulo lector RFID tienen el mismo voltaje operativo de 3.3V. La siguiente tabla muestra la conexión entre el microcontrolador RC522 y ESP32 para las interfaces VSPI y HSPI SPI.

Lector RFID RC522 EPS32 (interfaz VSPI) EPS32 (interfaz HSPI)

SDA515
SCK1814
MOSI2313
MISO1912
IRQno conectadono conectado
GNDGNDGND
RST2727
3,3 V3V33V3

En la tabla puede ver que podemos usar los pines de conexión VSPI o la interfaz HSPI en las 4 interfaces SPI proporcionadas por el ESP32. La siguiente imagen muestra la conexión entre el módulo lector RC RFID y la placa EPS32 ESP-WROOM-32 utilizando la interfaz VSPI.

ESP32 ESP-WROOM-32

RFID RC522 ESP32 NodeMCU

Al final de este artículo, encontrará un botón de descarga para descargar el código del programa completo como un archivo zip de los dos ejemplos.

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.

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

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.

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.

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

Construya un mostrador de café RFID automatizado

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.

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

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

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.

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.

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.

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.

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.

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.


Deja un comentario