Multiple RFID detection at the same time - MFRC522

I'm currently working on a school project for which I need to detect when a RFID card is present on a reader and when it is removed. To do this, I bought several MFRC522 readers and some cards.
I already achieved to detect when a single tag is present and when it is removed from the reader, but now I want to detect when the user place or remove a tag on multiple readers, at the same time.
I don't know if it's physically possible with this reader, but I found the below code on another forum, and it looks correct.

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

constexpr uint8_t RST_PIN = 9;     // Configurable, see typical pin layout above
constexpr uint8_t SS_1_PIN = 10;   // Configurable, take a unused pin, only HIGH/LOW required, must be diffrent to SS 2
constexpr uint8_t SS_2_PIN = 8;    // Configurable, take a unused pin, only HIGH/LOW required, must be diffrent to SS 1

constexpr uint8_t NR_OF_READERS = 2;

byte ssPins[] = {SS_1_PIN, SS_2_PIN};



MFRC522 mfrc522[NR_OF_READERS];   // Create MFRC522 instance.

bool cardPresent[NR_OF_READERS];   // true => card is present on reader

//*****************************************************************************************//
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

  for (uint8_t reader = 0; reader < NR_OF_READERS; reader++) {
    mfrc522[reader].PCD_Init(ssPins[reader], RST_PIN); // Init each MFRC522 card
    Serial.print(F("Reader "));
    Serial.print(reader);
    Serial.print(F(": "));
    mfrc522[reader].PCD_DumpVersionToSerial();

    // init card present flag
    cardPresent[reader] = false;

  }
}
uint8_t control = 0x00;


//*****************************************************************************************//



void loop() {

  for (uint8_t reader = 0; reader < NR_OF_READERS; reader++) {

    // Look for new card on this reader
    bool newCard = mfrc522[reader].PICC_IsNewCardPresent() && mfrc522[reader].PICC_ReadCardSerial();

    // if a new card is present
    if ( newCard && !cardPresent[reader] )
    {

      // mark this reader as having a card present
      cardPresent[reader] == true;

      Serial.println(reader);
      Serial.println("NewCard ");

    } else if ( cardPresent[reader] ) {

      // there was a card on the reader, is it still there?
      if ( !checkReader(reader) )
      {
        // no, print message and mark as not present
        Serial.print(reader);
        Serial.println("  CardRemoved");
        delay(500); //change value if you want to read cards faster

        // clear card present flag
        cardPresent[reader] = false;

      } // if

    } // else

    mfrc522[reader].PICC_HaltA();
    mfrc522[reader].PCD_StopCrypto1();
  }

}

// Return true if there is a card on the passed reader
//
bool checkReader(int reader)
{

  control = 0;
  for (int i = 0; i < 3; i++) {
    if (!mfrc522[reader].PICC_IsNewCardPresent()) {
      if (mfrc522[reader].PICC_ReadCardSerial()) {
        //Serial.print('a');
        control |= 0x16;
      }
      if (mfrc522[reader].PICC_ReadCardSerial()) {
        //Serial.print('b');
        control |= 0x16;
      }
      //Serial.print('c');
      control += 0x1;
    }
    //Serial.print('d');
    control += 0x4;
  }

  //Serial.println(control);
  return (control == 13 || control == 14);
  //card is still there

}

I run it and it correcly detect when a card is detected, but for some reasons it doesn't detect when i remove the tag. Looks like it never goes into the "else if ( cardPresent[reader] )" condition.
I don't understand why.

Welcome to the Arduino forum and good luck with your project.

The way to find your problem is to use serialPrint() to show you the values being tested in the "if" you refer to. Then you can actually see what your program code is using to make the determination. This is called "debugging" and I bet the term is not new to you.

Paul

Hello Paul,

Thanks for your answer.
I have already done some projects with Arduino, but I have never used the forum.
I tried a lot of things to understand why it doesn't enter the elseif condition, and of course, I tried to debug it with some Serial.print :confused:

After some trials, I found an issue : the boolean array "cardPresent", who, for some reasons, never set the different elements of the array to true.
Hence, I modified the array type to create an array of integers, in which the value "1" correspond to "true" and "0" to "false". I know it ain't the cleanest solution, but it works much better.

So I was finally able to move forward on my project :wink:

