RFID Scan Stops Working After the First Loop

Hi, I've searched all through this forum and google to no avail. I am trying to use an RFID card to open and close a small door. Everything works just fine on the very first loop, but then the RFID scanner (RC522) stops working. It won't detect the same card/tag, or even a different one. I have tried 4 different unique cards and tags and same thing. If I reset the MEGA board via the reset button, it will once again work on the very first try.

Here is a snapshot of my project:
Board: Elegoo Mega
RFID Module: RC522

Exact Physical Wiring As I Have It:

RFID Module Pin Layout (RC522)
SDA - Digital Pin 53
SCK - Digital Pin 52
MOSI - Digital Pin 51
MISO - Digital Pin 50
IRQ - Not Used
GND - GND Pin on Board
RST - Digital Pin 5
3.3V - 3.3V Pin on Board

LCD Display Pin Layout (LCD1602)
VSS - GND on Breadboard
VDD - 5V on Breadboard
VO - Output from 10k Potentiometer
RS - Digital Pin 7
RW - GND on Breadboard
E - Digital Pin 8
D0-D3 - Not Used
D4 - Digital Pin 9
D5 - Digital Pin 10
D6 - Digital Pin 11
D7 - Digital Pin 12
A - 5V on Breadboard
K - GND on Breadboard

10k Potentiometer
Input Pin 1 - 5V on Breadboard
Input Pin 2 - GND on Breadboard
Output Pin 1 - VO on LCD

Switch
Pin 1 - 5V on Breadboard
Pin 2 - GND with 10k Resistor in series

Passive Buzzer
Pin 1 - GND on Breadboard
Pin 2 - Digital Pin 2

Green LED
Pin 1 - GND on Breadboard
Pin 2 - Digital Pin 3 with 200Ohm resistor in series

Red LED
Pin 1 - GND on Breadboard
Pin 2 - Digital Pin 4 with 200Ohm resistor in series

Motor Driver Board (ULN2003)
In1 - Digital Pin 22
In2 - Digital Pin 24
In3 - Digital Pin 26
In4 - Digital Pin 28
Neg - GND on Breadboard
Pos - 5V on Breadboard
ABCD Connector to Stepper Motor (28BYJ-48)

MEGA GND Pin - GND on Breadboard
MEGA 5V Pin - 5V on Breadboard

Here is my Sketch:

#include <MFRC522.h>
// include the library code for the liquid crystal display:
#include <LiquidCrystal.h>
//include the library code for the passive buzzer:
#include "pitches.h"
//include the library code for the stepper motor:
#include <Stepper.h>

const int stepsPerRevolution = 2048;  // change this to fit the number of steps per revolution
const int rolePerMinute =17;         // Adjustable range of 28BYJ-48 stepper is 0~17 rpm

#define BUZZER 2 //buzzer pin
#define LED_G 3 //define green LED pin
#define LED_R 4 //define red LED
#define RST_PIN 5
#define SS_PIN 53
int Btn = 6;

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
// initialize the stepper library on pins 22 through 25:
Stepper myStepper(stepsPerRevolution, 22, 26, 24, 28);

MFRC522 mfrc522(SS_PIN, RST_PIN);   // Create MFRC522 instance.

void setup() {
  // put your setup code here, to run once:
  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(BUZZER, OUTPUT);
  noTone(BUZZER);
  pinMode(Btn,INPUT);
  Serial.println();
  Serial.println("Place your card on reader...");
  Serial.println();
  lcd.begin(16, 2);
  lcd.clear();
  lcd.setCursor(0,0); // column, row
  lcd.print(" Scan Your RFID "); 
  lcd.setCursor(0,1); // column, row
  lcd.print("   Door Closed   ");
  myStepper.setSpeed(rolePerMinute);
}

void loop() {
  // put your main code here, to run repeatedly:
  //This code below is for when the button is pressed.
  if(digitalRead(Btn) == HIGH){
      Serial.println("Access Granted");
      Serial.println();
      delay(500);
      digitalWrite(LED_G, HIGH);
      lcd.setCursor(0,1); // column, row
      lcd.print(" Door Open ");
      tone(BUZZER, 2000);
      delay(100);
      noTone(BUZZER);
      delay(50);
      tone(BUZZER, 2000);
      delay(100);
      noTone(BUZZER);
      myStepper.step(stepsPerRevolution);
      delay(3000);
      myStepper.step(-stepsPerRevolution);
      delay(100);
      digitalWrite(LED_G, LOW);
      lcd.setCursor(0,1); // column, row
      lcd.print("   Door Closed   ");
      tone(BUZZER, 2000);
      delay(100);
      noTone(BUZZER);
      delay(50);
      Serial.println("if statement for button...");
    }

  //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) == "6F 38 63 1E") //change here the UID of card/cards or tag/tags that you want to give access
  {
    Serial.println("Access Granted");
    Serial.println();
    delay(500);
    digitalWrite(LED_G, HIGH);
    lcd.setCursor(0,1); // column, row
    lcd.print(" Door Open ");
    tone(BUZZER, 2000);
    delay(100);
    noTone(BUZZER);
    delay(50);
    tone(BUZZER, 2000);
    delay(100);
    noTone(BUZZER);
    myStepper.step(stepsPerRevolution);
    delay(4000);
    myStepper.step(-stepsPerRevolution);
    delay(4000);
    digitalWrite(LED_G, LOW);
    lcd.setCursor(0,1); // column, row
    lcd.print("   Door Closed   ");
    tone(BUZZER, 2000);
    delay(100);
    noTone(BUZZER);
    delay(50);
    Serial.println();
    Serial.println("Place your card on reader...");
    Serial.println();
  }

  else
  {
    lcd.setCursor(0,1); // column, row
    lcd.print("Invalid RFID Tag");
    Serial.println(" Access denied");
    digitalWrite(LED_R, HIGH);
    tone(BUZZER, 1500);
    delay(500);
    digitalWrite(LED_R, LOW);
    noTone(BUZZER);
    delay(100);
    digitalWrite(LED_R, HIGH);
    tone(BUZZER, 1500);
    delay(500);
    digitalWrite(LED_R, LOW);
    noTone(BUZZER);
    delay(100);
    digitalWrite(LED_R, HIGH);
    tone(BUZZER, 1500);
    delay(500);
    digitalWrite(LED_R, LOW);
    noTone(BUZZER);
    lcd.setCursor(0,1); // column, row
    lcd.print("   Door Closed   ");
    Serial.println();
    Serial.println("Place your card on reader...");
    Serial.println();
 }

}

