Help with RFID Sensors

Struggling with these RFID-RC522 sensors for a dozen hours.

First off, I'm having trouble getting these sensors detected at all. But when they do connect, they always detect RFID tags. Until they suddenly stopped.

But in this set up in the photos, I'm able to consistently connect the sensor according to my code. When I succeeded in that before, it would then always be able to detect an RFID tag. Now when it connects it won't read RFID tags. I don't know what changed.

Here are some things I've tried:

  1. Yes, there are a lot of wires in the images, but I'm showing this version because it's the only set up that consistently shows the sensor connecting correctly. But I have tried other ways of connecting the sensors and when it does connect, it won't detect any RFID tags still.
  2. I have tried a dozen different sensors..
  3. I have tried a four Arduino UNOs.
  4. I have checked the resistance with every wire with the multimeter.
  5. I have tried a dozen different rfid tags and cards

Here is the code. Most of it is not relevant. It is set up to connect and detect four sensors. But should work and was working with just one. Once the setup shows its connected, it should detect in the loop(). But now it won't. It was, but now it won't.

/**
* "Object Placement" Puzzle
*
* This puzzle requires the player to place one or more items in the
* correct location, at which point an RFID tag embedded in the object
* is detected by a sensor.
* When all sensors read the tag of the correct object, the puzzle is solved.
*
* Demonstrates:
* - SPI interface shared between several devices
* - RFID library
*/

//Updated on 5/14/24

// DEFINES
// Provides debugging information over serial connection if defined
#define DEBUG

// LIBRARIES
// Standard SPI library comes bundled with the Arduino IDE
#include <SPI.h>
// Download and install from https://github.com/miguelbalboa/rfid
#include <MFRC522.h>
// CONSTANTS
// The number of RFID readers
const byte numReaders = 4;
// Each reader has a unique Slave Select pin
const byte ssPins[] = {2, 3, 4, 5};
// They'll share the same reset pin
const byte resetPin = 8;
// This pin will be driven LOW to release a lock when puzzle is solved
const byte lockPin = A0;
// The sequence of NFC tag IDs required to solve the puzzle
//const String correctIDs[] = {"3acbbd49", "2162261d", "c946c06e", "87e0f0a4"};
const String correctIDs[] = {"e946c06e", "2162261d", "c946c06e", "f9c57059"};
const String subcorrectIDs[] = {"11a6ed1d", "211c411d", "d1b02224", "11aa481d"};
const String tokenBackupIDs[] = {"8370cda0", "13e4d1a6", "337cfbb6", "23f6c0a6"};

const String cardIDs[] = {"40f87d1d", "93116aa9", "a3b8c395", "b35f96aa"};
const String cardBackupIDs[] = {"404c661d", "f191b81c", "43c42632", "f398a9aa"};


const String tokenBackupIDs2[] = {"c33495d", "2323b1d", "63b1a4d", "370a2d"};
const String cardBackupIDs2[] = {"5316b10", "23cf2810", "f31a2e11", "837ef311"};

const String tokenBackupIDs3[] = {"d3aabbd", "c3ed19f8", "f3883a13", "b35719"};
const String cardBackupIDs3[] = {"f3f95510", "23de011", "53fee911", "a36e8511"};

//Specify digital pin on the Arduino that the positive lead of piezo buzzer is attached.
int piezoPin = 10;

// GLOBALS
// Initialise an array of MFRC522 instances representing each reader
MFRC522 mfrc522[numReaders];
// The tag IDs currently detected by each reader
String currentIDs[numReaders];


/**
 * Initialisation
 */

void (* resetFunc) (void) = 0;

