Problem with the RC522.

So, I’m working on a project for a game, which has 10 LEDs that track the power a battery has. I want to be able to swipe an RFID card in order to raise or lower the battery, or put the battery into an error mode. It also has a 1602 LCD screen to spit out error codes and whatnot.

The issue I’m having is, every now and then, the RFID reader, an RC522, just stops reading cards. I can’t really figure out why. I was hoping to get some help from you guys on determining why that was happening.

#include <SPI.h>
#include <MFRC522.h>
#include <Wire.h> // Comes with Arduino IDE
#include <LiquidCrystal_I2C.h>

#define SS_PIN 10
#define RST_PIN 9
#define otherPin A0
#define otherPin1 A1
#define otherPin2 A2

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
MFRC522 rfid(SS_PIN, RST_PIN); // Instance of the class

MFRC522::MIFARE_Key key;


int ledPins[] = {2, 3, 4, 5, 6, 7, 8, otherPin, otherPin1, otherPin2};
int ledCount = 10;
int BatteryMode;
int BatterySubmode;
String ErrorCode = "0x00243M";
String Check = "";
char PowerDown[] = "1263113435";
char PowerUp[] = "949311935";
char Error[] = "1429311935";
char Tool1[]= "414735822273129";
byte nuidPICC[3];
String lcdMessage;


// the setup function runs once when you press reset or power the board
void setup() {
  // initialize digital pin 13 as an output.
Serial.begin(9600);
lcd.begin(16,2); // initialize the lcd for 16 chars 2 lines and turn on backlight
  lcd.setBacklight(15);

  SPI.begin(); // Init SPI bus
  rfid.PCD_Init(); // Init MFRC522

  for (byte i = 0; i < 6; i++) {
    key.keyByte[i] = 0xFF;
  }
  
  for (int p = 0; p < ledCount; p++)
  {
    pinMode(ledPins[p], OUTPUT);
    
  }
  BatteryMode = 1;
}

