3

I am building a Raspberry Pi B+ powered survey device. It would use NFC scanners for multiple choice questions. It should display a question on LCD screen and the user should have his NFC tag scanned by NFC scanner corresponding to his choice.

I am planning on using SunFounder's NFC scanner for Raspberry Pi, however, if I use separate GPIO pins for separate scanners, I can only read from 3 scanners which is not enough.

According to the user manual, NFC scanner uses 5 GPIO pins + 5V + GND out 26 available like this:

  • one is connected to GPIO 10 (SPIO_MOSI)
  • GPIO 9 (SPIO_MISO)
  • GPIO 8 (SPI_CE0)
  • GPIO 17
  • 5V, GND

I found no comments whatsoever which pin is used for what.

The device needs to identify NFC tag and the answer chosen (ie, scanner which read NFC tag).

Now the questions are can I reuse some (all) of the pins used to transfer NFC tag information and do I need to use some logic, for example, Charlieplexing to identify scanner?

3
  • Can you give a better link to the NFC scanner you plan to use than some PDF document? Ideally give us the details in your answer instead of in an external link, so this question stays readable and relevant even if the link document disappears?
    – Phil B.
    Commented May 21, 2015 at 10:21
  • That PDF is the user manual of the scanner. I guess, I could try extracting the relevant details.
    – julka
    Commented May 21, 2015 at 10:36
  • Why not just buy some USB NFC readers? Commented May 23, 2015 at 22:49

4 Answers 4

2

According to the documentation, the device you link can be used as an SPI device. Unfortunately, with the default pins for SPI, as far as I know, you only get 2 Chip Select pins, so you can drive maximum 2 cards this way when using standard available libraries. If you want to drive all 4, you cannot rely on those libraries and will need to do some bit-banging (unless my quick google search skipped something of course), but it only requires 2 extra GPIO pins (Easily available) or can even be done with the original 2 pins if you use a demultiplexer IC (0,0 = card 1; 0,1 = card 2; 1,0 = card 3 and 1,1 = card 4).

Now for some alternatives:

  1. Have you thought about giving your contestants 4 different tags, one for each answer? That way you can bring your setup down to 1 reader, no reading conflicts, and you replicate just the cheapest component in your setup (the RFID tag)
  2. You might want to look into different RFID readers - This one from Adafruit does UART, SPI and I2C. Since all of those mechanisms are available on the Pi (and it supports 2 devices via SPI) you could put one via UART, one via I2C and 2 via SPI. The card seems to have 2 select pin headers on it as well, I'm not sure if this would allow you to set different I2C addresses, but if it does and depending on how many different addresses it supports, you might be able to plug all of those on the same I2C bus and use them this way.

UPDATE: The two select headers are to select SPI, UART or I2C mode, not to set the I2C address. That address is fixed at 0x48 for all PN532 based cards, so you cannot put two of them on the same I2C bus, not even if you buy them from different board suppliers.

6
  • Can I send data to say UART pin from several cards and use demultiplexing logic (additional GPIO pins) to extend the number of scanners it can support? Assume only one scanner reads a tag at any single time.
    – julka
    Commented May 21, 2015 at 11:07
  • UART is a serial protocol - it is really designed for communication between 2 devices, one on each end, not one-to-many. Even if you managed to multiplex devices, they wouldn't be able to identify themselves as being different, so how would you determine from which NFC reader the response comes?
    – Phil B.
    Commented May 21, 2015 at 13:58
  • I am a total newbie when it comes to hardware. I only needed "use friggin I2C that allows you to speak to multiple slaves as raspberrypi.org/forums/viewtopic.php?f=44&t=20852 suggests".
    – julka
    Commented May 21, 2015 at 17:50
  • I2C indeed allows you to control multiple devices on the same bus, BUT, if those devices are the same make & model, you need to be sure that you can set a separate I2C address for each of them, otherwise they both (or all 4) listen to the same address and you get conflicts, or cannot determine which reader the signal comes from. The NFC card you mention does not have an I2C connection, the one I mentioned from Adafruit does.
    – Phil B.
    Commented May 21, 2015 at 17:58
  • 3
    This post over at the Adafruit forums confirms you cannot change the I2C address on the PN532.
    – Phil B.
    Commented May 21, 2015 at 18:17
1

I know this is an old question and likely resolved but for anyone still finding this, maybe this will help:

I've been working on a Project using multiple NFC Readers (MFRC522). I used pimylifeup's MFRC522-Python Library and wrote my own NFC class based on the SimpleMFRC522 class provided by the Library. It closes the SPI Connection whenever I want to switch to a different reader and reopens it after setting the appropiate reader's RST Pin to high.

The order of events to copy the contents of a chip on Reader1 to a chip on Reader2 would look a little something like this:

  1. Set Reader1's RST Pin HIGH
  2. Set Reader2's RST Pin LOW
  3. Initialize SPI (see line 129-131 in MFRC522.py)
  4. Read Chip
  5. Close SPI (see line 166 in MFRC522.py)
  6. Set Reader1's RST Pin LOW
  7. Set Reader2's RST Pin HIGH
  8. Initialize SPI
  9. Write Chip
  10. Close SPI