void setup() {

  #ifdef DEBUG
  // Initialise serial communications channel with the PC
  Serial.begin(9600);
  Serial.println(F("Serial communication started"));
  #endif
  
  // Set the lock pin as output and secure the lock
  pinMode(lockPin, OUTPUT);
  digitalWrite(lockPin, HIGH);
  
  // We set each reader's select pin as HIGH (i.e. disabled), so 
  // that they don't cause interference on the SPI bus when
  // first initialised
  for (uint8_t i=0; i<numReaders; i++) {
    pinMode(ssPins[i], OUTPUT);
    digitalWrite(ssPins[i], HIGH);
  }
  
  // Initialise the SPI bus
  SPI.begin();

  for (uint8_t i=0; i<numReaders; i++) {
  
    // Initialise the reader
    // Note that SPI pins on the reader must always be connected to certain
    // Arduino pins (on an Uno, MOSI=> pin11, MISO=> pin12, SCK=>pin13)
    // The Slave Select (SS) pin and reset pin can be assigned to any pin
    mfrc522[i].PCD_Init(ssPins[i], resetPin);
    
    // Set the gain to max - not sure this makes any difference...
    // mfrc522[i].PCD_SetAntennaGain(MFRC522::PCD_RxGain::RxGain_max);
    
  #ifdef DEBUG
    // Dump some debug information to the serial monitor
    Serial.print(F("Reader #"));
    Serial.print(i);
    Serial.print(F(" initialised on pin "));
    Serial.print(String(ssPins[i]));
    Serial.print(F(". Antenna strength: "));
    Serial.print(mfrc522[i].PCD_GetAntennaGain());
    Serial.print(F(". Version : "));
    mfrc522[i].PCD_DumpVersionToSerial();
  #endif
    
    // Slight delay before activating next reader
    delay(100);
  }
  
  #ifdef DEBUG
  Serial.println(F("--- END SETUP ---"));
  #endif

  //set up complete sound
    tone(piezoPin, 1000, 500);
}

/**
 * Main loop
 */
void loop() {
   // Serial.println(F("--- Loop  ---"));


  // Assume that the puzzle has been solved
  boolean puzzleSolved = true;

  // Assume that the tags have not changed since last reading
  boolean changedValue = false;

  // Loop through each reader
  for (uint8_t i=0; i<numReaders; i++) {
  //    Serial.println(String(i));

    

    // Initialise the sensor
    mfrc522[i].PCD_Init();
    
    // String to hold the ID detected by each sensor
    String readRFID = "";
    
    // If the sensor detects a tag and is able to read it
    if(mfrc522[i].PICC_IsNewCardPresent() && mfrc522[i].PICC_ReadCardSerial()) {
      // Extract the ID from the tag
      readRFID = dump_byte_array(mfrc522[i].uid.uidByte, mfrc522[i].uid.size);
      
      Serial.println(F("--- DETECTED ---"));
      Serial.print(String(readRFID));
      tone(piezoPin, 1000+ (i * 500), 50);
    }
    if(mfrc522[i].PICC_IsNewCardPresent())
    {
      Serial.println("New card");
    }
    if(mfrc522[i].PICC_ReadCardSerial())
    {
      Serial.println("Read Serial");
    }
    
    // If the current reading is different from the last known reading
    if(readRFID != currentIDs[i]){
      // Set the flag to show that the puzzle state has changed
      changedValue = true;
      // Update the stored value for this sensor
      currentIDs[i] = readRFID;
  //    Serial.println(F("--- CHANGED from last reading---"));
    }
    
    // If the reading fails to match the correct ID for this sensor 
    if(currentIDs[i] != correctIDs[i] && currentIDs[i] != subcorrectIDs[i] 
      && currentIDs[i] != tokenBackupIDs[i]
      && currentIDs[i] != tokenBackupIDs2[i]
      && currentIDs[i] != tokenBackupIDs3[i]
      && currentIDs[i] != cardIDs[i]
      && currentIDs[i] != cardBackupIDs[i]
      && currentIDs[i] != cardBackupIDs2[i]
      && currentIDs[i] != cardBackupIDs3[i]) {
      // The puzzle has not been solved
      puzzleSolved = false;
    }



    // Halt PICC
    mfrc522[i].PICC_HaltA();
    // Stop encryption on PCD
    mfrc522[i].PCD_StopCrypto1(); 
  }

  #ifdef DEBUG
  // If the changedValue flag has been set, at least one sensor has changed
  if(changedValue){
    // Dump to serial the current state of all sensors
    for (uint8_t i=0; i<numReaders; i++) {
  //    Serial.print(F("Reader #"));
  //    Serial.print(String(i));
  //    Serial.print(F(" on Pin #"));
   //   Serial.print(String((ssPins[i])));
  //    Serial.print(F(" detected tag: "));
  //    Serial.println(currentIDs[i]);
    }
  //  Serial.println(F("-- At least one sensor changed --"));
  }
  #endif


  #ifdef DEBUG
    

    if(currentIDs[3] == correctIDs[3] || currentIDs[3] == subcorrectIDs[3]
      || currentIDs[3] == tokenBackupIDs[3]
      || currentIDs[3] == tokenBackupIDs2[3]
      || currentIDs[3] == tokenBackupIDs3[3]
      || currentIDs[3] == cardIDs[3]
      || currentIDs[3] == cardBackupIDs[3]
      || currentIDs[3] == cardBackupIDs2[3]
      || currentIDs[3] == cardBackupIDs3[3]) {
      // The puzzle has been solved
      Serial.println(F("--- 3 correct---"));
    }
    if(currentIDs[2] == correctIDs[2] || currentIDs[2] == subcorrectIDs[2]
      || currentIDs[2] == tokenBackupIDs[2]
      || currentIDs[2] == tokenBackupIDs2[2]
      || currentIDs[2] == tokenBackupIDs3[2]
      || currentIDs[2] == cardIDs[2]
      || currentIDs[2] == cardBackupIDs[2]
      || currentIDs[2] == cardBackupIDs2[2] 
      || currentIDs[2] == cardBackupIDs3[2])  {
      // The puzzle has been solved
      Serial.println(F("--- 2 correct---"));
    }
    if(currentIDs[1] == correctIDs[1] || currentIDs[1] == subcorrectIDs[1]
      || currentIDs[1] == tokenBackupIDs[1]
      || currentIDs[1] == tokenBackupIDs2[1]
      || currentIDs[1] == tokenBackupIDs3[1]
      || currentIDs[1] == cardIDs[1]
      || currentIDs[1] == cardBackupIDs[1]
      || currentIDs[1] == cardBackupIDs2[1]
      || currentIDs[1] == cardBackupIDs3[1])  {
      // The puzzle has been solved
      Serial.println(F("--- 1 correct---"));
    }
    if(currentIDs[0] == correctIDs[0] || currentIDs[0] == subcorrectIDs[0]
      || currentIDs[0] == tokenBackupIDs[0]
      || currentIDs[0] == tokenBackupIDs2[0]
      || currentIDs[0] == tokenBackupIDs3[0]
      || currentIDs[0] == cardIDs[0]
      || currentIDs[0] == cardBackupIDs[0]
      || currentIDs[0] == cardBackupIDs2[0]
      || currentIDs[0] == cardBackupIDs3[0]) {
      // The puzzle has been solved
      Serial.println(F("--- 0 correct---"));
    }
  #endif


   // if(currentIDs[1] == correctIDs[1]) {
    //  puzzleSolved = true;
    //}

  // If the puzzleSolved flag is set, all sensors detected the correct ID
  if(puzzleSolved){
    onSolve();
  }
 
  // Add a short delay before next polling sensors
  delay(100); 
}