// the loop function runs over and over again forever
void loop() {
  

 if (BatteryMode == 1) {
  
    lcd.clear();
    
    
    lcd.print("Power: ");
    lcd.print(ledCount);
    lcd.print("0%");
    
  for (int p = 0; p < ledCount; p++)
  {
    
  
  delay(50);  
  digitalWrite(ledPins[p], HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(50);              // wait for a second
  }
  for (int p = 0; p < ledCount; p++)
  {
    delay(50);
  digitalWrite(ledPins[p], LOW);    // turn the LED off by making the voltage LOW
  delay(50);
  }
for (int p = 0; p < ledCount; p++)
  {    
  digitalWrite(ledPins[p], HIGH);   // turn the LED on (HIGH is the voltage level)                // wait for a second
  }
  delay(2000);
for (int p = 0; p < ledCount; p++)
  {    
  digitalWrite(ledPins[p], LOW);   // turn the LED on (HIGH is the voltage level)                // wait for a second
  }
  
    
 
  }


if (BatteryMode == 2) {
  for (int p = 0; p < ledCount; p++)
  {
    
  digitalWrite(ledPins[p], HIGH);   // turn the LED on (HIGH is the voltage level)
                // wait for a second
  }
  delay(500);
  for (int p = 0; p < ledCount; p++)
  {
    
  digitalWrite(ledPins[p], LOW);   // turn the LED on (HIGH is the voltage level)
                // wait for a second
  }
  delay(500);
     
  }

 
  // Look for new cards
  if ( ! rfid.PICC_IsNewCardPresent())
    return;

  // Verify if the NUID has been readed
  if ( ! rfid.PICC_ReadCardSerial())
    return;
 

if (rfid.uid.uidByte[0] != nuidPICC[0] ||
      rfid.uid.uidByte[1] != nuidPICC[1] ||
      rfid.uid.uidByte[2] != nuidPICC[2] ||
      rfid.uid.uidByte[3] != nuidPICC[3] ) {
    Serial.println(F("A new card has been detected."));

    // Store NUID into nuidPICC array
    for (byte i = 0; i < 4; i++) {
      nuidPICC[i] = rfid.uid.uidByte[i];
    }

    
        CheckID(rfid.uid.uidByte, rfid.uid.size);
      }
else
{
  CheckID(rfid.uid.uidByte, rfid.uid.size);
}


   // Halt PICC
  rfid.PICC_HaltA();

  // Stop encryption on PCD
  rfid.PCD_StopCrypto1();

}

void CheckID(byte *buffer, byte bufferSize) {
  Check = "";
  for (byte i = 0; i < bufferSize; i++) {
    char butt = (buffer[i], DEC);
    Check += String(buffer[i]);
  }
  
  Serial.print(Check);
  
    if (Check == PowerDown)
    {
      ledCount--;
    }
    else if (Check == PowerUp)
    {
      ledCount++;
    }
    else if (Check == Error && BatteryMode == 1)
    {
      BatteryMode = 2;
    }
    else if (Check == Error && BatteryMode == 2)
    {
      BatteryMode = 1;
    }
    else if (Check == Tool1 && BatteryMode == 2)
    {
      lcd.clear();
      lcd.print(ErrorCode);
    }
}

void EatPower(){
  ledCount--;
}

That’s my code. Anyone have any ideas?

Interesting. I assume that everything seems to work OK for a while, and then when a new card is presented, it is ignored and the LEDs keep turning off.

I would add some debug code in the if statements around Look for New Cards. The first one will spam your serial port, so you might add that later. This will narrow down where it is going wrong, assuming this isn't a result of overflow.

 // Look for new cards
 if ( ! rfid.PICC_IsNewCardPresent()) {
   serial.println("No new card present.");
   return;
 }
 // Verify if the NUID has been readed
 if ( ! rfid.PICC_ReadCardSerial()) {
   serial.println("Card present but unable to read serial number.");
   return;
 }

Another suggestion is to use Switch Case instead of if else if. That way, you can add DEFAULT: for unexpected outcomes, and print a message there. For example, if CheckID has an unexpected Check, you might want to know about it. BTW, there appears to be no point in the variable butt in this function.

Hamsterman: Interesting. I assume that everything seems to work OK for a while, and then when a new card is presented, it is ignored and the LEDs keep turning off.

That's actually exactly what's happening. Might I ask how you know that? Is it a common error that's happening?

I would add some debug code in the if statements around Look for New Cards. The first one will spam your serial port, so you might add that later. This will narrow down where it is going wrong, assuming this isn't a result of overflow.

 // Look for new cards
 if ( ! rfid.PICC_IsNewCardPresent()) {
   serial.println("No new card present.");
   return;
 }
 // Verify if the NUID has been readed
 if ( ! rfid.PICC_ReadCardSerial()) {
   serial.println("Card present but unable to read serial number.");
   return;
 }

Another suggestion is to use Switch Case instead of if else if. That way, you can add DEFAULT: for unexpected outcomes, and print a message there. For example, if CheckID has an unexpected Check, you might want to know about it. BTW, there appears to be no point in the variable butt in this function.

You're right about the variable, it's an artifact from when I was having difficulty getting the CheckID function working, that I forgot to remove.

So, interestingly, I removed the LCD screen and the associated code from the device, and now suddenly, everything's working perfectly, long term. I add the LCD screen back in, and then it reads the first few cards fine, and then locks up and can't read cards anymore.

I don't know what the conflict is, or maybe it's a processing power thing, but I'm migrating to beep codes and flashing LEDs for error codes for now.

I don't really know what is happening, to be honest. I tried looking up the LiquidCrystal_I2C library, but the one I found didn't have the same initialization as yours.

I'm not sure how you are powering your project, but you might consider externally powered +5V and +3.3V rather than depending on your Arduino. There could be a dropout, or its regulator could be operating near its limit and as it heats up it finally shuts down. Measure the +5V and +3.3V lines and see if they change when things stop working.

Since the LCD is I2C, and the RFID is SPI (4-wire), you might want to put a logic probe on the 4-wire connections to see if it is hanging up there. I tried searching for conflicts between I2C and SPI and they were all hardware or a different bug.

Good luck!