How to work with multiple RFID readers (MFRC522) ?

Hello!

I'm trying to build a prototype with:

  • 3 MFRC522 RFID readers (SPI protocol)
  • ESP32 microcontroller
  • external power supply for the RFID readers only

The result is very inconsistent. Sometimes 1 out of the 3 readers is working, most of the time none of them.
I've tried with 2 readers as well, it works sometimes, but still very inconsistent.

I took inspiration from this project where it seems to work fine with 4 readers.

Would any of you has some clue about why it's not working for me or how I could debug this?
Here are the wiring and code details of my implementation:


The code:

#include <SPI.h>
#include <MFRC522.h>//https://github.com/miguelbalboa/rfid

//Constants
const byte NUMBER_OF_READERS = 3;
const byte CS_PINS[] = {5,16,17};
const byte RESET_PIN = 22;

//Variables
MFRC522 mfrc522[NUMBER_OF_READERS];

void setup() {
  //Init Serial USB
  Serial.begin(115200);
  delay(2000);
  Serial.println(F("Initialize System"));

  SPI.begin();
  for (uint8_t i = 0; i < NUMBER_OF_READERS; i++) {
    mfrc522[i].PCD_Init(CS_PINS[i], RESET_PIN);
    Serial.print(F("Reader :"));
    mfrc522[i].PCD_DumpVersionToSerial();
  }
}

void loop() {
  readRFID();
}

