Using the MFRC522.py library and SimpleMFRC522 extension, I have been able to pass tag ID information as well as the text block; but only for one tag at a time.

Diving deeper into the MFRC522 library and SPI documentation, I see that it is passing the SPI port information in initialization, like so:

def __init__(self, bus=0, device=0, spd=1000000, pin_mode=10, pin_rst=-1, debugLevel='WARNING'):

    self.spi = spidev.SpiDev()
    self.spi.open(bus, device)
    self.spi.max_speed_hz = spd

    self.logger = logging.getLogger('mfrc522Logger')
    level = logging.getLevelName(debugLevel)

    gpioMode = GPIO.getmode()

SPIdev documentation shows the spi.open(x,y) function accesses /dev/spidev-x.y when initializing the port.

Now, when visiting the /dev/ directory, there is only spidev0.0 and spidev0.1 listed. From the documentation, 0.0 represents CS0 and 0.1 represents CS1. Is there a way to create more entries for spidev while pointing them to GPIO pins? Where should I be making this change?

EDIT: After running $ gpio readall, I see that Pins (Physical) 24 and 26 are simply set to OUT mode. Could I declare any other 8 GPIO as OUT? How would I make sure it knows those OUTs are supposed to be CE2-10?


1 Answer 1


/dev/spidev-x.y entries are only created for chip select pins which are hard-wired to the SPI module. There's only two of them and there's no way around that.

What you could do is to connect CS pins to GPIOs which you would toggle from your userspace code:

# Init
spi.open(0, 0)                   # Use SPI device 0
GPIO_CSx = 18                    # Pin you have wired to CS of module X
GPIO_CSy = 23                    # Pin you have wired to CS of module Y
GPIO.setup(GPIO_CSx, GPIO.OUT)   # Chip select X set as output
GPIO.setup(GPIO_CSy, GPIO.OUT)   # Chip select Y set as output
GPIO.output(GPIO_CSx, GPIO.HIGH) # Deselect device X
GPIO.output(GPIO_CSy, GPIO.HIGH) # Deselect device Y

# Communication
GPIO.output(GPIO_CSx, GPIO.LOW)  # Select device X
spi.xfer2(msg)                   # Talk to device X
GPIO.output(GPIO_CSx, GPIO.HIGH) # Deselect device X
GPIO.output(GPIO_CSy, GPIO.LOW)  # Select device Y
spi.xfer2(msg)                   # Talk to device Y
GPIO.output(GPIO_CSy, GPIO.HIGH) # Deselect device Y

In the simplest form, the original CS0 signal remains unused. Some devices will accept this kind of handling, others may timeout if the delay between chip select going low and the first clock pulse is too long. You'll have to try.

In a more sophisticated form, the original CS0 signal is combined with GPIO_CSx/GPIO_CSy using a logical OR (so that the result goes LOW only when e.g. both CS0 and GPIO_CSx are LOW). This requires some soldering / breadboard assembly, but improves the timing.

  • 2
    Dmitry, I posted a followup question to this one after trying to implement your suggestion. Any additional information would be greatly appreciated. Thanks again.
    – tmakes
    Mar 3, 2020 at 21:53
  • 1
    Also, I tried to implement all of this within the MFRC522.py file. While I notice GPIO13 (CS1) is initialized HIGH and as an Output, it is pulled LOW when using the read() function and the program hangs. The interesting part is that the SCLK is still driving the CE0 pin 1/0/1/0/1/0 expecting data from the default /spidev-0.0. I can't seem to make it recognize the "new" CE pin which is actually GPIO13, Any ideas?
    – tmakes
    Mar 4, 2020 at 19:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.