RC522 stops reading cards [kinda solved, workaround]

Hey, I found a similar topic with no answers though
https://forum.arduino.cc/index.php?topic=407884.0

Maybe you can help me figure this out.
The RC522 works fine for a while, so should be no wiring problems, but after a few minutes it just starts either

  1. sending an identical gliched readout from any RFID card
  2. stops reading or sending RFID data completely

After I close and open the COM port window, it works fine for a few minutes again.

*   RFID-RC522 (SPI connexion)
 *   
 *   CARD RC522      Arduino (UNO)
 *     SDA  -----------  10 (Configurable, see SS_PIN constant)
 *     SCK  -----------  13
 *     MOSI -----------  11
 *     MISO -----------  12
 *     IRQ  ----------- 
 *     GND  -----------  GND
 *     RST  -----------  9 (onfigurable, see RST_PIN constant)
 *     3.3V ----------- 3.3V
 *     
 */

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


  #define SS_PIN          10
  #define RST_PIN         6

  MFRC522 mfrc522(SS_PIN, RST_PIN);  // Create MFRC522 instance
  MFRC522::StatusCode status; //variable to get card status

  byte buffer[18];  //data transfer buffer (16+2 bytes data+CRC)
  byte size = sizeof(buffer);

  uint8_t pageAddr = 0x06;  //In this example we will write/read 16 bytes (page 6,7,8 and 9).
                            //Ultraligth mem = 16 pages. 4 bytes per page. 
                            //Pages 0 to 4 are for special functions.           
long int delta = 0;
void setup() {
  Serial.begin(9600); // Initialize serial communications with the PC
  SPI.begin(); // Init SPI bus
  mfrc522.PCD_Init(); // Init MFRC522 card 
  //Serial.println(F("Sketch has been started!"));
  memcpy(buffer,"xx04",16);
}

void loop() {
    
  // Look for new cards
  if ( ! mfrc522.PICC_IsNewCardPresent())
    return;

  // Select one of the cards
  if ( ! mfrc522.PICC_ReadCardSerial())
    return;

  // Read data ***************************************************
  status = (MFRC522::StatusCode) mfrc522.MIFARE_Read(pageAddr, buffer, &size);
  // here i switched the bytes to only show first 4
  for (byte i = 0; i < 4; i++) {
    Serial.write(buffer[i]);
  }
  
  Serial.println();
  mfrc522.PICC_HaltA();
  //delay(1000);

}

I'll try to get a separate 3.3v power supply later on, maybe it has some weird effects by being powered directly from Arduino, but if you have any other ideas, would be nice to hear them.

I don't expect it's doing any harm, but this is odd:

  memcpy(buffer,"xx04",16);

Copy 16 bytes from a five byte string to buffer. strcpy would be better, but I don't see why you need to do it at all.

 *     RST  -----------  9 (onfigurable, see RST_PIN constant)

but

 #define RST_PIN         6

I see a conflict there.

 memcpy(buffer,"xx04",16);

That probably doesn't do what you expect it to do. Replace the 16 by 5.

 status = (MFRC522::StatusCode) mfrc522.MIFARE_Read(pageAddr, buffer, &size);

You should set the size variable before each call of MIFARE_Read() as the method returns the read bytes in this variable. So if you read less then the expected bytes once you'll never see more in the future.

memcpy was there as a vestigial leftover part from when the code was also writing into the RFID chips, sorry. The RST_PIN was wired correctly, but the comments were from the library example, I apologise.

So I managed to find a workaround, not great but it works somewhat consistently. For anyone reading this, be warned that this is FOR SURE not a good way to fix this, but it kinda gets the job done. What I did is a 10 second timer that resets arduino via soft reset.

  #include <SPI.h>
  #include <MFRC522.h>
  
  #define SS_PIN          10
  #define RST_PIN         9
  
  MFRC522 mfrc522(SS_PIN, RST_PIN);  // Create MFRC522 instance
  MFRC522::StatusCode status; //variable to get card status

  byte buffer[18];  //data transfer buffer (16+2 bytes data+CRC)
  byte size = sizeof(buffer);

  uint8_t pageAddr = 0x06;  //In this example we will write/read 16 bytes (page 6,7,8 and 9).
                            //Ultraligth mem = 16 pages. 4 bytes per page. 
                            //Pages 0 to 4 are for special functions.           
long int delta = 0;
void setup() {
  Serial.begin(9600); // Initialize serial communications with the PC
  SPI.begin(); // Init SPI bus
  mfrc522.PCD_Init(); // Init MFRC522 card 
  //Serial.println(F("Sketch has been started!"));
}

void(* resetFunc) (void) = 0; //declare reset function @ address 0

void loop() {
    
  if (millis() > delta + 10000){
    delta = millis();
    mfrc522.PCD_SoftPowerDown();
    delay(10);
    mfrc522.PCD_SoftPowerUp();
    mfrc522.PCD_Init();
    delay(4);
    resetFunc(); 
  }
  
  // Look for new cards
  if ( ! mfrc522.PICC_IsNewCardPresent())
    return;

  // Select one of the cards
  if ( ! mfrc522.PICC_ReadCardSerial())
    return;

  // Read data ***************************************************
  status = (MFRC522::StatusCode) mfrc522.MIFARE_Read(pageAddr, buffer, &size);
  // here i switched the bytes to only show first 4
  for (byte i = 0; i < 4; i++) {
    Serial.write(buffer[i]);
  }
  
  Serial.println();
  mfrc522.PICC_HaltA();
  delay(1000);

}

As I wrote this I also came to realise that the reset is written very sloppy and there probably is no need to do a delta increment, since everytime it happens, it should reset the millis() to 0 as well. Since this is in no way an elegant solution by design, I'll let the reset timer remain as it is :smiley:

Did you read and understand the last hint I gave you in my answer?