OSSLibraries / Arduino_MFRC522v2

Home Page:https://osslibraries.github.io/Arduino_MFRC522v2/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Issue while reading RFID and detect removal

ScreamZ opened this issue · comments

Step 1: Describe your environment

  • OS version: N/A
  • Arduino IDE version: 2.2.1
  • MFRC522 Library version: 2.0.4
  • Arduino device: UNO
  • MFRC522 device: Standard blue card?

The Arduino was tested with VIN on 5V and then VIN on 10V. It's powered by VIN.

Step 2: Describe the problem

Affected file(s) or example(s):

#include <MFRC522v2.h>
#include <MFRC522DriverSPI.h>
#include <MFRC522DriverPinSimple.h>
#include <MFRC522Debug.h>

#define ENABLE_SERIAL
#define SS_PIN 10
#define RST_PIN 9
#define SIGNAL_PIN 7 // To propagate information to firmata arduino High is Valid medal detected Low otherwise
#define REFRESH_DELAY 500

byte MedalID[4] = {0x13, 0x76, 0x8E, 0x31}; // The ID to check for the medal
bool cardRemoved = false;
int counter = 0;
bool current, previous;

MFRC522DriverPinSimple ss_pin(10);
MFRC522DriverSPI driver{ss_pin};
MFRC522 mfrc522{driver};

void setup()
{
#ifdef ENABLE_SERIAL
  // Init RS232
  Serial.begin(115200);
  Serial.println("Initialization");
#endif

  // Init SPI bus
  SPI.begin();

  // Init MFRC522
  mfrc522.PCD_Init();

  // Init signal gate
  pinMode(SIGNAL_PIN, OUTPUT);
  pinMode(A0, OUTPUT);
  digitalWrite(SIGNAL_PIN, LOW);
}

void loop()
{
  blinkLED();
  // Look for new cards
  if (!mfrc522.PICC_IsNewCardPresent())
  {
#ifdef ENABLE_SERIAL
    Serial.println("Skipping, no new card present.");
#endif
    return;
  }
  if (!mfrc522.PICC_ReadCardSerial())
  {
#ifdef ENABLE_SERIAL
    Serial.println("Skipping, unable to read card.");
#endif
    return;
  }

#ifdef ENABLE_SERIAL
  Serial.print("New RFID detected : ");
  PrintHex(mfrc522.uid.uidByte, mfrc522.uid.size);
  Serial.println("");
#endif

  digitalWrite(SIGNAL_PIN, VerifyRFID(MedalID, mfrc522.uid.uidByte) ? HIGH : LOW);

  // Check if Card was removed
  cardRemoved = false;
  counter = 0;

  previous = !mfrc522.PICC_IsNewCardPresent();

  while (!cardRemoved)
  {
    current = !mfrc522.PICC_IsNewCardPresent();

    if (current && previous)
      counter++;

    previous = current;
    cardRemoved = (counter > 2);
  }

#ifdef ENABLE_SERIAL
  Serial.println("RFID was removed");
#endif
  digitalWrite(SIGNAL_PIN, LOW);
  mfrc522.PICC_HaltA();
}

bool VerifyRFID(byte *RequiredID, byte *CheckedID)
{
  if ((RequiredID[0] == CheckedID[0]) && (RequiredID[1] == CheckedID[1]) && (RequiredID[2] == CheckedID[2]) && (RequiredID[3] == CheckedID[3]))
    return true;
  else
    return false;
}

#ifdef ENABLE_SERIAL
void PrintHex(uint8_t *data, uint8_t length) // prints 8-bit data in hex with leading zeroes
{
  char tmp[16];
  for (int i = 0; i < length; i++)
  {
    sprintf(tmp, "0x%.2X", data[i]);
    Serial.print(tmp);
    Serial.print(" ");
  }
}
#endif

const int ledPin = A0;            // The pin the LED is connected to
int ledState = LOW;               // Tracks the state of the LED
unsigned long previousMillis = 0; // Will store last time LED was updated
const long interval = 1000;       // Interval at which the LED should blink (milliseconds
void blinkLED()
{
  unsigned long currentMillis = millis(); // Get the current time

  if (currentMillis - previousMillis >= interval)
  {
    // Save the last time the LED blinked
    previousMillis = currentMillis;

    if (ledState == LOW)
    {
      ledState = HIGH; // If the LED is off, turn it on
    }
    else
    {
      ledState = LOW; // If the LED is on, turn it off
    }

    digitalWrite(ledPin, ledState); // Apply the LED state
  }
}

Observed Results:

The above code is working well but after some time (in minutes, hard to guess) seems to always return a LOW signal on SIGNAL_PIN. I added some test code with a blinking LED to detect whether it's stuck on the while clause or elsewhere. It seems that it's stuck after some time on if (!mfrc522.PICC_IsNewCardPresent()) as the LED keeps blinking, no matter if I move or not the RFID close to the sensor. When I restart the Arduino, things work again.

EDIT:
After some investigation, it looks like if it stays too long in the while loop, it goes back to the start of the loop function and never quits isNewCardPresent condition resulting in LOW signal
EDIT2: : Even out of the while loop (when a card is present waiting for removal), it goes into LOW signal

Expected Results:

When an RFID is read and as long it's not removed, I want to put my SIGNAL_PIN to HIGH. When it's removed or when the ID doesn't match my MedalID I want the SIGNAL_PIN to be low.

I don't like the way I'm forced to check card removal, and this random isNewCardPresent returning value is really annoying.

Am I supposed to use PICC_HaltA somewhere else ? Adding some pause time like 150 ms at begin of the loop doesn't seem to change the problem

Here is my new code:

