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.
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:
- 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.
- 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
Criterios | RFID pasiva | RFID activa |
---|---|---|
Batería de la etiqueta | No | Sí |
Fuente de alimentación de la etiqueta | Energía transferida desde el lector | Interna a la etiqueta |
Disponibilidad de energía de la etiqueta | Sólo dentro del campo de un lector activado | Continuo |
Fuerza de la señal requerida del lector a la etiqueta | Alta (debe alimentar la etiqueta) | Baja (sólo para transportar información) |
Fuerza de la señal disponible de la etiqueta al lector | Baja | Alta |
Rango de comunicación | Alcance corto o muy corto (3m o menos) | Alcance largo (100m o más) |
Vida útil de la etiqueta | Muy larga | Limitada a la duración de la batería (depende de la estrategia de ahorro de energía) |
Tamaño típico de la etiqueta | Pequeña | Grande |
Recogida de múltiples etiquetas | Recoge 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 sensor | Capacidad de leer y transferir los valores del sensor sólo cuando la etiqueta es alimentada por el lector; sin sello de fecha/hora | Capacidad de monitorizar y registrar continuamente la entrada del sensor; sello de datos/hora para los eventos del sensor |
Almacenamiento de datos | Pequeñ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ípicas | Procesos 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 impresas | Procesos 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 |
Coste | Bajo (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
Bandas | Regulaciones | Rango | Velocidad de los datos | Observaciones |
---|---|---|---|---|
120-150 kHz (LF) | No regulado | 10 cm | Bajo | Identificación de animales, recogida de datos en fábrica |
13,56 MHz (HF) | BandaISM en todo el mundo | 10 cm-1 m | Baja a moderada | Tarjetas inteligentes, tarjetas de memoria no compatibles con ISO, tarjetas de microprocesador compatibles con ISO |
433 MHz (UHF) | Dispositivos de corto alcance | 1-100 m | Moderado | Aplicaciones de defensa, con etiquetas activas |
865-868 MHz (Europa) 902-928 MHz (Norteamérica) UHF | BandaISM | 1-12 m | Moderada a alta | EAN, varios estándares; utilizada por los ferrocarriles |
2450-5800 MHz | BandaISM | 1-2 m | Alta | 802.11 WLAN, estándares Bluetooth |
3,1-10 GHz | Banda ultraancha | Hasta 200 m | Alta | Requiere 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:
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
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 Nano | Amazon | AliExpress |
Arduino Pro Mini | Amazon | AliExpress |
Arduino Uno | Amazon | AliExpress |
Arduino Mega | Amazon | AliExpress |
ESP32 ESP-WROOM-32 | Amazon | AliExpress |
ESP8266 NodeMCU | Amazon | AliExpress |
ESP8266 WeMos D1 Mini | Amazon | AliExpress |
Kit RFID RC522 | Amazon | AliExpress |
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
SDA | diez | SS |
SCK | 13 | SCK |
MOSI | 11 | MOSI |
MISO | 12 | MISO |
IRQ | no conectado | no conectado |
GND | GND | GND |
RST | 9 | 9 |
3,3 V | 3V3 | 3V3 |
- Arduino Nano
- Arduino Pro Mini 3.3V
- Arduino Uno
- Arduino Mega
Arduino Nano
Para obtener más información sobre Arduino Nano, visite el tutorial de Arduino Nano.
Arduino Pro Mini 3.3V
Arduino Uno
Para obtener más información sobre Arduino Uno, visite el tutorial de Arduino Uno.
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
SDA | D8 |
SCK | D5 |
MOSI | D7 |
MISO | D6 |
IRQ | no conectado |
GND | GND |
RST | D0 |
3,3 V | 3V3 |
- ESP8266 NodeMCU
- ESP8266 WeMos D1 Mini
ESP8266 NodeMCU
ESP8266 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)
SDA | 5 | 15 |
SCK | 18 | 14 |
MOSI | 23 | 13 |
MISO | 19 | 12 |
IRQ | no conectado | no conectado |
GND | GND | GND |
RST | 27 | 27 |
3,3 V | 3V3 | 3V3 |
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
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.
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.
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.