Monday, February 25, 2013

Parallax RFID Reader/Writer & the Raspberry Pi

The Parallax RFID Reader/Writer is a serial device for reading from and writing to writable 125 kHz RFID tags. Since it's a serial device, it is fairly easy to connect to the Pi. It is a 5 volt device, however, so a logic level converter is required.

Freeing Serial Port ttyAMA0:


The RXD pin on the Pi connects to the Linux serial device ttyAMA0. By default, though, this device is used for console output. Follow the 3 steps on the Adafruit Learning System page, "Freeing UART on the Pi."

Connections:


Parallax  Logic Lvl Conv (HV Side)
VCC       HV
SIN       TX0
SOUT      RX1
GND       GND

RPi       Logic Lvl Conv (LV Side)
3V3       LV
GND       GND
RXD       RX0
TXD       TX1

The Raspberry Pi's 5V0 is also connected to the same breadboard row as the logic level converter's HV.    

The following code reads and prints the card or tag's serial number. If this first phase is successful, it writes the current time in seconds since epoch (midnight, January 1st, 1970) to one of the tag's data areas. It then reads the time data just written to show that it was stored correctly.   

When testing this code, I do find that I need to hold the tag/card just a hair's breadth away from the antenna.


Python Code:


import math
import serial
import struct
import time

CMD_HEADER = "!RW"
READ_CMD = "\x01"
WRITE_CMD = "\x02"
SERIAL_NUM_ADDR = "\x20"
DATA_ADDR = "\x03"
STATUS_OK = "01"

serial = serial.Serial("/dev/ttyAMA0", baudrate=9600)
while True:
    # Time iin seconds since epoch, dropping fraction of second
    t = math.floor(time.time())
    # Send command header & read card number
    serial.write(CMD_HEADER)
    serial.write(READ_CMD) 
    serial.write(SERIAL_NUM_ADDR)
    # If successful, read card number & write time to card
    if serial.inWaiting > 0:
        read_result = serial.read()
        if read_result.encode('hex') == STATUS_OK :
            card = serial.read(size=4)
            print "Card: " + card.encode('hex')
            serial.write(CMD_HEADER)
            serial.write(WRITE_CMD) 
            serial.write(DATA_ADDR)
            data = list(struct.pack("!I", t))
            serial.write(data[0])
            serial.write(data[1])
            serial.write(data[2])
            serial.write(data[3])
            if serial.inWaiting > 0:
                write_result = serial.read()
                print "Write result: " + write_result.encode('hex')
        else:
            serial.flushInput() # ignore errors, no data
    # Send command header & read stored time data from card
    serial.write(CMD_HEADER)
    serial.write(READ_CMD) 
    serial.write(DATA_ADDR)
    if serial.inWaiting > 0:
        read_result = serial.read()
        if read_result.encode('hex') == STATUS_OK :
            # Read all 4 bytes of data
            card_data = serial.read(size=4)
            print "Time: " + str(t)
            # Read data as hexadecimal, convert to decimal, then print
            print "Data: " + str(int(card_data.encode('hex'), 16))
            print 
        else:
            serial.flushInput() # ignore errors, no data
        time.sleep(1) # Pause for 1 second

5 comments:

  1. First of all.. thanks for the tutorial, saved me a lot of trouble trying to figure out how to connect and stuff. I've followed all steps and now the led is burning red and once ever x seconds it blinks green. I can hold my tags in front of it but nothing seems to happen. When I use minicom I don't see any output either.. Do you have any idea what I could be doing wrong?
    Thanks in advance!

    ReplyDelete
    Replies
    1. Hi Danny - I wonder if the serial port is really set up correctly. I vaguely remember having seen something like what you describe, but I don't remember the details. I'll dig out my RFID reader/writer and try this again in the next couple days.

      Delete
    2. I am very curious to what you find out. Please let me know :)

      Delete
    3. I had the same issue and found that needed to disable serial port from kernel, did a sudo raspi-config (advanced options) and disable serial port for OS and code worked fine!

      Thanks Brad!

      Delete
  2. I am trying to read the UID of mi-fare card using the RFID module connected to RPI2 GPIO 14,15. Facing issues in reading the UID when UID consists of any number and character D or A. For example 0D or 4D or 0A. How we should handle it ? Vivek

    ReplyDelete