I share my final code below, with which I can test the presence of tags on two readers at the same time, and with a "retry" loop to improve the relevance of the information.

Hoping it will help someone :smiley:

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

#define RST_PIN  9 
#define SS_1_PIN  10   // Configurable, take a unused pin, only HIGH/LOW required, must be diffrent to SS 2
#define SS_2_PIN  8   // Configurable, take a unused pin, only HIGH/LOW required, must be diffrent to SS 1

#define NR_OF_READERS  2 
#define RETRY_TOLERANCE  5 // Configurable, increase the number if you want to test more times 

byte ssPins[] = {SS_1_PIN, SS_2_PIN};
uint8_t control = 0x00;

MFRC522 mfrc522[NR_OF_READERS];   // Create MFRC522 instance.

int CardDetected[NR_OF_READERS]; //Array of integers to know if a reader has detected something


//*****************************************************************************************//
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

  for (uint8_t reader = 0; reader < NR_OF_READERS; reader++) {
    mfrc522[reader].PCD_Init(ssPins[reader], RST_PIN); // Init each MFRC522 card
    Serial.print(F("Reader "));
    Serial.print(reader);
    Serial.print(F(": "));
    mfrc522[reader].PCD_DumpVersionToSerial();

    // init card presence flag
    CardDetected[reader] = 0;
  }
}

//*****************************************************************************************//
// Returns true if there is a card on the passed reader
// This method includes a "retry loop" to add robustness to the tag presence verification process
//
void checkReader(int reader)
{
     bool RetryDetection=false; //Boolean used to signal when the reader has detected something in the retry loop
      
      for ( int RetryIndex = 0 ; RetryIndex < RETRY_TOLERANCE ; RetryIndex++) //Enter Retry Mode to be sure that the tag is removed
      {  
        // Card presence verification process
        control = 0;
        for (int i = 0; i < 3; i++) 
        {
            if (!mfrc522[reader].PICC_IsNewCardPresent()) {
            if (mfrc522[reader].PICC_ReadCardSerial()) {
            //Serial.print('a');
            control |= 0x16;
            }
              if (mfrc522[reader].PICC_ReadCardSerial()) {
                //Serial.print('b');
                control |= 0x16;
              }
              //Serial.print('c');
              control += 0x1;
            }
            //Serial.print('d');
            control += 0x4;
        }
      
        //Determining if the card is removed or is still on the reader
        if(control == 13 || control == 14) //The card is still on the reader
        {
          RetryDetection=true;
        }
        
        delay(50); //Time base for successive verifications -- can be changed according your need
      }

      if(RetryDetection) // If, after 5 attempts, the reader did detect a tag at least once, we consider that the card is still on the reader
      {
        String TestText = "Reader" + String(reader) + ": Card is still there"; 
        Serial.println(TestText);
      }
  
      else //If, after 5 attempts, the reader didn't detect a card, we consider that the card was removed from the reader
      {
          String TestText = "Reader" + String(reader) + ": Card was removed !"; 
          Serial.println(TestText);
          CardDetected[reader] = 0;
      }
}

//*****************************************************************************************//
void loop() {

  for (int reader = 0; reader < NR_OF_READERS; reader++) 
  {
    // Look for new card on this reader
    bool newCard = mfrc522[reader].PICC_IsNewCardPresent() || mfrc522[reader].PICC_ReadCardSerial();
    
    String TestText = "Reader" + String(reader) + " is waiting for tags ... " + String(CardDetected[reader]); 
    Serial.println(TestText);

    // if a new card is present
    if ( newCard && CardDetected[reader] == 0 )
    {
      // mark this reader as having a card present
      CardDetected[reader] = 1;
      String TestText = "Reader" + String(reader) + ": new Card detected !"; 
      Serial.println(TestText);
    }     
    else if ( CardDetected[reader] == 1 )
    {
      checkReader(reader);
    }
    
    mfrc522[reader].PICC_HaltA();
    mfrc522[reader].PCD_StopCrypto1();
  }
}

An array of anything, boolean or int or byte or... is never set to anything by the compiler. For boolean, 0 is false, non-zero is true, so you could have had anything in that memory space and each byte could be initially true or false.

Paul

What does this mean, then:

“. The elements of global and static arrays, on the other hand, are automatically initialized with their default values, which for all fundamental types this means they are filled with zeros.”

just my 25 second googling, true.

a7