RFID Sensor Tutorial for Arduino, ESP8266 and ESP32

In this tutorial you learn everything you have to know about RFID for your next project with an Arduino, ESP8266 or ESP32 microcontroller.

After we learn the basics of a RFID system, we see how power and data is transferred between the RFID reader and the tag.

After the theory an example of an automated coffee counter shows you the RC522 module in action.

Arduino RFID Sensor

Table of Contents

What is RFID?

RFID stands for Radio-frequency identification and is an electronic communication technique mostly used to identify objects. Moreover RFID summaries all identification system which use radio frequency.

Typical use cases are:

  • Identify books in a library
  • Open a barrier only for specific cars
  • Access employees to restricted areas using a RFID system to open doors.

The advantage compared to barcode is that there is no direct line of side required between RFID tag and reader.

Components in a RFID System with Microcontroller

In a general RFID setup there is an RFID reader and a tag (transponder) that should be identified. The following picture shows the different components in detail.

Components in an RFID System

The reader consists of three parts. The radio frequency signal generator generates the electromagnetic field through a coil which is send out to power tags. There is also a receiver and signal detector to read the response of the tag The microcontroller is the head of the reader and controls the other components and further processes the information.

The tag has a transponder which receives the radio waves from the reader and also sends data back to the reader. The receiver circuit stores the energy in the tag to power the microcontroller. The microcontroller itself is connected with a memory where the information is stored which can be transmitted to the reader.

There are two fundamental different types of RFID systems:

  1. Passive system where tags do not have an internal source of power and therefore are powered from the RFID reader device by radio waves.
  2. Active system where tags are powered by a battery and can be read by a longer distance up to hundreds of meters.

The following table shows the differences of passive and active tags on different categories:

Comparison of Passive and Active RFID Systems

CriteriaPassive RFIDActive RFID
Tag BatteryNoYes
Tag Power SourceEnergy transferred from the readerInternal to tag
Availability of Tag PowerOnly within the field of an activated readerContinuous
Required Signal Strength from Reader to TagHigh (must power the tag)Low (only to carry information)
Available Signal Strength from Tag to ReaderLowHigh
Communication RangeShort or very short range (3m or less)Long range (100m or more)
Tag lifetimeVery longLimited to battery life (depends on energy saving strategy)
Typical tag sizeSmallLarge
Multi-Tag CollectionCollects hundreds of tags within 3 meters from a single reader

Collects 20 tags moving at 8 km/h or slower
Collects 1000s of tags over a 28000 m2 region from a single reader

Collects 20 tags moving at more than 160 km/h
Sensor CapabilityAbility to read and transfer sensor values only when tag is powered by reader; no date/time stampAbility to continuously monitor and record sensor input; data/time stamp for sensor events
Data StorageSmall read/write data storage (Bytes)Large read/write data storage (KBytes) with sophisticated data search and access capabilities available
Typical applicationsRigid business processes, constrained asset movement, basic security (one time tamper event detection), substantial business process impact. Individual item tagging, luggage, boxes, cartons, pallet, printed labelsDynamic business process, unconstrained asset movement, security/sensing, data storage/logging Inter-modal container, rail car area monitoring, high speed multi-tag portals, sophisticated cargo security applications (continuous tamper detection, date/time stamp), electronic manifest
CostLow (below $0.5 )High (above $5, up to hundreds)

Source: OECD (2008-06-18), “RFID Guidance and Reports”, OECD Digital Economy Papers, No. 150, OECD Publishing, Paris. http://dx.doi.org/10.1787/230334062186

Power Transmission for a RFID System

From the table you see that in a passive RFID system the tag has no internal power supply and therefore has to be powered from the reader. The reader is sending out an electromagnetic field through an antenna coil. This electromagnetic field is received from the coil of the tag’s transponder and creates an induction voltage which serves as power supply for the microchip on the tag and is stored inside the receiver circuit.

In case of an active RFID system there is no need for a power transmission because the tag itself has an internal power supply.

Data Transmission for a RFID System

After the tag is powered by the induction voltage of the RFID reader, the tag sends data to the reader via load manipulation. Load is switched on and off on the tag. Because the reader and tag are inductive coupled, a change in the load at the tag results in a change of the power consumption of the readers antenna. This change in consumption is represented as voltage drop and interpreted as 1 and 0.