/**
 * Detect when a PICC (that is: a RFID Tag or Card) is present and when it is
 * removed from the field of detection using a MFRC522 based RFID Reader on the Arduino SPI interface.
 *
 * When the Arduino and the MFRC522 module are connected (see the pin layout below), load this sketch into Arduino IDE
 * then verify/compile and upload it. To see the output: use Tools, Serial Monitor of the IDE (hit Ctrl+Shft+M). When
 * you present a PICC (that is: a RFID Tag or Card) at reading distance of the MFRC522 Reader/PCD, the serial output
 * will show the NUID and report that it is "locked" onto that PICC. No other PICC will be detected until that one is
 * removed. The program will print "unlocked" when the card is not detected any more.
 * If a new card enters the range while locked into another card, it will be ignored, but it will be detected as soon
 * as the locked one is removed, and that will be the new locked card.
 *
 * Typical pin layout used:
 * -----------------------------------------------------------------------------------------
 *             MFRC522      Arduino       Arduino   Arduino    Arduino          Arduino
 *             Reader/PCD   Uno/101       Mega      Nano v3    Leonardo/Micro   Pro Micro
 * Signal      Pin          Pin           Pin       Pin        Pin              Pin
 * -----------------------------------------------------------------------------------------
 * RST/Reset   RST          9             5         D9         RESET/ICSP-5     RST
 * SPI SS      SDA(SS)      10            53        D10        10               10
 * SPI MOSI    MOSI         11 / ICSP-4   51        D11        ICSP-4           16
 * SPI MISO    MISO         12 / ICSP-1   50        D12        ICSP-1           14
 * SPI SCK     SCK          13 / ICSP-3   52        D13        ICSP-3           15
 *
 * More pin layouts for other boards can be found here: https://github.com/miguelbalboa/rfid#pin-layout
 */

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

#define SS_PIN 10
#define RST_PIN 9
#define SIGNAL_PIN 7                        // The pin that will be used to signal the medal presence and validation to the rest of the system
byte MedalID[4] = {0x13, 0x76, 0x8E, 0x31}; // The ID to check for the medal

MFRC522 rfid(SS_PIN, MFRC522::UNUSED_PIN); // Disable RST Pin, which seems to be glitchy and fallback to software reset see https://github.com/miguelbalboa/rfid/issues/540#issuecomment-1807872461

bool locked = false;

void setup()
{
  Serial.begin(9600);
  SPI.begin();     // Init SPI bus
  rfid.PCD_Init(); // Init MFRC522
  pinMode(SIGNAL_PIN, OUTPUT);
  digitalWrite(SIGNAL_PIN, LOW); // Init signal gate
  delay(4);

  // Clear the information stored about locked cards.
  rfid.uid.size = 0;
}

void loop()
{
  // Wake up all cards present within the sensor/reader range.
  bool cardPresent = rfid.PICC_IsNewCardPresent();

  // Reset the loop if no card was locked an no card is present.
  // This saves the select process when no card is found.
  if (!locked && !cardPresent)
    return;

  // When a card is present (locked) the rest ahead is intensive (constantly checking if still present).
  // Consider including code for checking only at time intervals.

  // Ask for the locked card (if rfid.uid.size > 0) or for any card if none was locked.
  // (Even if there was some error in the wake up procedure, attempt to contact the locked card.
  // This serves as a double-check to confirm removals.)
  // If a card was locked and now is removed, other cards will not be selected until next loop,
  // after rfid.uid.size has been set to 0.
  MFRC522::StatusCode result = rfid.PICC_Select(&rfid.uid, 8 * rfid.uid.size);

  if (!locked && result == MFRC522::STATUS_OK)
  {
    locked = true;
    // Action on card detection.
    Serial.print(F("locked! NUID tag: "));
    printHex(rfid.uid.uidByte, rfid.uid.size);
    digitalWrite(SIGNAL_PIN, VerifyRFID(MedalID, rfid.uid.uidByte) ? HIGH : LOW);
    Serial.println();
  }
  else if (locked && result != MFRC522::STATUS_OK)
  {
    locked = false;
    rfid.uid.size = 0;
    // Action on card removal.
    digitalWrite(SIGNAL_PIN, LOW);
    Serial.print(F("unlocked! Reason for unlocking: "));
    Serial.println(rfid.GetStatusCodeName(result));
  }
  else if (!locked && result != MFRC522::STATUS_OK)
  {
    // Clear locked card data just in case some data was retrieved in the select procedure
    // but an error prevented locking.
    digitalWrite(SIGNAL_PIN, LOW);
    rfid.uid.size = 0;
  }

  rfid.PICC_HaltA();
}

/**
 * Helper routine to dump a byte array as hex values to Serial.
 */
void printHex(byte *buffer, byte bufferSize)
{
  for (byte i = 0; i < bufferSize; i++)
  {
    Serial.print(((buffer[i]) >> 4) & 0x0F, HEX);
    Serial.print(buffer[i] & 0x0F, HEX);
    Serial.print(" ");
  }
}

/**
 * Ensure the checked medal is the valid RFID tag we are looking for.
 */
bool VerifyRFID(byte *RequiredID, byte *CheckedID)
{
  if ((RequiredID[0] == CheckedID[0]) && (RequiredID[1] == CheckedID[1]) && (RequiredID[2] == CheckedID[2]) && (RequiredID[3] == CheckedID[3]))
    return true;
  else
    return false;
}

I've tried to remove RST Pin, and fallback to the software. Just like this library does.
When using a RST pin, it does the same thing.

I can observe that when I'm plugged to the serial port, reading the printed line, it seems to always work, even after a few minutes.
Without serial port, it never detect card again