RC522 - Print Once Only to Console If No card Present

This should be very simple but I'm failing here. I have tried boolean flags which seemed to be ideal but they didn't work.

As the code stands, it prints a single line once any of 5 known RFID tags are present at the reader.

However, I now want to simply print another single line (e.g "No tag") when there is no tag upon the reader.

I'd be really super grateful if somebody told me how to do this as it's driving me a bit mental at this stage :confused:

Reason:
The end goal is that a midi command will be put in place of those serial print commands; a "note on" command when a card is present and a "note off" command when not. I can't have these commands sending continuously, so I just need a way to send the "note off" bit once and once only when the card is taken away.

Thanks in advance for any tips! :slight_smile:
Thanks

#include <SPI.h>
#include <MFRC522.h>
#define SS_PIN 10
#define RST_PIN 9
MFRC522 mfrc522(SS_PIN, RST_PIN);   // Create MFRC522 instance.

char* instrumentUIDs[] = {"E6 7A 78 89", "67 10 DB 2B", "54 8F DA 2B", "84 C2 BE 1E", "A7 0B 75 F2"};

//*****************************************************************************************//
void setup() {
  Serial.begin(115200); // Open serial monitor at 115200 baud to see ping results.  
  SPI.begin();      // Initiate  SPI bus
  mfrc522.PCD_Init();   // Initiate MFRC522
}

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

  if ( ! mfrc522.PICC_IsNewCardPresent()) {  // Look for new cards
    return;
  }
  if ( ! mfrc522.PICC_ReadCardSerial()) {    // Select one of the cards
    return;
  }
  
  ObjectTagChecker();

  mfrc522.PICC_HaltA();          // Halt PICC
  mfrc522.PCD_StopCrypto1();     // Stop encryption on PCD
}

//*****************************************************************************************//
void ObjectTagChecker() {  

  String content= "";
  byte letter;
  
  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();

  for (int i = 0; i < (sizeof(instrumentUIDs)/2); i++) {  // UNIVERSAL MIDI, DONT NEED CHANGE MIDI NUMBER - Just change midi input on indiv ableton tracks! - ONLY FOR THE TRIGGIN OF CLIPS BELOW!
    if (content.substring(1) == instrumentUIDs[i]) {       
        Serial.println("PRINT CARD PRESENT - JUST ONCE!");       
    } 
  }
}

I have tried boolean flags which seemed to be ideal but they didn't work.

Post what you tried and explain what went wrong

No problem. For the boolean flag method, I tried the following and kept it very simple. However, it prints "CARD PRESENT" the whole time.

I followed the example in the post by @OldSteve here:
https://forum.arduino.cc/index.php?topic=412979.0

#include <SPI.h>
#include <MFRC522.h>
#define SS_PIN 10
#define RST_PIN 9
MFRC522 mfrc522(SS_PIN, RST_PIN);   // Create MFRC522 instance.

bool doneFlag = false;


void setup() {
  Serial.begin(115200); // Open serial monitor at 115200 baud to see ping results.  
  SPI.begin();      // Initiate  SPI bus
  mfrc522.PCD_Init();   // Initiate MFRC522
}

void loop(){
  if (doneFlag == false) {
    if ( ! mfrc522.PICC_IsNewCardPresent()) {
      Serial.println("NO CARD");
    }
    doneFlag = true;
  }
  Serial.println("CARD PRESENT");  
  
  mfrc522.PICC_HaltA();          // Halt PICC
  mfrc522.PCD_StopCrypto1();     // Stop encryption on PCD    
}

The other method I tried is since deleted. I'll try and replicate it.

UKHeliBob:
Post what you tried and explain what went wrong

And here is the other method. It works but prints continually. Thanks in advance for any tips :slight_smile:

#include <SPI.h>
#include <MFRC522.h>
#define SS_PIN 10
#define RST_PIN 9
MFRC522 mfrc522(SS_PIN, RST_PIN);   // Create MFRC522 instance.

char* instrumentUIDs[] = {"E6 7A 78 89", "67 10 DB 2B", "54 8F DA 2B", "84 C2 BE 1E", "A7 0B 75 F2"};

bool doneFlag = false;

//*****************************************************************************************//
void setup() {
  Serial.begin(115200); // Open serial monitor at 115200 baud to see ping results.  
  SPI.begin();      // Initiate  SPI bus
  mfrc522.PCD_Init();   // Initiate MFRC522
}

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

 if ( ! mfrc522.PICC_IsNewCardPresent())
 {
    delay(50);
  if ( ! mfrc522.PICC_IsNewCardPresent())
  {
    delay(50);
    Serial.println("NO CARD PRESENT"); 
    return;
    }
  }

 Serial.println("CARD PRESENT"); 

  mfrc522.PICC_HaltA();          // Halt PICC
  mfrc522.PCD_StopCrypto1();     // Stop encryption on PCD
}

it prints "CARD PRESENT" the whole time.

You have no logic to prevent that

Print the status message when the card present status becomes true or false rather than when it is true or false

Look at the StateChangeDetection example in the IDE to see how to detect such a change

Okay, thanks. I'm looking at that example now but I don't get how to apply that to this situation? Is there an example somewhere that uses true or false... or are suggesting a totally different method? Sorry.

UKHeliBob:
You have no logic to prevent that

Print the status message when the card present status becomes true or false rather than when it is true or false

Look at the StateChangeDetection example in the IDE to see how to detect such a change

Yes, that's worked. Thanks so much. Sorry I was initially confused about the numerics in the example given the need for true/false.

Thanks so much for taking the time to help a brother out :slight_smile:

Here's the fix:

#include <SPI.h>
#include <MFRC522.h>
#define SS_PIN 10
#define RST_PIN 9
MFRC522 mfrc522(SS_PIN, RST_PIN);   // Create MFRC522 instance.