An other data transmission approach is data transmission via backscattered coupling. The tag creates a second electromagnetic field with the power though the first field. This second field is received by reader and through changes in the second electromagnetic field, data is transmitted.

Normally the first data that is transmitted from the tag to the reader are the UID and the PICC type which identifies the tag.

  • UID: The UID is the Unique Identifier of the tag for example: “BD 31 15 2B”. The UID is saved in the first memory block of the tag and read-only. Therefore the identifier can not be changed.
  • PICC: Short for Proximity Integrated Circuit Card. This is the type of tag, like that car is a Ford. For example a frequently used RFID tag for Arduino or ESP8266 microcontrollers is the MIFARE 1KB which I also use in this tutorial.

RFID Frequency Bands

In general there are different frequency bands where the RFID application can operate. The following table shows the different frequency bands.

BandsRegulationsRangeData SpeedRemarks
120–150 kHz (LF)Unregulated10 cmLowAnimal identification, factory data collection
13.56 MHz (HF)ISM band worldwide10 cm–1 mLow to moderateSmart cards, ISO-non-compliant memory cards, ISO-compatible microprocessor cards
433 MHz (UHF)Short range devices1–100 mModerateDefense applications, with active tags
865–868 MHz (Europe)

902–928 MHz (North America) UHF
ISM band1–12 mModerate to highEAN, various standards; used by railroads
2450–5800 MHzISM band1–2 mHigh802.11 WLAN, Bluetooth standards
3.1–10 GHzUltra wide bandUp to 200 mHighRequires semi-active or active tags

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

RFID RC522 Module Setup with Microcontroller

In this tutorial I use the RC522 module as reader and also different tags which are compatible to that reader. Normally you can buy the reader with some tags as a package to make sure that the reader is able to identify the tag. It is important that the frequency is matching and that the reader supports the format of the tag.

The RC522 module is based on the Philips MF522-AN-on board and supports a RFID frequency of 13.56 MHz as well as the following tag formats: S50, S70 Ultralight, Pro, DESFire. The RC522 is connected to the Arduino or ESP8266 microcontroller via SPI which allows a transmission rate between reader and microcontroller up to 10 Mbit/s.

It is very important to supply the RC522 module only with 3.3V and not 5V.

If you use an Arduino Pro Mini, then only the 3.3V model.

The current consumption is very low between 80 µA and 26 mA:

  • Data transmission: 13…26 mA
  • Idle state: 10…13 mA
  • Sleep state: 80 µA

The tag is a Mifare transponder with 1 KB of memory which is divided into 16 sectors, each sector into 4 blocks and each block can store 2 bytes of data. Each sector has two keys (A/B) which can be assigned with rights for reading and writing memory blocks. The last block contains the keys and the rights (access conditions).

The following picture shows how the memory is build up:

RFID RC522 dumpinfo

The sectors are numbered from 0 to 15 and the block number for every block (containing 2 bytes) is serially numbered from 0 to 63.
The output from the picture is called DumpInfo and is an example that comes with the installation of the MFRC522 library. The following pictures shows how you find this example: File → Examples → MFRC522 → DumpInfo

Arduino IDE DumpInfo

The Mifare classic has a proprietary “Crypto-1” algorithm which is not secure anymore since 2008. There are newer MIFARE DESFire EV1 and EV2 tags which are secure until today. But for some DIY projects the security is in my case not so important.

The following table gives you an overview of all components and parts that I used for the following examples. I get commissions for purchases made through links in this table.

ComponentAmazon LinkAliExpress Link
Arduino Nano AmazonAliExpress
Arduino Pro Mini AmazonAliExpress
Arduino Uno AmazonAliExpress
Arduino Mega AmazonAliExpress
ESP32 ESP-WROOM-32AmazonAliExpress
ESP8266 NodeMCU AmazonAliExpress
ESP8266 WeMos D1 Mini AmazonAliExpress
RFID RC522 Kit AmazonAliExpress

Wiring between RC522 RFID Reader and Microcontroller

The following pictures show the wiring between the RC522 RFID reader module and different Arduino, ESP8266 and ESP32 microcontroller boards. The connection between the microcontroller and the RC522 module is the same for all following examples in this article.

Because the RFID reader uses SPI communication, you have to know the SPI pins on your microcontroller. If you are not sure what are the SPI pins on your micorcontroller, I recommend to download my free Microcontroller Datasheet eBook, where you find detailed pinouts including the pins for the SPI communication.

