Arduino MFRC522 RFID Continuous Reading

Hi,

I'm trying to make use of the MFRC522 card reader and tags to enable a relay and some LEDS, the code is doing all what I need it to do on the hardware side, enabling the correct outputs etc. and can read the tags no issue. But I cannot figure out how to program the code to keep the outputs high whenever a saved card/tag is present and then set outputs low with a 10 second delay after the card is removed. I'm sure it must be possible but I cannot figure this out and it is getting really frustrating.

Please see code below that works fine and does the job but with an off delay after the card is read and authorised. The delay just isn't ideal for the application. Removing the card to stop the relay output is really what is needed.

Any Help on this would be much appreciated.

Many Thanks
Dan

#include <SPI.h>
#include <MFRC522.h>
 
#define SS_PIN 10
#define RST_PIN 9
#define LED_G 6 //define green LED pin
#define RELAY 5 //Relay out
#define LED_G2 4 //Green LED
#define LED_R 3//define red LED
#define Access_Delay 1000UL*10
#define DENIED_DELAY 1000
MFRC522 mfrc522(SS_PIN, RST_PIN);   // Create MFRC522 instance.
 
void setup() 
{
  Serial.begin(9600);   // Initiate a serial communication
  SPI.begin();          // Initiate  SPI bus
  mfrc522.PCD_Init();   // Initiate MFRC522
  pinMode(LED_G, OUTPUT);
  pinMode(LED_R, OUTPUT);
  pinMode(RELAY, OUTPUT);
  pinMode(LED_G2, OUTPUT);
  digitalWrite(RELAY, LOW);
  Serial.println("Put your card to the reader...");
  Serial.println();

}
void loop() 
{
  // Look for new cards
  if ( ! mfrc522.PICC_IsNewCardPresent()) 
  {
    return;
  }
  // Select one of the cards
  if ( ! mfrc522.PICC_ReadCardSerial()) 
  {
    return;
  }
  //Show UID on serial monitor
  Serial.print("UID tag :");
  String content= "";
  byte letter;
  for (byte i = 0; i < mfrc522.uid.size; i++) 
  {
     Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
     Serial.print(mfrc522.uid.uidByte[i], HEX);
     content.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "));
     content.concat(String(mfrc522.uid.uidByte[i], HEX));
  }
  Serial.println();
  Serial.print("Message : ");
  content.toUpperCase();
  if (content.substring(1) == "99 83 9D A3" || content.substring(1) == "09 13 8F A3" || content.substring(1) == "D9 35 9C A2" || content.substring(1) == "79 AB 6A C2") //change here the UID of the card/cards that you want to give access
  {
    Serial.println("Authorized access");
    Serial.println("Card Present");
    digitalWrite(RELAY, HIGH);
    digitalWrite(LED_G, HIGH);
    digitalWrite(LED_G2, HIGH);
  **Whilst the card is present and being read, Keep these outputs above high until the RFID card is removed then the access delay below will trigger and the program continues.**
    delay (Access_Delay);
    digitalWrite(RELAY, LOW);
    digitalWrite(LED_G, LOW);
    digitalWrite(LED_G2, LOW);
  }
 else   {
    Serial.println(" Access denied");
    digitalWrite(LED_R, HIGH);
    delay(DENIED_DELAY);
    digitalWrite(LED_R, LOW);
  }
}

Welcome to the forum

Please follow the advice given in the link below when posting code, in particular the section entitled 'Posting code and common code problems'

Use code tags (the < CODE/ > icon above the compose window) to make it easier to read and copy for examination

You need "states" (like a verb, "states of being")

If card is present, make variable "state = 1"... if "state = 1", immediately set output high
if card is absent, make variable "state = 0"... if "state = 0", wait 10 seconds, then set outputs low

That's great but are you able to give and example of this in the code I have please? I can see exactly what you mean I'm just not sure and where exactly this would be written in. I have tried many other ways including, mfrc522.PICC_HaltA this again doesnt yield the required result.
Thanks,
Dan.

I just put this in a simulator... and it seems all you want/need is to have the 'delay(access_delay)` removed, so that when the "good" card is remove, the relay stops being actuated.

Starting with this... use of "**" is incorrect...

  **Whilst the card is present and being read, Keep these outputs above high until the RFID card is removed then the access delay below will trigger and the program continues.**

I understand this is your comment to the person reading, but it you should use correct syntax... two "solidus" (slant, forward-slash) mark "start of comment" to compilers and the people reading.

  // Whilst the card is present and being read, Keep these outputs above high until the RFID card is removed then the access delay below will trigger and the program continues.**

Here is a simulation with a "bad" card:

Here is a simulation with my added "good" card and I "tapped" and "held" the card:

Here is with the "good" card, but "tapped" and "removed" the card:

Here is your code, with two edits:

  1. I added a "good" card for the simulator (see comments)
  2. I removed (commented-out) the delay(access_delay) line

// I made a big mistake... see update code below...

It isn't pretty... and can be improved... but your code "works."

