Setting two devices on SPI interface

Hi,

In recent weeks I try to run two RFID RC522 on the same arduino using the SPI interface. I checked that each of my connections worked separately. Then I plugged in both at the same time and neither of them work. I checked that each PIN was plugged in correctly and checked that SS and RESET were different for each RC522.

I use an arduino of this type: ATmega328P CH340G 5 V Micro

I did some actions:

  • Check that my library for the RFID reader used an SPI library with transactions.
  • Test a basic implementation without a standard library

None of these tests was conclusive, I went through many documentations and thread of discussions without overcoming my worries.

You need to post your program and tell us exactly what it does and what you want it to do that is different.

I wonder if your code needs to set the SS pin "off" for one device before trying to talk to the other device? The library will not know that there are two devices.

...R

Together with complete code post a wiring diagram of your setup (may be hand drawn)! Provide a link to the library you're using.

I use the sources of a github project : GitHub - miguelbalboa/rfid: Arduino RFID Library for MFRC522
Especially the file ReadUidMultiReader.ino in the example folder.

VARIABLES :

constexpr uint8_t RST_PIN = 9; // Configurable, see typical pin layout above
constexpr uint8_t SS_1_PIN = 10; // Configurable, take a unused pin, only HIGH/LOW required, must be diffrent to SS 2
constexpr uint8_t SS_2_PIN = 8; // Configurable, take a unused pin, only HIGH/LOW required, must be diffrent to SS 1

constexpr uint8_t NR_OF_READERS = 2;

byte ssPins[] = {SS_1_PIN, SS_2_PIN};

SETUP :

void setup() {

Serial.begin(9600); // Initialize serial communications with the PC
while (!Serial); // Do nothing if no serial port is opened (added for Arduinos based on ATMEGA32U4)

SPI.begin(); // Init SPI bus

for (uint8_t reader = 0; reader < NR_OF_READERS; reader++) {
mfrc522[reader].PCD_Init(ssPins[reader], RST_PIN); // Init each MFRC522 card
Serial.print(F("Reader "));
Serial.print(reader);
Serial.print(F(": "));
mfrc522[reader].PCD_DumpVersionToSerial();
}
}

MAIN LOOP :

void loop() {

for (uint8_t reader = 0; reader < NR_OF_READERS; reader++) {
// Look for new cards

if (mfrc522[reader].PICC_IsNewCardPresent() && mfrc522[reader].PICC_ReadCardSerial()) {
Serial.print(F("Reader "));
Serial.print(reader);
// Show some details of the PICC (that is: the tag/card)
Serial.print(F(": Card UID:"));
dump_byte_array(mfrc522[reader].uid.uidByte, mfrc522[reader].uid.size);
Serial.println();
Serial.print(F("PICC type: "));
MFRC522::PICC_Type piccType = mfrc522[reader].PICC_GetType(mfrc522[reader].uid.sak);
Serial.println(mfrc522[reader].PICC_GetTypeName(piccType));

// Halt PICC
mfrc522[reader].PICC_HaltA();
// Stop encryption on PCD
mfrc522[reader].PCD_StopCrypto1();
} //if (mfrc522[reader].PICC_IsNewC
} //for(uint8_t reader
}

// RFID lib change SS PIN to LOW or HIGH
/**

  • Writes a byte to the specified register in the MFRC522 chip.
  • The interface is described in the datasheet section 8.1.2.
    */
    void MFRC522::PCD_WriteRegister( PCD_Register reg, ///< The register to write to. One of the PCD_Register enums.
    byte value ///< The value to write.
    ) {
    SPI.beginTransaction(SPISettings(MFRC522_SPICLOCK, MSBFIRST, SPI_MODE0)); // Set the settings to work with SPI bus
    digitalWrite(_chipSelectPin, LOW); // Select slave
    SPI.transfer(reg); // MSB == 0 is for writing. LSB is not used in address. Datasheet section 8.1.2.3.
    SPI.transfer(value);
    digitalWrite(_chipSelectPin, HIGH); // Release slave again
    SPI.endTransaction(); // Stop using the SPI bus
    } // End PCD_WriteRegister()