/**
 * Called when correct puzzle solution has been entered
 */
void onSolve(){

  #ifdef DEBUG
  // Print debugging message
  Serial.println(F("Puzzle Solved!"));
  #endif
  
  // Release the lock
  digitalWrite(lockPin, LOW);

    tone(piezoPin, 440);
  delay(700);
  tone(piezoPin, 550);
  delay(700);
  tone(piezoPin, 660);
  delay(700);
  tone(piezoPin, 440);
  delay(700);
  noTone(piezoPin);
  digitalWrite(lockPin, LOW);

  delay(10000);
  resetFunc();

  //while(true) {
  //  delay(1000);
  //}
  
}

/**
 * Helper function to return a string ID from byte array
 */
String dump_byte_array(byte *buffer, byte bufferSize) {
  String read_rfid = "";
  for (byte i=0; i<bufferSize; i++) {
    read_rfid = read_rfid + String(buffer[i], HEX);
  }
  return read_rfid;
}



Also, I have made this exact project with the same exact same parts and code before and it worked. Here is a picture of that with all four sensors, the pezo buzzer and solenoid lock included:

Given that, what do you think the error could be?

If I had any idea, I wouldn't post here as a last resort.

Well, you have two identical setups, one works, one doesn;t. Same software I assume. Using breadboards that are notorious for poor connectors especially in the cheaper units. I got a handful of those things a month ago and cobbled together a working example in a few minutes. Simplify the setup until you find the weak spot. (I am betting a wiring error OR bad breadboard connections)

As in my original post, I've already tried all of that.

That's unfortunate that you can't find it.