//bool doneFlag = false;
bool CurrentCardPresentStatus = false;         // current state of the button
bool lastCardPresentStatus = false;     // previous state of the button

void setup() {
  Serial.begin(115200); // Open serial monitor at 115200 baud to see ping results.  
  SPI.begin();      // Initiate  SPI bus
  mfrc522.PCD_Init();   // Initiate MFRC522
}



void loop(){

  CurrentCardPresentStatus = mfrc522.PICC_IsNewCardPresent();

  if (CurrentCardPresentStatus != lastCardPresentStatus) {
    
    if (CurrentCardPresentStatus == true) {
      // if the card is detected
      Serial.println("CARD PRESENT");  
    } else {
      Serial.println("NO CARD");  
    }
  }
  lastCardPresentStatus = CurrentCardPresentStatus;
    
  mfrc522.PICC_HaltA();          // Halt PICC
  mfrc522.PCD_StopCrypto1();     // Stop encryption on PCD    
}

Oh dear. Now that I've expanded that code into my larger example, I am having issues.

Using the code below, I can detect once a card is taken away. But I now don't have access to the UID size so cannot reach the "CARD DETECTED" line in the 'ObjectTagChecker' function.

However, if I uncomment the 'mfrc522.PICC_ReadCardSerial();' line within that function, I can access it... but then "CARD DETECTED" & "NO CARD PRESENT" print every time a card is placed on the reader.

#include <SPI.h>
#include <MFRC522.h>
#define SS_PIN 10
#define RST_PIN 9
MFRC522 mfrc522(SS_PIN, RST_PIN);   // Create MFRC522 instance.

char* instrumentUIDs[] = {"E6 7A 78 89", "67 10 DB 2B", "54 8F DA 2B", "84 C2 BE 1E", "A7 0B 75 F2"};

bool CurrentCardPresentStatus = false;         // current state of the button
bool lastCardPresentStatus = false;     // previous state of the button


//****************************************************************************** 
void setup() {
  Serial.begin(9600);   // Initiate a serial communication  
  SPI.begin();      // Initiate  SPI bus
  mfrc522.PCD_Init();   // Initiate MFRC522
}


//******************************************************************************
void loop(){
  
  CurrentCardPresentStatus = mfrc522.PICC_IsNewCardPresent();

  if (CurrentCardPresentStatus != lastCardPresentStatus) {

    if (CurrentCardPresentStatus == true) {
      ObjectTagChecker();
      
    }  else {
      Serial.println("NO CARD PRESENT");  
    }    
  }
  lastCardPresentStatus = CurrentCardPresentStatus;

  //Serial.print(mfrc522.uid.size);    
  mfrc522.PICC_HaltA();          // Halt PICC
  mfrc522.PCD_StopCrypto1();     // Stop encryption on PCD    
}


//******************************************************************************
void ObjectTagChecker() {  
  
  //mfrc522.PICC_ReadCardSerial();
  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();
  
  for (int i = 0; i < (sizeof(instrumentUIDs)/2); i++) { 
    if (content.substring(1) == instrumentUIDs[i]) {   
      Serial.println("CARD DETECTED");                    
    } 
  }  
}

Anyone able to advise on how to do this? :blush: Thanks so much :slight_smile:

I suspect that you're going to have to dig into the library a bit. From what you're seeing, I assume that the readcardserial call means that the card is no longer considered new. You may well need to use the lower level functions to get & keep the id so you can tell whether the same one is still there.

disclaimer - have never used that library, so I'm really just guessing.

wildbill:
I suspect that you're going to have to dig into the library a bit. From what you're seeing, I assume that the readcardserial call means that the card is no longer considered new. You may well need to use the lower level functions to get & keep the id so you can tell whether the same one is still there.

disclaimer - have never used that library, so I'm really just guessing.

Thanks for your input, Bill. I eventually solved it with the following code:

#include <MFRC522.h>
#define SS_PIN 10
#define RST_PIN 9
MFRC522 mfrc522(SS_PIN, RST_PIN);   // Create MFRC522 instance.

char* instrumentUIDs[] = {"E6 7A 78 89", "67 10 DB 2B", "54 8F DA 2B", "84 C2 BE 1E", "A7 0B 75 F2", "97 08 75 F2"};

void setup() {
  Serial.begin(115200); // Open serial monitor at 115200 baud to see ping results.  
  SPI.begin();      // Initiate  SPI bus
  mfrc522.PCD_Init();   // Initiate MFRC522
  Serial.println("Approximate your card to the reader...");
  Serial.println();
}


void loop(){
  // Look for new cards
  if ( !mfrc522.PICC_IsNewCardPresent()) {
    Serial.println("No Card");
    return;
  }
  if ( !mfrc522.PICC_ReadCardSerial()) {
    return;
  }

  if ( !mfrc522.PICC_IsNewCardPresent()) { // ****************
    ObjectTagChecker();
  } 
 
  mfrc522.PICC_HaltA();          // Halt PICC
  mfrc522.PCD_StopCrypto1();     // Stop encryption on PCD  
} 


void ObjectTagChecker() {    
  String content= "";
  byte letter;
  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();  

  for (int i = 0; i < (sizeof(instrumentUIDs)/2); i++) {  // UNIVERSAL MIDI, DONT NEED CHANGE MIDI NUMBER - Just change midi input on indiv ableton tracks! - ONLY FOR THE TRIGGIN OF CLIPS BELOW!
    if (content.substring(1) == instrumentUIDs[i]) {       
      Serial.print("Card Present: Item number ");
      Serial.print(i);
      Serial.println(" has been selected");               
    } 
  }       
}

Good to know - it's nice to get closure on threads.