Thanks,
Antoine

Post complete code and use code tags! This code does not compile (no includes, mfrc522 array is not declared)!

I checked that each PIN was plugged in correctly and checked that SS and RESET were different for each RC522.

This is not true for the posted code and for the posted wiring diagram.

Okay, my apologies for this post a bit messy. I will try to do things properly in this answer.

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

constexpr uint8_t RST_1_PIN = 9;     // Configurable, see typical pin layout above
constexpr uint8_t RST_2_PIN = 7;     // Configurable, see typical pin layout above
constexpr uint8_t SS_1_PIN = 10;   // Configurable, take a unused pin, only HIGH/LOW required, must be diffrent to SS 2
constexpr uint8_t SS_2_PIN = 8;    // Configurable, take a unused pin, only HIGH/LOW required, must be diffrent to SS 1

constexpr uint8_t NR_OF_READERS = 2;

byte ssPins[] = {SS_1_PIN, SS_2_PIN};
byte rstPins[] = {RST_1_PIN, RST_2_PIN};

MFRC522 mfrc522[NR_OF_READERS];   // Create MFRC522 instance.

/**
 * Initialize.
 */
void setup() {

  Serial.begin(9600); // Initialize serial communications with the PC
  while (!Serial);    // Do nothing if no serial port is opened (added for Arduinos based on ATMEGA32U4)

  SPI.begin();        // Init SPI bus

  for (uint8_t reader = 0; reader < NR_OF_READERS; reader++) {
    mfrc522[reader].PCD_Init(ssPins[reader], rstPins[reader]); // Init each MFRC522 card
    Serial.print(F("Reader "));
    Serial.print(reader);
    Serial.print(F(": "));
    mfrc522[reader].PCD_DumpVersionToSerial();
  }
}

/**
 * Main loop.
 */
void loop() {

  for (uint8_t reader = 0; reader < NR_OF_READERS; reader++) {
    // Look for new cards

    if (mfrc522[reader].PICC_IsNewCardPresent() && mfrc522[reader].PICC_ReadCardSerial()) {
      Serial.print(F("Reader "));
      Serial.print(reader);
      // Show some details of the PICC (that is: the tag/card)
      Serial.print(F(": Card UID:"));
      dump_byte_array(mfrc522[reader].uid.uidByte, mfrc522[reader].uid.size);
      Serial.println();
      Serial.print(F("PICC type: "));
      MFRC522::PICC_Type piccType = mfrc522[reader].PICC_GetType(mfrc522[reader].uid.sak);
      Serial.println(mfrc522[reader].PICC_GetTypeName(piccType));

      // Halt PICC
      mfrc522[reader].PICC_HaltA();
      // Stop encryption on PCD
      mfrc522[reader].PCD_StopCrypto1();
    } //if (mfrc522[reader].PICC_IsNewC
  } //for(uint8_t reader
}

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

Here is the message displayed by the console after downloading on the arduino :

Reader 0: Firmware Version: 0x0 = (unknown)
WARNING: Communication failure, is the MFRC522 properly connected?
Reader 1: Firmware Version: 0x0 = (unknown)
WARNING: Communication failure, is the MFRC522 properly connected?

No reaction for each reader if I use an RFID token.

If I remove one of the MISO (lecteur 1 or 2), it works.

Thanks,
Antoine

Images from Reply #5 so we don't have to download them. See this Simple Image Guide

...R

Oh thanks!

The MFRC522 is a 3.3V chip. As you say that your setup runs with only one reader the breakout board must contain some level converter. It seems that your board vendor doesn't use an SPI compatbile level converter (CS HIGH => MISO tri-state). Ask your vendor for schematics for your board. You might have to change the level converter to one that isolates MISO from the bus if CS isn't pulled down.

Can i use a 74HC595 to solve the problem ?

qowii:
Can i use a 74HC595 to solve the problem ?

No, that's a serial shift register. But this device is an example.

pylon:
No, that's a serial shift register. But this device is an example.

If you want to have it less fancy but a lot cheaper 3.3V 5V TXS0108E 8 Channel Logic Level Converter