I briefly got a detection again on sensor (numbered #3). Then I disconnected it and got detention on sensor #2. Then I tried 3 again and it still worked. Then I connected 2 through my plastic wire dviders and it stopped working. Then I replaced each connection that was going through the plastic wire dividers one by one and it still didn't work. Then I reconnected my sensor #3 and it stopped detecting. Then I tried #2 again and it not only stopped detecting, it stopped connecting. Then I tried #3 again and it won't connect, detect and the sensor light won't even come on. Then I tried it all again and same result. (Multiply these attempts by a dozen hours and that's what this project has been like for me)

The bottom line is that my results constantly shift and change and I have no idea why. Sometimes I do nothing but reload the project from my PC and it will have different results. Just when one thing starts to work consistently, it suddenly stops for no reason. Or when something doesn't work, it might work again. I spent 5 hours with absolutely no detections whatsoever and suddenly one started working again, briefly. I don't understand why nothing is ever consistent. It's like time itself changes the result. The time between attempts is sometimes the only variable.

What about electromagnetic interference?

It sounds like you have some bad wire connections, likely on the breadboard as @sonofcy mentioned. It is also possible that you are getting some EMI from the rats nest of wires that you have. It is also possible that you are loading all of the sensors with capacitance due, again, to all of the wires and the breadboard.

I would recommend cleaning everything up, shortening every wire to the absolute minimum distance, and using a PCB that is designed like a breadboard. Shortening the wires will reduce capacitance and EMI, and will likely reveal where your bad connections are, and replacing the the solderless breadboard with a solderable breadboard will greatly reduce the capacitance,

In your picture I see atleast one wire that isn't clamped in to the connector properly, and I also wonder why that connector (and others like it) even exist. You are adding capacitance and noise with each clamp in each of those connectors.

Hope this helps!

1 Like

Unfortunately, you're telling me what I've been told a thousand times and I'll give the response I've given a thousand times: I've tried all of that.

I'm not using the breadboard (that was in an older project). I sometimes use these plastic wire dividers, but have tried it many times without them.

I've also tried:

  1. Different wires
  2. Different sensors
  3. Different Arduinos
  4. Different usb cables
  5. Different ways of connecting the sensors

Here's another picture of what doesn't work 90% of the time until it does for no discernable reason.

Have you tried it with level shifters to account for the fact that the RC522 is a 3.3V device and isn't 5V tolerant?

1 Like

I have not. Can you elaborate or point to more information?

This perhaps?

Link to the MFRC522 datasheet.

Relevant excerpt:

Someone will no doubt be along anytime now to dismiss this out of hand, because "everyone knows the MFRC522 is 5V tolerant". Everyone, it seems, except the manufacturer.

When I use them, I use them with 3.3V volt signals, as required by the datasheet. And you know what? They work for me. Over, and over, and over again.

A typical circuit is shown below:

I've been using the 3.3V Pin on the Arduino. (EDIT) Or... is that not correct because we're not talking about the power source but the input power...?

3.3V power, but 5V signals?

So I'll need the 8 channel level shifter and not the 4 channel. This one? Amazon.com: EPLZON TXS0108E High Speed Full Duplex Logic Level Converter 8 Channel SPI 8 Way 3.3V 5V IIC 8-Bit Bi-Directional Converter Module Apply to Raspberry Pi and Arduino (Pack of 5 Set) : Electronics

I have to ask. If this is needed, why did my earlier project work without level shifters?

Because operating outside of the limits doesn't mean that something will fail immediately. It might work once, twice, a dozen, or hundreds of times with no complaints. It might work, but oddly. It might only work in a certain temperature range. A new part might work differently than an old one.

When a manufacturer says "these are the limits under which we guarantee our product will work", it doesn't mean that going outside them means instant failure. It just means that if it fails you have no recourse.

Colouring inside the lines is conservative engineering, and in the long run, it usually makes your life simpler.

1 Like

Maybe the Arduino made a difference. I'm currently using Arduino UNO Rev 3 Elegoo, which may be different than the one in the previous project.

I will try using the level shifters as described in the video.

I have 4 channel level shifters but will have to wait until I receive 8 channel level shifters.

Do all inputs I use require the converted voltage or could I use the 4 channel level shifter?

Only the outputs to the sensor boards require level shifting. The signal that the arduino sends out to the sensors must be converted to 3.3V, but the response that the boards send to the Arduino do not need to be shifted. So, theoretically, a 4-channel shifter should be enough.

Hope this helps.