RFID access system
Night watchman Les Pounder shows us how to make our own security system using a Raspberry Pi, a magnetic lock and an RFID reader.
It’s lockdown at LXF Towers as Les Pounder wields a Pi, a magnetic lock and an RFID reader.
For this month’s project we shall build our own door security system, which can be used to log who enters a property using inexpensive RFID (radio frequency identification) cards. These RFID cards are read using an RFID reader – the RFID-RC522 – which gives a unique ID for each card. This is checked against a dictionary of accepted cards, and if found a relay is triggered, disconnecting a 12V circuit used to power the magnetic lock. Watch your fingers, though: the magnet is strong and can supply 280kg of force!
High and low
There are two parts to this project: the low-voltage circuit for the Raspberry Pi, and the higher-voltage 12V circuit for the magnetic door lock. The Pi is connected to the RFID reader using the SPI interface on the GPIO. Our release button for the door is also on this circuit. We connect a relay board to the Pi, providing it with 5V and GND, and then connect GPIO17 of our Pi to IN1 on the relay board. This enables the Pi to trigger the relay and remain isolated from the 12V circuit.
The 12V circuit to the relay is the 12V+ power from a 12V DC supply. This is connected to the COM terminal, the centre terminal. And a connection is made from the NC (normally closed) terminal to the magnetic door lock. The 12V GND connection is made from the DC power supply to the GND of the magnetic lock. So when the relay is triggered, the DC12V+ connection is made to the door lock, causing the magnet to energise and lock the door. See the diagram ( topright).
There are quite a few libraries that require installation for this project. The first is SPI-Py, specifically a fork created by Simon Monk. This library requires manual installation via “git clone” because it’s not in the “pip” repositories, so we also need to install logzero, a simple Python logging tool that can write to external files and provide easily identifiable output in the Python shell. So to make software installation straightforward, we’ve written a small bash script that be downloaded and run in the terminal using the following: $ curl https://raw.githubusercontent.com/lesp/LXF230-RFIDDoor-Lock/master/install.sh | bash
We also need to enable the SPI interface. So on the Raspbian desktop, go to the main menu and navigate to Preferences, then select Raspberry Pi Configuration. In the new menu, look for Interfaces and then enable the SPI interface. Click OK to make the change. Now is a good time to reboot the Pi and return to the desktop.
Writing the code
In Thonny, click File>Save and call the project RFID-security. py and save the file in the LXF230-RFID-Door-Lock directory. Remember to save your code as you go.
Our first few lines of Python are the libraries. First, we import the Button and OutputDevice classes from GPIO Zero. The button class is self-evident, but the OutputDevice is used to connect the Raspberry Pi to the relay. The next two libraries are SimpleMFRC522 and time. Again, time is obvious, but the former is used to connect and read the data from the RFIDRC522 reader. The final two imports relate to logzero. This is the Python library that provides an easy way to create logfiles, and to format the data that’s output to the Python shell: from gpiozero import Button, OutputDevice import SimpleMFRC522 import time import logzero from logzero import logger
Now let’s create three objects that we will be using to connect our relay board to GPIO 17 of the Raspberry Pi, then create a release button on GPIO27, and create a connection to the RFID reader: relay = OutputDevice(17) release = Button(27) reader = SimpleMFRC522.SimpleMFRC522()
The next line of code uses the relay object that we’ve just created. This will turn the GPIO pin on and that will trigger our relay to click into life. On the other side of the relay is our 12V circuit, in this case the 12V + power connection, which is connected to the relay as “Normally Closed”, NC. This means that when the relay is turned on, the circuit is active and power can flow to the magnetic door lock, triggering it to lock. relay.on()
Now, to log all of the events for entering and leaving the building we create a logfile using logzero. This is called
access.log and it has a maximum size of 1e6, 1MB. It also creates up to three backups of the log via a rotating log file: logzero.logfile("access.log”, maxBytes=1e6, backupCount=3)
In order to unlock the magnetic door lock, we need to write a function that will take the user id for the card presented to the reader and write it to the log. Our function “opendoor” takes one argument, the id of the card. This is passed to the logger and written to the log using the format “info” which is colour-coded green in the shell output.
We then write the name of the user to the log, using a dictionary called “cards” and the key, which is the id of the card. More on this later. The next step is to turn the relay off, breaking the 12V circuit and turning off the magnetic lock, and allowing the user to enter. We then print that the door is open to the Python shell. The code then waits for five seconds before turning the 12V circuit back on and locking the door.
def opendoor(id): logger.info(id) logger.info("The user is “+str(cards[id])) relay.off() print("DOOR OPEN") time.sleep(5) relay.on() print("DOOR LOCKED")
We now create another function to handle the situation when the release button is pressed. It will log that the door has been opened, and turn off the relay to release the magnet in the same manner as using the RFID card.
def button_open(): logger.info("Door Release Pressed") relay.off() print("DOOR OPEN") time.sleep(5) relay.on() print("DOOR LOCKED")
In order to have a “list” of authorised users, we’re going to create a dictionary, called “cards”. A dictionary is a data storage type which uses a key, value relationship. So when we see the user id from the RFID card, it’s used as a key to search the dictionary and return the value for that key, in this case the user name. The id numbers in this dictionary are found by scanning the tags across the reader, something you can learn more about in the boxout ( above).
cards = {642581926087: “John Smith”,572050203913: “Sarah Rogers"}
Moving on to the main loop of our project. We use a while True loop to constantly run the code within. The first task is to check if the release button has been pressed and if so, to run the button_open function we created earlier. Notice that the function call has no parentheses because that would call the function every time the loop iterates, and not when the button is pressed:
while True: release.when_pressed = button_open
Next, we introduce a 0.1 second delay to pace the code, then we create two variables: “id” and “text”. The id variable is used to store the id of the RFID card presented to the reader. We then print the id to the shell:
time.sleep(0.1) id, text = reader.read() print(id)
In order to check the id of the presented card against our dictionary, we need to use an “if” conditional test. This will check to see “if the id is in the dictionary called cards” and if that’s correct then the opendoor(id) function we created will be run, opening the door and logging the user details to the access log. But if the user is unknown then the door remains locked and the details are recorded on the log:
if id in cards: opendoor(id) else: print("Unknown Card") logger.error(id)
With the code now completed, save your work and click Run>Run Current Script to start the project. Now present one of the cards to the reader and if it’s in the dictionary, the door will unlock. If it isn’t then you can add it – just follow the boxout ( above) for help. LXF