void readRFID(void ) { /* function readRFID */
  ////Read RFID card

  for (uint8_t i = 0; i < NUMBER_OF_READERS; i++) {
    if (!mfrc522[i].PICC_IsNewCardPresent())
      continue;

    if (!mfrc522[i].PICC_ReadCardSerial())
      continue;

    Serial.print(F("[Reader "));
    Serial.print(i);
    Serial.print(F("] "));
    printDec(mfrc522[i].uid.uidByte, mfrc522[i].uid.size);
    Serial.println();

    // Halt PICC
    mfrc522[i].PICC_HaltA();

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

// Helper routine to dump a byte array as dec values to Serial.
void printDec(byte *buffer, byte bufferSize) {
  for (byte i = 0; i < bufferSize; i++) {
    Serial.print(buffer[i] < 0x10 ? " 0" : " ");
    Serial.print(buffer[i], DEC);
  }
}

Thank you! Any help is very much appreciated :folded_hands:

The wiring looks clean but the MFRC522 is very picky with SPI timing and wiring length
If you get inconsistent reads with multiple modules it’s usually one of these:

  1. shared SPI lines too long → signal integrity problems
  2. 3.3V supply not stable enough (these readers draw more than people expect)
  3. no separate pull-ups / noisy MISO line when multiple readers are idle
  4. all readers waking the SPI bus at the same time

If I were debugging this, I’d start simple:
→ test one reader with very short wires
→ then add the second
→ then the third
If it breaks as soon as you add the next one it's almost always a hardware / noise issue, not the code

  const byte RESET_PIN = 22;
  .
  .
  .
  for (uint8_t i = 0; i < NUMBER_OF_READERS; i++) {
    mfrc522[i].PCD_Init(CS_PINS[i], RESET_PIN);

By using the same reset pin for multiple readers, you first reset all readers, initialize the first reader, then reset all readers again, including the first reader, initialize the second reader, and then reset all readers again, including the first and second readers before initializing the last reader.

I would be surprised if that ended up working.

@van_der_decken This makes absolute sense, thank you!
I've tried with a dedicated pin for each reader's RST and it's much better now.

I still have inconsistency with 1 reader though, but after a few tests, I believe the reader is faulty.
I've ordered a replacement unit and I will test again when I receive it, this is promising though. I'll make sure to update the thread when I have news

Most of the internet gets this wrong, but this is the way a MFRC522 should be wired when connecting this 3V3 device to a 5V system.

Also if the readers are too close together they will interfere with each other. This will reduce the range of the readers and sometimes stop them working.

Note when constructing them in a case, never use any metal fastenings. Always use nylon nuts and bolts.

I have made many projects that use three RFID readers in the past that use readers like this to generate the things you get in mixed up books.

What is your final application?

This is one example I made earlier.

Mixed up Robots

esp32 has 2 SPI busses, wont they work together?

also, I would use FreeRTOS for this kind of tasks (where timing is a problem).

pd. I second the suggestion that this breadboard might induce some problems, try to make your circuit tidy before going further.

Good to hear the separate reset lines improved things. That’s usually the first hidden issue with multiple MFRC522s on the same SPI bus. Even with good resets, keep an eye on the SPI lines: the MFRC522 tends to leave MISO floating when idle, so a single bad module can corrupt the whole bus. If the replacement fixes the inconsistency, then it was most likely that one faulty reader pulling MISO low or adding noise

@Grumpy_Mike I'm not sure to understand, my ESP32 is a 3.3V, not a 5V, do I still need these resistors ?

I'm building an educational toy for my kid. The goal would be to place cube letters on a board, these letters get recognized and the toy will read it on a speaker.

@maikarg Probably, but my final application would be on a smaller board with a single bus, so I'd like my prototype to work with a single bus.

No, if the whole system is 3V3 you do not need the resistors.

Thanks, but I am not too sure what you mean by cube letters.

I have found that it is best to scan the readers one at a time while disabling the others. This way there is less interference. If you look at the video I posted you will see it is from a MagPi magazine article I wrote. You can get a free PDF download of the whole magazine and check out what hardware I used.

Sure the software is written in Python, but could equally well be written in C/C++ on an Arduino.

The library comes with an example.
Try that (with separate RST lines as in the example)

rfid/examples/ReadUidMultiReader/ReadUidMultiReader.ino at master · miguelbalboa/rfid · GitHub

@Grumpy_Mike It's cubes with letters on it, each cube will have an RFID tag so it can be read by the RFC522's (here is a similar project for reference)

About your project, I'm wondering what are the pros of using a 74HC4051 multiplexer instead of driving the SDA's with GPIO pins :thinking:

It makes the software much simpler, ensuring that only one reader can be accessed at any one time.

I have similar projects for the Arduino, but those involve readers with a Wiegand output using the pin change interrupt function.

Someone made a Wiegand library using the techniques I used here.

I received the new RFID readers.
I managed to make it work with 3 readers, but then after a few tests, some of the readers have stopped working.

To confirm something is wrong with the reader:

  • I've isolated the reader in my circuit
  • the reader doesn't detect anything anymore
  • mfrc522[i]PCD_DumpVersionToSerial() returns Firmware Version: 0x0 = (unknown)
  • the exact same setup with a healthy reader works fine

I believe I must be doing something wrong that kind of "fried" the readers, but I honestly don't know what it could be.

I've tested the voltage output of the external power supply, it's 3.3V as expected.

Any idea what could be wrong here ?

Hopefully a silly question, but are all the headers are soldered to their respective boards?

Yes, I've soldered the headers for each reader, otherwise I wouldn't even be able to test it, maybe I misunderstand your question :smile:

Here is the headers of one of the non-working reader

No, you understood the question. But you would be amazed/appalled at how many people think they're going to get reliable electrical connections across multiple pins by simply sticking header pins through the holes... so I'm glad it was a silly question!

Can't say as I've ever fried one of those modules. And you're running everything at 3.3V so there's not even any potential 5V issues.

The only thing I've got, and it's a long shot (and something I've never seen with these) is one of the modules not tristating MISO when it's not selected. That could damage one or more modules if a non selected module left MISO as an active high when the selected module was driving the line active low. Like I say, I've never seen it myself so I've got no idea if it's a real potential problem or not, but I have seen it mentioned.

Unless... have you measured the output from your external power supply to see that it really is 3.3V?

Oh, interesting. Then, this whole solution of sharing the MISO between modules and switching the selected module could damage it.
@Grumpy_Mike have you ever experienced that with your "Mixed up robots" project ?

Yes I did measure it, it's exactly 3.3V.

After sleeping on it, even if "MISO not being tristated when the board is not selected" is a real problem with MFRC522 boards, I don't see how it could be what's causing your boards to die after some time. They simply wouldn't work from the start when you had two or more boards connected.

Then I am completely out of ideas, I'm afraid.

No but that is because I used a different circuit, designed specifically for the Raspberry Pi, and was all soldered up, no solder-less bread boards. I have been doing a bit of work with solder less bread boards, with the Pi Hut's Advent calendar, (my son bought it for me) and they are very un-reliable at making contact. My guess is that the intermittent connection they provide could be the cause if you frying something

Anyway I think what we are missing from you is a picture of all your boards when connected together, not just the individual module.

Interesting, what else would you suggest to build prototypes ?

It's super messy, but here it is:


By the way, sometimes I disconnect the power supply before disconnecting the ESP32.
So the modules are powered through the SPI lines for a second before I disconnect the ESP32 (I can see the module's LED flickering).
Is it possible that this could fry the module ?