Wiring between RC522 RFID Reader and Arduino Microcontroller

The wiring between the RC522 RFID reader and different Arduino boards is shown in the following table, as well as in different fritzing pictures for each Arduino board. Because the maximum operation voltage of the RC522 module is 3.3V, we can not use the 5V pins of the Arduino board but instead use the 3.3V pins.

RC522 RFID ReaderArduino Nano, Pro Mini 3.3V, UnoArduino Mega
SDA10SS
SCK13SCK
MOSI11MOSI
MISO12MISO
IRQnot connectednot connected
GNDGNDGND
RST99
3.3V3V33V3

Wiring between RC522 RFID Reader and ESP8266 Microcontroller

The following table and pictures show the wiring between the RC522 RFID reader and different ESP8266 microcontroller boards. For the power supply, we use the 3.3V pins of the ESP8266 NodeMCU and ESP8266 WeMos D1 Mini.

Because the SPI interface with ID 0 is used for the communication of the flash chip, when you upload a program from your PC to the connected ESP8266 board via USB, I always use the HSPI interface.

RC522 RFID ReaderESP8266
SDAD8
SCKD5
MOSID7
MISOD6
IRQnot connected
GNDGND
RSTD0
3.3V3V3

Wiring between RC522 RFID Reader and ESP32 Microcontroller

The ESP32 microcontroller and the RFID reader module have the same operation voltage of 3.3V. The following table shows the connection between the RC522 and the ESP32 microcontroller for both SPI interfaces VSPI and HSPI.

RC522 RFID ReaderEPS32 (VSPI interface) EPS32 (HSPI interface)
SDA515
SCK1814
MOSI2313
MISO1912
IRQnot connectednot connected
GNDGNDGND
RST2727
3.3V3V33V3

From the table, you see that we can use the VSPI connection pins or the HSPI interface out of the 4 SPI interfaces that the ESP32 provides. The following fritzing picture shows the connection between the RC RFID reader module and the EPS32 ESP-WROOM-32 board using the VSPI interface.

At the end of this article you find a download button to download the whole program code as zip file from the two examples.

Validation of a RFID Tag with Unique Identifier

In the first example we want to read the identifier of the tag and when the identifier is valid we want to print this in the serial monitor. The valid tag is therefore defined in the program code.

I separated the Arduino program code into 4 parts, because the explanation of each part is easier to understand. You only have to copy each part one below the other to get the complete program code.

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

At the beginning of the script we have to include the SPI library to activate the SPI communication between the microcontroller and the RC522 module. The second library is the MFRC522 which makes it easier to handle the RFID module. You can find detailed information about the MFRC522 library by miguelbalboa in his github repository.

If you do not know how to install a library in your Arduino IDE, then you find here a step by step tutorial.

After we include the libraries we define the pin of the reset and the SPI slave select. You can see from my fritzing sketches that I choose pin 9 and 10 for the Arduino microcontroller. If you are using an ESP8266 or ESP32 microcontroller, you can uncomment the lines of code of the microcontroller and comment the two lines of code for the Arduino.

Also we create a MFRC522 instance and a key.

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");
  }
}

In the setup function we first set the baud rate to 9600 which has to match to the baud rate on your serial monitor. We wait until the serial line communication is ready and initialize the SPI bus and the MFRC522 instance we created before.

Now we set the key A and B to FFFFFFFFFFFFh which is the fault key value. Because we can only upload arrays as HEX we have to use a self created function called dump_byte_array that gets a byte array and the length of the array and transfer it to 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();
}

The loop function starts with checking if an RFID tag is available. If not we restart to loop function. If a tag is recognized, the tag is selected.

Next we want to display the UID and the PICC type of the tag in the serial monitor. Therefore we also use the function dump_byte_array and the function of the MFRC522 library mfrc522.uid.uidByte. To get the PICC type we use an other function of the library called mfrc522.PICC_GetType.

After we know the UID and the PICC type we have to check for compatibility. The PICC type has to be one of the following types:

  • MIFARE MINI
  • MIFARE 1K
  • MIFARE 4K

Because the tag I use is a MIFARE 1K it is valid at this point.

Now we want to check if the card that we are currently reading is the one with the identifier that we defined as valid. First we want to make sure that the card is still available and fetch the current status with the function MFRC522::StatusCode status.

