RFID with Raspberry PI on the cheap

If you look around there is no shortage of RFID-based projects on the internet ranging from music boxes to access control systems.

If you look around most of the guides are either using a USB reader or Arduino devices, so I thought it is high time to share a guide on how to get RFID functionality to any Raspberry PI-based project in python.

If you are looking to use RFID for your project choosing the RDM6300 board with 125 kHz cards can be an inexpensive solution to do so. The board itself sells for around $2 on AliExpress, while you can get 10 RFID cards for a few bucks. The only thing to watch out for is compatibility, the EM 4100 uses a 125 kHz RFID protocol, so please ensure that you are picking up the right card for the job.

The RDM6300 reader and matching cards

There are plenty of guides on how to use the RDM6300 reader (based on the EM4100 chip) with Arduino (which is a 5V board), however, I had seen not many addressing the Raspberry PI ecosystem.

This might be due to the two challenges the RDM6300 poses when interfacing with the Raspberry PI: first of all the Raspberry PI uses 3.3V for signaling. Connecting a 5V to signal to the Pi can fry the GPIO pins.

The second issue is that the RDM6300 reader was designed with 5V input in mind: it might be tempting to just feed 3.3V to the reader, thus limiting the output voltage of the pins to 3.3V, but in reality, it does not work properly as the antenna was designed in a way to assume 5V input power for proper power delivery.

Wiring to the Raspberry PI

To get around this the following wiring can be used:

Connecting the RDM6300 to the Raspberry PI

As it is visible we are using the 5V power pin (pin 2) of the Raspberry PI to feed the RDM6300 with power.

The RDM6300 uses the UART Serial protocol, from the wiring perspective connecting such devices can be done with a pair of wires. One wire can be used by the Raspberry PI to send data to the board, the other will be used to receive data from. Now the PI has one built-in Serial port available via the GPIO headers. GPIO 14/15 can be reconfigured to act as a serial port:

Raspberry PI pinout

Wiring a serial connection is quite easy: the PI’s transfer (UART_TXD0) pin needs to be connected to the RDM’s RX pin and the PI’s receive (UART_RXD0) pin needs to be connected to the TX pin on the RDM. Please notice the crossover: the transfer and receive pins are always marked from the board’s point of view.

Pinout of the RDM6300 board

Also, it is visible on the wiring diagram that only the PI’s receive (UART_RXD0 ) pin is connected to the RDM’s transfer pin. This is due to how the reader works: it does not receive any data, it just sends the ID of the card it detects on the serial line.

Of course, we still need to tackle the problem of the 5V output of RDM versus the hard limit of GPIO pins of 3.3V on the PI side. To come around this limitation we are using a voltage divider: pick any two matching resistors (I had used 2 kOhms) and wire them up the same way as shown in the diagram. What this setup does is halves the output voltage of the transfer pin of RDM, making the high level represented as 2.5V.

3.3V systems behave in a way, that if a signal is between 2.0V and 3.3V then that is considered a logic high signal (think of it as a binary 1). This way, using the divider we land in spec, and also preventing our Raspberry PI from being fried.

Of course, the Raspberry PI by default does not enable the serial port, so let’s check next how we enabled support for it on the SBC.

Enabling serial/UART on the Raspberry PI

To be able to access the serial port you will need to use the sudo raspi-config command. Please set 5 — Interfacing Options >P6 — Serial:

  • Would you like a login shell accessible over serial? No
  • Would you like the serial port hardware to be enabled? Yes
Setting up the serial port on Raspberry PI

Note: you must disable the login shell in this case, otherwise the serial port will try to interpret the incoming card ids as console commands, furthermore the serial port will be locked by the Raspbian.

After rebooting the RPI a file called /dev/ttyS0 should be available, that can be used to interface the RDM6300

Antenna positioning

The linked cards have their RFID tags positioned like this:

Position of the RFID chip in the cards

Given that the coil included with the kit is approximately half of the card please be careful when creating the casing so that the antenna is near the tag itself.

As a rule of thumb please position the coil in a way that it is around the middle of the card when the card is inserted.

If well positioned the RDM6300 should constantly output the card’s ID until is inside its reach. On one hand, this is how the card removal detection logic is implemented inside the library I will introduce in the next section, but also if you are not getting this behavior there’s a huge chance that the card can be inserted into your device without it being detected.

Interfacing in Python

You can use this package I had created for interfacing the board (also available on PyPI too):

This is a Python 3 rewrite of the project https://www.pm-codeworks.de/pyrfid.html with corrections to the checksum verification code. This way you can use your PC to populate any card database you wish, which came quite handy in my case when I had to scan 50 cards for my own build.

The library can operate in two modes. The first one (I call easy or raw mode) is demonstrated by this code piece:

Reading Card IDs

This code will print out the Card ID of any card the reader detects. As mentioned before the reader will continuously emit the card’s ID if it is within its reach. This way you can use this simple program to verify if the coil placement is right for your build, as when the card is “inserted” into your build this should continuously print out the card’s ID.

The package also provides a more pythonic way to interface the reader:

Advanced Mode

In this mode, the package will handle the detection of card presence instead of your code allowing the builder to focus on the core logic they need to implement. The card_inserted/card_removed/invalid_card methods will be called whenever a card gets inserted/moved away from the coil or in case of reading errors respectively.

Conclusion

I hope this guide helps with integrating an RFID reader into your project if needed. I do think that Raspberry PI and DIY should be about being creative, and dealing with such low-level nuances and system programming might not be the thing one considers a creative way of spending time.

If you used these inside your project, please share the experience with me, so that I can improve the library further.

SRE, Developer who loves tinkering with stuff