MFRC522 read anomalies - card UID not being obtained

I’m wondering if there’s anyone that may be able to shed some light on a issue I’m having with an Arduino Mega and MFRC522 NFC reader.

Before I describe the particular issue I’ll point out that the code works 99.9% of the time with no issues and I’m hoping somone can help me refine it to prevent the issue I have occasionally.

Within my sketch I have a byte array named:

uint8_t TagRead[4];

There are also a number of arrays storing the card UIDs:

uint8_t RED1[4] = { 0x17, 0xF6, 0xE2, 0xA4 };
uint8_t RED2[4] = { 0x77, 0xF9, 0xD5, 0xA4 };
uint8_t RED3[4] = { 0x85, 0x83, 0xB1, 0xFB };

Within the loop section of my code I do this:

void loop() {
    do {
      readflag = checkread();              //Returns 1 if the MFRC522 
                                             detects a card
    }
    while (!readflag);

    NewTone(readerbuzzer, 1000, 180);      //Beep
    recordid();                            //Record the scanned card's ID
    action();                              //Do something
}

checkread() looks like this:

int checkread() {
  if ( ! mfrc522.PICC_IsNewCardPresent()) {
    return 0;
  }
  mfrc522.PICC_HaltA();
  return 1;
}

So basically, if a card is detected it returns 1.

recordid() looks like this:

void recordid() {
  mfrc522.PICC_IsNewCardPresent();
  mfrc522.PICC_ReadCardSerial();
  for (int i = 0; i < mfrc522.uid.size; i++) {
    TagRead[i] = mfrc522.uid.uidByte[i];
  }
  mfrc522.PICC_HaltA();
}

So I end up with the scanned card’s UID in the RagRead array. With this I can perform some action, for example compare it to one of the cards that’s declared already:

void action() {
  if (*((uint32_t *)TagRead) == *((uint32_t *)RED1)) {
      dosomething();    
  }
  else if (*((uint32_t *)TagRead) == *((uint32_t *)RED1)) {
      dosomethingelse();    
  }
}

This all works OK 99% of the time.

The problem

Sometimes, if a card is scanned but removed too quickly, the system detects a new card (and so triggers recordid() and action()…) but the new card’s UID is not recorded in TagRead. TagRead keeps the value of the previous card and so the action for the card scanned previously is triggered again.

Does anyone know why this is happening and more importantly, how I can prevent it?

If the card isn’t scanned properly, could I call another function that warns the user they need to scan again?

The most important thing to solve is the calling of the action function if TagRead hasn’t been updated with the new UID.

Is it possible that the card is detected (enough to break out of the loop) but the card info is not being obtained?

Thank you in advance.

  mfrc522.PICC_IsNewCardPresent();

It's useless to call this function when you don't give a rats ass what it returns.

Your action() method is nonsense. You do NOT compare the contents of arrays like that. There is a really stupidly simple to use function, memcmp(), that compares arrays correctly.

It would also make sense to change checkread() to actually do what the name suggests. Check that there is a card AND read the card. Return true only if the card is successfully read.

I'm doing this the exact same way as the DumpInfo tutorial.

The way I compare arrays works, so what's the issue with it?

why you dont want to delete/initilialize TagRead to zeroes after you have read it (and done what ever you wanted) ... at least the card uid wouldn't survive for the next read ...