The readers are all connected in parallel and only the RST Pins are connected to individual GPIOs. This has worked fine for me using 5 readers and should (theoretically) work with an unlimited amount of readers at the same time. Of course, you can't use them at the exact same time, but swapping through them at high speeds did the trick as well.

TLDR:

Schematic using 2 readers

Schematic using 4 readers

Code example for a class supporting multiple NFC Readers using this method:

import RPi.GPIO as GPIO
from mfrc522 import SimpleMFRC522
import spidev

class NFC():
    def __init__(self, bus=0, device=0, spd=1000000):
        self.reader = SimpleMFRC522()
        self.close()
        self.bus
        self.boards = {}
        
        self.bus = bus
        self.device = device
        self.spd = spd

    def reinit(self):
        self.reader.READER.spi = spidev.SpiDev()
        self.reader.READER.spi.open(self.bus, self.device)
        self.reader.READER.spi.max_speed_hz = self.spd
        self.reader.READER.MFRC522_Init()

    def close(self):
        self.reader.READER.spi.close()

    def addBoard(self, rid, pin):
        self.boards[rid] = pin

    def selectBoard(self, rid):
        if not rid in self.boards:
            print("readerid " + rid + " not found")
            return False

        for loop_id in self.boards:
            GPIO.output(self.boards[loop_id], loop_id == rid)
        return True

    def read(self, rid):
        if not self.selectBoard(rid):
            return None

        self.reinit()
        cid, val = self.reader.read_no_block()
        self.close()

        return val

    def write(self, rid, value):
        if not self.selectBoard(rid):
            return False

        self.reinit()
        self.reader.write_no_block(value)
        self.close()
        return True


if __name__ == "__main__":
    nfc = NFC()
    nfc.addBoard("reader1",5)
    nfc.addBoard("reader2",6)

    data = nfc.read("reader1")
    nfc.write("reader2",data)
0

I am new to Python wiring as per above from the above i understand that you have created a class how do i use this class.. i copied your class and named it as MultiNFC.py

my program to read 2 RFID is

from MultiNFC import NFC nfc = NFC() while True: nfc.addboard("reader1",5) #5 is GPIO 5 at pin number 29 nfc.addboard("reader2",6) #6 is GPIO 6 at pin number 31 data1 =nfc.read("reader1") data2 =nfc.read("reader2") GPIO.cleanup()

is this correct

Regards

Amogh Walvekar

1
  • As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.
    – Community Bot
    Commented Mar 14, 2023 at 17:33
0

I updated Lugico's code with Amogh's advice to work with 2 readers on a Raspberry Pi 3B+.

Make sure you're supplying sufficient power to your pi or it will not be able to power all of your readers. dmesg will report if your pi is not able to supply enough power. Use something like this https://www.sparkfun.com/products/114 at 3.3V on your breadboard instead of using the lines from your Pi if you can't supply enough power natively.

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

class NFC():
    def __init__(self, bus=0, device=0, spd=1000000):
        self.reader = SimpleMFRC522()
        self.close()
        self.boards = {}

        self.bus = bus
        self.device = device
        self.spd = spd

    def reinit(self):
        self.reader.READER.spi = spidev.SpiDev()
        self.reader.READER.spi.open(self.bus, self.device)
        self.reader.READER.spi.max_speed_hz = self.spd
        self.reader.READER.MFRC522_Init()

    def close(self):
        self.reader.READER.spi.close()

    def addBoard(self, rid, pin):
        self.boards[rid] = pin
        GPIO.setup(pin, GPIO.OUT)
        print(pin)

    def selectBoard(self, rid):
        if not rid in self.boards:
            print("readerid " + rid + " not found")
            return False

        for loop_id in self.boards:
            GPIO.output(self.boards[loop_id], loop_id == rid)
        return True

    def read(self, rid):
        if not self.selectBoard(rid):
            return None

        self.reinit()
        cid, val = self.reader.read_no_block()
        self.close()

        return val

    def write(self, rid, value):
        if not self.selectBoard(rid):
            return False

        self.reinit()
        self.reader.write_no_block(value)
        self.close()
        return True

# clean up gpios on ctrl+c
def signal_handler(sig, frame):
    GPIO.cleanup()
    print()
    sys.exit(0)

def main():
    signal.signal(signal.SIGINT, signal_handler)
    GPIO.setmode(GPIO.BCM)

    nfc = NFC()

    readers = [
        # rid, pin
        ("reader1", 5),
        ("reader2", 6),
    ]

    for r in readers:
        nfc.addBoard(r[0], r[1])

    while True:
        for r in readers:
            try:
                r_name = r[0]
                data = nfc.read(r_name)
                if data:
                    print(f"{r_name}: {data}")
            except Exception as e:
                print("e", e)

    GPIO.cleanup()

if __name__ == "__main__":
    main()

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.