I missed an observation on that code.... forgot to check and release when the good card is gone... here is the new "still ugly, but works" code

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

#define SS_PIN 10
#define RST_PIN 9
#define LED_G 6 //define green LED pin
#define RELAY 5 //Relay out
#define LED_G2 4 //Green LED
#define LED_R 3//define red LED
#define Access_Delay 1000UL*10
#define DENIED_DELAY 1000
MFRC522 mfrc522(SS_PIN, RST_PIN);   // Create MFRC522 instance.

bool goodcard = 0;

void setup()
{
  Serial.begin(9600);   // Initiate a serial communication
  SPI.begin();          // Initiate  SPI bus
  mfrc522.PCD_Init();   // Initiate MFRC522
  pinMode(LED_G, OUTPUT);
  pinMode(LED_R, OUTPUT);
  pinMode(RELAY, OUTPUT);
  pinMode(LED_G2, OUTPUT);
  digitalWrite(RELAY, LOW);
  Serial.println("Put your card to the reader...");
  Serial.println();

}
void loop()
{
  // Look for new cards
  if ( ! mfrc522.PICC_IsNewCardPresent())
  {
    return;
  }
  // Select one of the cards
  if ( ! mfrc522.PICC_ReadCardSerial())
  {
    return;
  }
  //Show UID on serial monitor
  Serial.print("UID tag :");
  String content = "";
  byte letter;
  for (byte i = 0; i < mfrc522.uid.size; i++)
  {
    Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
    Serial.print(mfrc522.uid.uidByte[i], HEX);
    content.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "));
    content.concat(String(mfrc522.uid.uidByte[i], HEX));
  }
  Serial.println();
  Serial.print("Message : ");
  content.toUpperCase();

  // ADDED FIRST "BLUE" CARD "01:02:03:04	MIFARE Classic 1K" for simulation

  if (goodcard == 0 && content.substring(1) == "01 02 03 04" || content.substring(1) == "99 83 9D A3" || content.substring(1) == "09 13 8F A3" || content.substring(1) == "D9 35 9C A2" || content.substring(1) == "79 AB 6A C2") //change here the UID of the card/cards that you want to give access
  {
    Serial.println("Authorized access");
    Serial.println("Card Present");
    digitalWrite(RELAY, HIGH);
    digitalWrite(LED_G, HIGH);
    digitalWrite(LED_G2, HIGH);
    goodcard = 1;

    // Whilst the card is present and being read, Keep these outputs above high until the RFID card is removed then the access delay below will trigger and the program continues.**
  }  else   {
    if (goodcard == 1) {
      goodcard = 0; // reset goodcard
      // delay (Access_Delay); // <-- remove this DELAY
      digitalWrite(RELAY, LOW);
      digitalWrite(LED_G, LOW);
      digitalWrite(LED_G2, LOW);
    } else {
      Serial.println(" Access denied");
      digitalWrite(LED_R, HIGH);
      delay(DENIED_DELAY);
      digitalWrite(LED_R, LOW);
    }
  }
}

Hi, Thanks for this. Its odd that it works in your simulation but still doesn't work with my actual setup. Its like the card reader resets or stops reading and restarts every time it has read the card. Instead of actually just keeping the reader continuously reading. But again cannot find anything in the RC522 library to do this. I doubt this has anything to do with it, but I'm using the little fobs rather than a card to the reader? It was to be cards but the fobs are better for the application. What a pain this is becoming.

Just to add, the only way to reset/turn off the relay is to use an unauthorised card. I'm baffled as to why this worked in the simulator but not on my hardware.

Be baffled no more, a simulator does not take into account everything with respect to the hardware.

So how have you wired up your hardware?

There is a problem driving a 3V3 chip with a 5V system. Almost all of the internet gets this wrong, but this is what you need to do:-

Note you might have already damaged your hardware.

Thanks Mike for your input. I have tried all of what you have sent with new hardware and still no joy. In fact the reader does not work at all. So im still baffled on this. Im starting to wonder if this is even possible? might have to look down a different route.

All that I want to do, is place an RFID card on the reader, read the card, enable a relay and green led whilst the card that is on the reader is authorised. (Save about X5 RFID codes in the code that are authorised.) Keep the relay and green led on whilst the authorised card is still on the reader and when the card is removed, switch off the relay and led after a 10 second delay.

Unauthorised cards will activate a red led when placed on the reader.

If anyone can help with this or has any other suggestions this would be much appreciated.

Many Thanks,
Dan.

Reading around the internet, it seems the reader will be stuck in "authorized" until "new card" happens. The suggestions seem to point toward "cycling" the reader in and out of sleep mode with...

PICC_IsNewCardPresent () // see new card
PICC_ReadCardSerial () // get/store card data
.
.
// card is authorized
PICC_HaltA () // put card to sleep
.
.
PICC_WakeupA () // if wakeup is successful, a card is present
  // card present, so try some delay AND keep LEDs/relays ON
  PICC_HaltA () // back to sleep
else // wakeup failed, no card present
 // go to IsNewCardPresent()