I am trying to avoid using the built-in CS/CE 0 and 1 pins that the system defaults to when using SPI communication so that I can expand out to as many as 10 devices in the future. The devices in question are MFRC522 13.56MHz RFID Reader/Writers. Following some guidance from a previous post of mine, I am trying to toggle the virtual CS/CE pins I created in the MFRC522.py class initialization from userspace (Read.py). Currently, the Read.py program will get stuck when calling reader.read() after setting CS1 low.

Could this be a timing issue? What is causing it to hang?

SPI debugging techniques are also welcome.

Snippet from MFRC522.py -- (Main class of library for interfacing with RFID reader)

    def __init__(self, spd=1000000, debugLevel='WARNING'):
        self.spi = spidev.SpiDev()
        self.spi.open(0, 0)
        self.spi.max_speed_hz = spd
        CS1 = 13
        GPIO.setup(CS1, GPIO.OUT)
        GPIO.output(CS1, GPIO.HIGH)
        CS2 = 15
        GPIO.setup(CS2, GPIO.OUT)
        GPIO.output(CS2, GPIO.HIGH)

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

        pin_rst = 22
        GPIO.setup(pin_rst, GPIO.OUT)
        GPIO.output(pin_rst, 1)

MFRC522.py continued -- Only place where spi.xfer2() is used

    def Write_MFRC522(self, addr, val, CS):
        GPIO.output(CS, GPIO.LOW)
        val = self.spi.xfer2([(addr << 1) & 0x7E, val])
        GPIO.output(CS, GPIO.HIGH)

    def Read_MFRC522(self, addr, CS):
        GPIO.output(CS, GPIO.LOW)
        val = self.spi.xfer2([((addr << 1) & 0x7E) | 0x80, 0])
        GPIO.output(CS, GPIO.HIGH)
        return val[1]

Read.py -- (My program for testing read functionality)

import RPi.GPIO as GPIO
import time
import signal
import sys
from mfrc522 import SimpleMFRC522


CS1_Idle = lambda : GPIO.output(13, GPIO.HIGH)
CS2_Idle = lambda : GPIO.output(15, GPIO.HIGH)
CS1_Active = lambda : GPIO.output(13, GPIO.LOW)
CS2_Active = lambda : GPIO.output(15, GPIO.LOW)

tags = []

reader = SimpleMFRC522()

def signal_handler(sig, frame):
    print("\nProgram Successfully Terminated")

signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)

def read_tag(tag_list, CS):
    if CS == 1:
        print("CS1 Pulled Down")
        tid, data = reader.read()
        print("CS1 Back UP")
        read = [tid,data]
        print("CS1 Successful")

    print("Attempting to READ...\n")
    read_tag(tags, 1)
    print('ID       TEXT\n', *tags, sep='\n')
  • 2
    Use the kernel driver. You can easily get as many SPI connections as you need (until you run out of CS pins). Look at /boot/overlays/README from spi1-1cs down.
    – Dougie
    Mar 3, 2020 at 22:44
  • 1
    Ah, let me see. I have been using Arduino/Rpi GPIO pins as extra CS pins since my Rpi1 days and so far so good. My trick is simple: (1) disconnect the Rpi SPI1/2/3/4/5/6 CS1/2/3 pins from the SPI device, (2) To read/write any SPI1 device say, I first activate/set low the GPIO pin faking the CS pin, then read/write SPI as nothing cheating has happened. I guess you are doing something similar. (3) There are some nasty devices which have special timing sequence triggered by the CS low edge, ... Perhaps I can read the RFID chip datasheet and see there is anything weird need to watch out. Cheers.
    – tlfong01
    Mar 4, 2020 at 2:17
  • 1
    Just now I read the datasheet and found the chip select pin (NSS) is nothing special, SPI timing is common. You might like to read the SPI timing diagram in my penzu reading log: penzu.com/p/e7b96deb. I have not read your porgram, because it has the newbie scary thing: "lambda"! :)
    – tlfong01
    Mar 4, 2020 at 3:45
  • 2
    Or consider using Rpi4B's 6 SPI Channels. But I have only tired two buses and three CS signals, SPI0,0, 0,1, 1,0, 1,1, 1,2. You might like to read my penzu testing notes on SPI0, 1nd SPI 1: penzu.com/p/6d5601f6.
    – tlfong01
    Mar 4, 2020 at 5:33
  • @Dougie, when you say "running out of CS pins" are you just talking about the available GPIO pins I'd be spoofing?
    – tmakes
    Mar 4, 2020 at 16:13


Your Answer

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

Browse other questions tagged or ask your own question.