To check if it is the right card we use a second self written function called get_UID which has a string as argument. The function reads the UID again but does not display the ID to the serial monitor but checks if the ID is “E3 26 92 03”. If it is the same ID then we print the result to the serial monitor and if it is the wrong ID we print that it is the wrong tag.

At the end of the loop function we halt the PICC and stop the encryption of the 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");
  }
}

The following picture shows that I tried to get access two times with a tag that ID is “39 3F 50 A2” and that the program code is running correct, telling me that it is the wrong ID. The third attempt was the valid tag and I got access.

RFID validation UID

Build an Automated RFID Coffee Counter

In this second example we want not only read out a specific memory block of the tag, we also want to write into this block. In this example we create a coffee list where each time an employee gets a coffee her or his tag is scanned by the reader. The reader increases the bit we choose to count the coffees and write the increased counter back to the tag.

Also we want to have a master tag which enables the option to reset the coffee counter to 0. If someone pays the bill, the master tag is identified by the reader and the counter of the next tag will be reset.

A lot of the program code is the same compared to the first example. Therefore I only describe the changes and additional code lines. To get the final program code that is running on your Arduino, ESP8266 or ESP32 microcontroller, copy each part of the code one below the other or use the download button at the end of this section to download the full Arduino file.

#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];

In the first section we have to add some more variables:

  • byte sector: we want to write our coffee counter in the first sector.
  • byte blockAddr: in the first sector we choose the fourth block for the counter.
  • byte dataBlock: is the array which is written to the fourth block in the first sector and defined as HEX.
  • byte reset_counter: is a flag we set when the master tag was read. This flag indicates to reset the counter or not.
  • byte trailerBlock: defines the block where the key A and key B is stored.
  • byte buffer: is the array that is filled when we read out the block 4 of the tag’s memory.
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();
}

The setup function is 1:1 the same from the previous example.

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();
}

The loop function starts and ends the same compared to the first example. Only the length of the buffer array is recalculated each time because this length could change when writing to the tag. In the middle part we execute a couple more functions which I describe in the next section of this tutorial:

  • authenticate_key_A(): before we can read the values of block 4 we have to authenticate with key A.
  • read_sector(): after the authentication we read the block 4.
  • compute_coffee_counter(): either we increase the coffee counter in block 4 or reset the counter.
  • authenticate_key_B(): then we need another authentication with key B before we can write the changed values to block 4.
  • write_block(): write the new content to block 4.
  • check_block(): Check if the block was written correctly or if the transmission was interrupted.
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);
    }
}

The function dump_byte_array is the same as in the first example.

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

The function to reset the counter is nearly the same as in the first example to decide if the UID is valid or not. But in this example we change the reset_counter variable to 1 if we want to reset the counter for the next tag or if we leave the variable to 0, indicating that the counter has to be incremented by 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]);
}

Now we want to change the counter. Therefore we read the first element of the buffer array and save this value to the variable coffee_counter as integer. We print the old value of the counter to the serial monitor and evaluate the variable reset_counter as mentioned before. If reset_counter is 1, the previous read tag was the master tag and we set the counter to 0 and also reset the variable reset_counter. If there was no master tag we increase the counter by 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;
  }
}

The two function for the authentication use the function mfrc522.PCD_Authenticate from the library. After the authentication we can read or write to different block of the memory.

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();
}

The next function reads the data from the memory sector and uses the library function mfrc522.MIFARE_Read with the address of the block, the array to save the block data and the size of the array as argument.

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();
}

The block to write to the memory is not too much different from the reading function but the library function mfrc522.MIFARE_Write instead of read is used.

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();
}

The last function check_block() compares the buffer element by element and also the size of the buffer. If the data was not written correctly the data is dumped and you have to start the writing of the coffee list again.

The following picture of the serial monitor shows how I increase the coffee counter and also that I reset the counter from 4 to zero. It is also possible not to reset the counter but to decrease the counter by 1 if the master tag was previously detected by the reader.

RFID Coffee Counter

I hope you like this tutorial and if you have any questions, please use the comment section below to ask you questions. I answer them as comment as soon as possible.

Loading comments...
Get your free Microcontroller Datasheet eBook

Get your free Microcontroller Datasheet eBook now, by joining the DIYI0T newsletter

- Ranking of 14 Arduino, ESP8266 and ESP32 boards

- Comparison of the Power Consumption of all Boards

- Detailed Datasheet Information and Pinouts