Search code examples
rfidarduino-ideesp32

MFRC 522 Authentication RESET on Arduino IDE with ESP32


I've been tinkering with the MFRC-522 (RC-522) RFID module for a project.

I'm testing authentication using an old key to check if the RFID's key A for a sector (in my case, Sector 2) is different from the original, if it was, then I would continue, if not I would like to "register" the card by changing the key.

I was caught at the beginning on checking different keys authentication, if I tested a working key and then an incorrect key, it works as expected, but if I test with the incorrect key first, it doesn't allow even the correct key to authenticate.

If I ran the code below everything in serial is

PCD_Authenticate() failed NEW(read): Timeout in communication.
PCD_Authenticate() failed OLD(read): Timeout in communication.

repeatedly but if I flipped old() and neww() I get

OLD WORKS
PCD_Authenticate() failed NEW(read): Timeout in communication.

Why does it work as such?

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

#define RST_PIN         22          // Configurable, see typical pin layout above
#define SS_PIN          21         // Configurable, see typical pin layout above

MFRC522 mfrc522(SS_PIN, RST_PIN);  // Create MFRC522 instance

MFRC522::MIFARE_Key old_key = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
MFRC522::MIFARE_Key new_key = {0x23,0x54,0x64,0x3a,0x32,0x66};

void setup() {
    Serial.begin(115200);       // 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
    delay(4);               // Optional delay. Some board do need more time after init to be ready, see Readme
    mfrc522.PCD_DumpVersionToSerial();  // Show details of PCD - MFRC522 Card Reader details
    Serial.println(F("Scan PICC to see UID, SAK, type, and data blocks..."));
}

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

    neww();
    old(); 
}


void old(){
  //authentication of the desired block for access
  byte status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, 15, &old_key, &(mfrc522.uid));

  if (status != MFRC522::STATUS_OK) {
         Serial.print("PCD_Authenticate() failed OLD(read): ");
         Serial.println(mfrc522.GetStatusCodeName((MFRC522::StatusCode)status));
         return;
  }else {Serial.println("OLD WORKS");}
  //delay(1000);
  mfrc522.PICC_HaltA();
  mfrc522.PCD_StopCrypto1(); 
}

void neww() {
  //authentication of the desired block for access
byte  status_new = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, 15, &new_key, &(mfrc522.uid));

  if (status_new != MFRC522::STATUS_OK) {
         Serial.print("PCD_Authenticate() failed NEW(read): ");
         Serial.println(mfrc522.GetStatusCodeName((MFRC522::StatusCode)status_new));
         return;
  } else {Serial.println("NEW WORKS");}
  //delay(1000);
  mfrc522.PICC_HaltA();
  mfrc522.PCD_StopCrypto1(); 
}
}

Solution

  • So, after reading the datasheet extra hard I came to the conclusion that the state of the card was not ready for the next read, so I came with a fire-all-guns solution that helped my case, The Serial prints are for debugging so if using the code feel free to comment them out.

      bool reselect_Card() {
      //-------------------------------------------------------
      // Can also be used to see if card still available,
      // true means it is false means card isnt there anymore
      //-------------------------------------------------------
            byte s;
            byte req_buff[2];
            byte req_buff_size=2;
            mfrc522.PCD_StopCrypto1();
            s = mfrc522.PICC_HaltA();
              Serial.print("Halt Status: ");
              Serial.println(mfrc522.GetStatusCodeName((MFRC522::StatusCode)s));
           delay(100);
           s = mfrc522.PICC_WakeupA(req_buff,&req_buff_size);
              Serial.print("Request: ");
              Serial.println(mfrc522.GetStatusCodeName((MFRC522::StatusCode)s));
              Serial.print("ATQA : ");
              Serial.println(dump_byte_array_to_string(req_buff,req_buff_size)); 
           delay(100);
           s = mfrc522.PICC_Select( &(mfrc522.uid),0);
              Serial.print("Selected : ");
              Serial.println(mfrc522.GetStatusCodeName((MFRC522::StatusCode)s)); 
           if( mfrc522.GetStatusCodeName((MFRC522::StatusCode)s) == F("Timeout in communication.") ) { return false;} 
           return true;
    }