Here is an example of what is shown in the Serial Monitor Window after running it once:

Place your card on reader...

UID tag : 6F 38 63 1E
Message : Access Granted

Place your card on reader...

After this point, like I mentioned it will no longer scan another card or tag. It's hung up somewhere and I can't figure out where it is. Thanks for any advice.

Here is a picture of my setup:

I believe that after each successful call to PICC_ReadCardSerial() you need a call to PICC_HaltA().

And no doubt someone will be along anytime now to spread the word on the badness of using String. Off the top of my head, you can accomplish the same thing w/o fragmenting your heap memory a couple of ways:

if (mrfc522.uic.uidByte[0] == 0x6F && mrfc522.uic.uidByte[1] == 0x38  && mrfc522.uic.uidByte[2] == 0x63 && mrfc522.uic.uidByte[3] == 0x1E) {
.
.
.
const uint8_t desiredUID[] = {0x6F, 0x38, 0x63, 0x1E};
.
.
.
if ( !memcmp(mfrc522.uid.uidByte, desiredUID, sizeof desiredUID)) {
.
.
.

Thanks for your reply. I've tried putting the PICC_HaltA() in different parts of the code (inside the if/else loops) and at the very end of the code just after the else loop, and I get the same result. I'm new to coding, so I'm not sure if the statement needs to be put in a certain spot for it to work properly.

Regarding the "String" command, I'm not sure I understand what is bad about using it? I will do some searching on that topic and thank you for your suggestions on how to replace it.

Since I happened to have an RC522 and an OLED already wired up to an Uno, I decided to give your code a try. After replacing the LCD code with the OLED equivalents, it ran. And worked. And kept on working. It detected the proper card and "opened the door" as many times as I cared to try, and rejected an invalid one. Hmm.

Looking at your hookup, it appears that you've got the RC522 wired directly to the Mega. A 3.3V peripheral hooked up to 5V signals will never end happily. The RC522 is not 5V compliant. I'm aware that there are umpteen examples on the web showing just such a hookup and claiming that it's fine, it'll work, no problem. The datasheet says otherwise. I urge you to look it up and see for yourself. I use a 74AHC125 to do the level shifting and as evidenced by the fact that your sketch worked with no changes to the RC522 code... well, you can draw your own conclusions.

That is very interesting indeed. I do have the RC522 wired directly to the MEGA, but I am using the 3.3V Pin on the MEGA board. I made sure of this as I saw other posts mention this caution. I also ensured that it was in fact 3.3V using a multimeter before connecting it for the first time.

Thanks for checking it with your setup! I'll keep tinkering around to see what it may be on my end.

@van_der_decken I just wanted to thank you for your help! I followed your recommendations by using a few resistors to essentially lower the voltage at each pin to the RC522 RFID reader module. For others who may run into this issue in the future, look up Voltage Dividers and Level Shifting to get an idea of how this works.

For my specific example, I ended up using 3 resistors for each Digital Pin that feeds into the RC522 module. The first R1 = 1k Ohms and the second was R2 = 440 Ohms. I had to use two 220 Ohm resistors in series to achieve the 440 Ohms. Using Vout = Vin * (R1 / (R1 + R2)), I was able to supply the RC522 module with about 3.47V (with Vin = 5, R1 = 1k, R2 = 440).

After doing this, my code is working as intended. Thanks to this wonderful community for the support! I'll include a picture of how I did this.

Adding some documentation that should help with this topic:

Note the following from the Github page:

Arduino UNO/Nano/Mega operates at 5V logic. However, the MFRC522 works at 3.3V logic level, and is not 5V tolerant. If using one of these microprocessors:

  • You must use a 5V <-> 3.3V level shifter on any lines that send HIGH output from the Arduino to the MFRC522. These are RST, NSS (SDA), MOSI, and SCK marked with an asterisk in the list above.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.