Search code examples
arduinonfcesp32rfidmfrc522

Measure how much time an NFC tag stays on RC522


I'm trying to measure of much time does a specific NFC tag stays on the RC522 reader through an ESP32. I'm using MFRC522.h library to use the RFID module, but I don't know what some functions do as it's not very well documented... I've tried different approaches, but I always end up with the same result. The wires are connected correctly, as dumping the info show the right info.

Code:

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

#define SS_PIN 5    // ESP32 pin GPIO5
#define RST_PIN 27  // ESP32 pin GPIO27

MFRC522 rfid(SS_PIN, RST_PIN);

unsigned long timeStart = 0;
unsigned long timeEnd = 0;
bool tagPresent = false;


void setup() {
  Serial.begin(9600);
  SPI.begin();      // init SPI bus
  rfid.PCD_Init();  // init MFRC522
  Serial.println("Use an RFID tag");
}

void loop() {
  if (rfid.PICC_IsNewCardPresent() && rfid.PICC_ReadCardSerial()) {
    if (!tagPresent) {  // if tagPresent = false, then the tag has just "arrived"
      tagPresent = true;
      timeStart = millis();
    }

    // Removing the next 2 function calls doesn't solve the problem but 
    // it seems to halve the time read in the duration variable

    rfid.PICC_HaltA();  
    rfid.PCD_StopCrypto1();

  } else {
    if (tagPresent) {  //at some point there was a tag, but it's gone now
      Serial.print("\n");
      timeEnd = millis();
      unsigned long duration = timeEnd - timeStart;
      Serial.print("Tag NFC stayed for ");
      Serial.print(duration);
      Serial.println(" ms");
      // noted the last tag's time, reset
      tagPresent = false;
    }
  }
}

Output:

    Tag NFC stayed for 51 ms
    Tag NFC stayed for 51 ms    
    Tag NFC stayed for 51 ms    
    Tag NFC stayed for 51 ms    
    ...

If I put the tag on the reader it immediatly pops out a line of the output and nothing else for as much as I leave the tag there. If I repeatedly lift and lower the tag towards the reader I get multiple prints like in the output above.

Instead I need that if I leave the tag for 10 seconds, and then remove it, to print "Tag NFC stayed for 10000 ms".


Solution

  • After studying more accurately the ISO documentation and the library files I managed to solve this by using a WakeUp Call which brings the PICC to the state READY*, which allows to be seen as a "new" tag again.

    I placed MFRC522::StatusCode status = rfid.PICC_WakeupA(bufferATQA, &bufferSize); at the beginning of loop(), and called the function again after passing the IsNewCardPresent() and ReadCardSerial() check, and also a the end of loop(). Not sure why, but if I try to remove even one of the three calls, it doesn't work.

    void loop() {
      MFRC522::StatusCode status = rfid.PICC_WakeupA(bufferATQA, &bufferSize);
      //Serial.print("Before check, status - ");
      //Serial.println(status, DEC);
    
    
      if (rfid.PICC_IsNewCardPresent() && rfid.PICC_ReadCardSerial()) {
        status = rfid.PICC_WakeupA(bufferATQA, &bufferSize);
        //Serial.print("Inside IF, status - ");
        //Serial.println(status, DEC);
            
        if (!tagPresent) {  // if tagPresent = false, then the tag has just "arrived"
          tagPresent = true;
          timeStart = millis();
          Serial.println("Tag NFC RILEVATO!");
        }
    
      } else {
        if (tagPresent) {  //at some point there was a tag, but it's gone now
          Serial.print("\n");
          timeEnd = millis();
          unsigned long duration = timeEnd - timeStart;
          Serial.print("Tag NFC stayed for ");
          Serial.print(duration);
          Serial.println(" ms");
         //  noted the last tag's time, reset
          tagPresent = false;
        }
      }
      status = rfid.PICC_WakeupA(bufferATQA, &bufferSize);
      //Serial.print("End, status - ");
      //Serial.println(status, DEC);
    }