Attendance Tracking with RFID Module

I am a volunteer fire fighter, and I am looking at using an RFID reader to track attendance rather than the old paper version.

I have a PI 5 and a PiicoDev RFID Module already.

I am after a simple time and date stamp, with the RFID number (Will be programed with ID #) that can automatic update an excel sheet with real life information (Wireless).

I have no programing experience so needing some help

Thanks in advanced

1 Like

There will be many ways you could do this project.

Since this is just attendance tracking and not secure access I think it can be a basic system.

For this I would stick to something like EM4100 IDs/Tags.
You can buy real ones that are “hardwired” with IDs (EM4100 is an LF 125Khz read only tag). then you can pair that with a user.
If you want more control over the ID Values you can buy a cheap proxmark3 easy (512K version) and use T5577 tags and program them as EM4100 ids and use your own number system.

Once you know your ID type you now just need to find the reader that can read that format and send the data to you device for logging (If you use T5577 tags and get a proxmark3, you can program a lot of different formats, so a very good chance of finding a match to the readers.

EM4100 IDs are 5 Bytes, normally just read in hex
e.g. AABBCCDDEE, if you program your own you can then, for example use 2 Bytes as a year of issue reference and then 3 bytes for user IDs
e.g
2025000000 - 2025FFFFFF gives 16 Mil card issues per year. so more then enough. Then you have a ready made system that should never repeat as people come and go and cards get lost/replaced.

When you issue a card, simply record the Username etc with the EM4100 Card ID you gave them. Now when the swipe the card your device will have the ID which you can pair back with the user.

The next step up from here would be to move into HF (13.56Mhz) e.g. Mifare Classic is a well know tag, but the UID of the tag is hard coded (unless you use some form of magic card). So if you want unique tags, you would then have the option of programming them with, say an actual name. e.g. Mifare Clasics has data blocks of 16 bytes grouped in to sectors (mostly 3 Data Blocks per sector)

Depending on how you really want it to work and budget the use of HID Omikey readers can be programed to read both Common LF and HF tags and spit out the ID as a usb keyboard. e.g. if you have that on a PC with the spread sheet open/notepad etc each tap can just send the ID that append the as needed to auto move to the next line.

The next step up and more secure would be the use of something like Desfire HF cards. This, if setup correctly are very hard to clone (as long as you use the secure storage)

So long post, but like I said, there are many ways depending on what is really important to you and the project.

1 Like

You will need a Raspberry Pi 5, PiicoDev RFID Module and RFID tags programmed with ID numbers.

1 Like

Hi @Mitchyr67

Welcome to the forum!

I’ve put together some code to get you started, you will need to make sure you have the Piicodev Unified package installed on your Pi.

from PiicoDev_RFID import PiicoDev_RFID
from PiicoDev_Unified import sleep_ms
import time
import math
import machine

#Intitalise the readers
reader = PiicoDev_RFID    # Initialise the RFID module with both address switches OFF

#intialising the basic RFID module function for read
rfid = PiicoDev_RFID()
file_name = "attendance.csv"

with open(file_name, 'w') as file:
    file.write("Name, ID, Date,Time\n")

def printTagDetails(name, ID):
    print(0*" " + 'Name: ' + name)	# print the persons name
    print(0*" " + 'ID: ' + ID)	# print the persons ID number
    
def log_tag(time):
    # Get current local time
    current_time = time.localtime()
    formatted_date = "{:02}/{:02}/{:04}".format(current_time[2], current_time[1], current_time[0])
    formatted_time = "{:02}:{:02}:{:02}".format(current_time[3], current_time[4], current_time[5])
    
    # Combine name, ID, date and time into a single CSV line
    csv_line = "{},{},{},{}\n".format(name, ID, formatted_date, formatted_time)
    
    # Append the CSV line to the file
    with open(file_name, 'a') as file:
        file.write(csv_line)

#Start of code
print('Checking Slots\n')


while True:
    if reader.tagPresent():              # if an RFID tag is present on reader
        rawData = reader.readText().split()             # get the info from the tag
        name, ID = rawData[:2]     # assign the elements in rawData into individual variables
        printTagDetails(name, ID)   # Call function to output tag details
        log_tag(time)
    sleep_ms(500)

2 Likes

I just need a very basic thing - RFID Chip Number with time and date stamp - Not anything official it’s just to monitor who is present in the shed at what time - Nothing to do with secure access

Thanks so much - Its it much harder than I thought lol
Can it export the file with the details automatically to external USB

1 Like

Hi @Mitchyr67,

This shouldn’t be to hard of a modification to the code Dan provided.

The line file_name = "attendance.csv" is telling the code where to save the data.

If you change “attendance.csv” to the location of your USB drive the data will be saved in that location.

For a standard Pi 5 setup and assuming this is the only USB device you have connected, the location should be “/media/pi/USB/attendance.csv”.

“pi” will be the name of the user currently logged into the Pi
“USB” will be the name of the USB device.

If you are unsure you can always open the USB drive from the file manager and copy/paste its location into the code.

Hope this helps! :slight_smile:

1 Like

I think it just seems harder then it is as its new to you.

Most of these things can can build bit by bit and test each bit to ensure you get it right, then move on.

While there are other solutions then the module and pi you have some are way more complex and others are just more expensive.

e.g. At work we use onmikey readers on our printer/copiers. When someone taps to print the reader is setup to read the needed information from the card and send to the firmware via a usb keyboard. As such the “tracking” seems just needs a usb keyboard interface. BUT its now a $400+ project and you still need to ensure the collection is stable and feeding what you want.

With my RFID background I would use a $45 reader into a PC and write the software to get what I want from the RFID Tag… BUT you now need to know the APDUs (rfid command responses for the card you are talking to) so way more complex, but very robust.

I think the reader and pi option as outlined should be ok for your project… My only real comment, just for completeness so MOST rfid tags (NTAG, Mifare Classic, LF tags etc can be cloned). If just using the default UID/ID of the 13.56 Mhz Tag that can be cloned. If people making copies is not likely to happen and does not really matter if it does, then that keeps it simple. If you want/need it to be more secure, then it does get more complex as every card type has its own way to secure and store data.

2 Likes

Hey @Mitchyr67

Another thing I should mention is the Piicodev RFID reader is also capable of writing to the cards/fobs, I’ve modified one of the example scripts so that it will write a number to the tag, and then won’t try to write again until the tag has been removed and 5 seconds has passed.

from PiicoDev_RFID import PiicoDev_RFID
from PiicoDev_Unified import sleep_ms, ticks_ms

rfid = PiicoDev_RFID()

current_number = 0
previously_detected = False
last_time_seen = ticks_ms()

print('Hold the tag near the PiicoDev RFID Module to write and increment a number on it.')

while True:
    # Try to write the current number to the tag, converted to a string
    myString = str(current_number)
    success = rfid.writeText(myString)

    if success:
        data = rfid.readText()
        print('Number stored in tag:')
        print(data)
        
        previously_detected = True
        last_time_seen = ticks_ms()  # Update the last time the tag was seen
    else:
        # Check if the tag was previously detected and now absent for 5 seconds
        if previously_detected and (ticks_ms() - last_time_seen > 5000):
            current_number += 1  # Increment the number
            previously_detected = False  # Reset detection status

    sleep_ms(10)  # Brief pause to prevent excessive polling
2 Likes