Category Archives: linux

quick and cheap RFID with RPi and rc522

To my great surprise it turns out you can nowadays get an RFID reader with 2 tags for somewhere between 7$ and 10$. Better yet, interfacing these to Arduino is well documented and several libraries are available for that purpose.

My friend who bought a couple of these asked me to see if I can read the tags directly from a Linux based ARM board (for example Raspberry Pi). It turned out to be rather easy as long as you aren’t interested in anything but the ID of the card. This can be done using rpi-rc522 library (NOT written by me). It sadly currently lacks any documentation or a Makefile so here are my notes on how to get it running.

First you have to connect the rc522 and RPi over the SPI interface. It will look something like this:

Raspberry pi and rc522 RFID reader

Raspberry Pi and rc522 RFID reader

Then you have to install the bcm2835 library. Assuming that you have gcc and other essential development stuff already installed you can achieve it this way:

wget http://www.airspayce.com/mikem/bcm2835/bcm2835-1.35.tar.gz
tar -zxf bcm2835-1.35.tar.gz
cd bcm2835-1.35
./configure
sudo make install

After that you can compile and run the rpi-rc522 with the following commands:

sudo apt-get install subversion
svn checkout http://rpi-rc522.googlecode.com/svn/trunk/ rpi-rc522-read-only
cd rpi-rc522-read-only/rc522
gcc config.c rfid.c rc522.c main.c -o rc522_reader -lbcm2835
sudo cp RC522.conf /etc/
./rc522_reader -d

You should see tag IDs in the output of the program as they are read. You can put these into the /etc/RC522.conf file and map each ID to a specific command to run there.

udev rule

One thing that has bothered me for quite some time about my beagleboard home automation “server” is that the various USB dongles that use the USB to serial interface show up under random ttyUSBX device names on each reboot.

So I finally got around to writing couple of udev rules that would create necessary symlinks that will always point to the correct device.

First let’s see what devices are attached to the USB bus:

root@beaglemonitor:# lsusb
Bus 002 Device 026: ID 04fa:2490 Dallas Semiconductor DS1490F 2-in-1 Fob, 1-Wire adapter
Bus 002 Device 025: ID 13b1:0018 Linksys USB200M 10/100 Ethernet Adapter
Bus 002 Device 003: ID 0403:6001 Future Technology Devices International, Ltd FT232 USB-Serial (UART) IC
Bus 002 Device 004: ID 0403:6001 Future Technology Devices International, Ltd FT232 USB-Serial (UART) IC
Bus 002 Device 002: ID 0424:2507 Standard Microsystems Corp.
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

Currently this system only has two usb-serial converters attached, but both have the same ID so we have to use something more specific in order to distinquish between the two.
One way to get see what parameters are available is with lsusb -v but we will go with udevadm which gives output in a format that can be directly copy-pasted to the rule file.

root@beaglemonitor# udevadm info -a -p `udevadm info -q path -n /dev/ttyUSB1`
custom logging function 0x2a026008 registered
selinux=0
calling: info
device 0x2a0260e8 has devpath '/devices/platform/musb_hdrc/usb2/2-1/2-1.4/2-1.4:1.0/ttyUSB1/tty/ttyUSB1'
custom logging function 0x2a026008 registered
selinux=0
calling: info
device 0x2a0260e8 has devpath '/devices/platform/musb_hdrc/usb2/2-1/2-1.4/2-1.4:1.0/ttyUSB1/tty/ttyUSB1'
 
Udevadm info starts with the device specified by the devpath and then
walks up the chain of parent devices. It prints for every device
found, all possible attributes in the udev rules key format.
A rule to match, can be composed by the attributes of the device
and the attributes from one single parent device.
  looking at device '/devices/platform/musb_hdrc/usb2/2-1/2-1.4/2-1.4:1.0/ttyUSB1/tty/ttyUSB1':
    KERNEL=="ttyUSB1"
    SUBSYSTEM=="tty"
    DRIVER==""
 
device 0x2a026350 has devpath '/devices/platform/musb_hdrc/usb2/2-1/2-1.4/2-1.4:1.0/ttyUSB1'
  looking at parent device '/devices/platform/musb_hdrc/usb2/2-1/2-1.4/2-1.4:1.0/ttyUSB1':
    KERNELS=="ttyUSB1"
    SUBSYSTEMS=="usb-serial"
    DRIVERS=="ftdi_sio"
    ATTRS{latency_timer}=="1"
    ATTRS{port_number}=="0"
 
device 0x2a0265f8 has devpath '/devices/platform/musb_hdrc/usb2/2-1/2-1.4/2-1.4:1.0'
  looking at parent device '/devices/platform/musb_hdrc/usb2/2-1/2-1.4/2-1.4:1.0':
    KERNELS=="2-1.4:1.0"
    SUBSYSTEMS=="usb"
    DRIVERS=="ftdi_sio"
    ATTRS{bInterfaceNumber}=="00"
    ATTRS{bAlternateSetting}==" 0"
    ATTRS{bNumEndpoints}=="02"
    ATTRS{bInterfaceClass}=="ff"
    ATTRS{bInterfaceSubClass}=="ff"
    ATTRS{bInterfaceProtocol}=="ff"
    ATTRS{modalias}=="usb:v0403p6001d0600dc00dsc00dp00icFFiscFFipFF"
    ATTRS{supports_autosuspend}=="0"
    ATTRS{interface}=="FT232R USB UART"
 
device 0x2a026ab8 has devpath '/devices/platform/musb_hdrc/usb2/2-1/2-1.4'
  looking at parent device '/devices/platform/musb_hdrc/usb2/2-1/2-1.4':
    KERNELS=="2-1.4"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{configuration}==""
    ATTRS{bNumInterfaces}==" 1"
    ATTRS{bConfigurationValue}=="1"
    ATTRS{bmAttributes}=="a0"
    ATTRS{bMaxPower}==" 90mA"
    ATTRS{urbnum}=="488"
    ATTRS{idVendor}=="0403"
    ATTRS{idProduct}=="6001"
    ATTRS{bcdDevice}=="0600"
    ATTRS{bDeviceClass}=="00"
    ATTRS{bDeviceSubClass}=="00"
    ATTRS{bDeviceProtocol}=="00"
    ATTRS{bNumConfigurations}=="1"
    ATTRS{bMaxPacketSize0}=="8"
    ATTRS{speed}=="12"
    ATTRS{busnum}=="2"
    ATTRS{devnum}=="4"
    ATTRS{devpath}=="1.4"
    ATTRS{version}==" 2.00"
    ATTRS{maxchild}=="0"
    ATTRS{quirks}=="0x0"
    ATTRS{avoid_reset_quirk}=="0"
    ATTRS{authorized}=="1"
    ATTRS{manufacturer}=="FTDI"
    ATTRS{product}=="FT232R USB UART"
    ATTRS{serial}=="A100dj0d"
 
device 0x2a0273d0 has devpath '/devices/platform/musb_hdrc/usb2/2-1'
  looking at parent device '/devices/platform/musb_hdrc/usb2/2-1':
    KERNELS=="2-1"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{configuration}==""
    ATTRS{bNumInterfaces}==" 1"
    ATTRS{bConfigurationValue}=="1"
    ATTRS{bmAttributes}=="e0"
    ATTRS{bMaxPower}=="  2mA"
    ATTRS{urbnum}=="430"
    ATTRS{idVendor}=="0424"
    ATTRS{idProduct}=="2507"
    ATTRS{bcdDevice}=="0000"
    ATTRS{bDeviceClass}=="09"
    ATTRS{bDeviceSubClass}=="00"
    ATTRS{bDeviceProtocol}=="01"
    ATTRS{bNumConfigurations}=="1"
    ATTRS{bMaxPacketSize0}=="64"
    ATTRS{speed}=="480"
    ATTRS{busnum}=="2"
    ATTRS{devnum}=="2"
    ATTRS{devpath}=="1"
    ATTRS{version}==" 2.00"
    ATTRS{maxchild}=="7"
    ATTRS{quirks}=="0x0"
    ATTRS{avoid_reset_quirk}=="0"
    ATTRS{authorized}=="1"
 
device 0x2a027c10 has devpath '/devices/platform/musb_hdrc/usb2'
  looking at parent device '/devices/platform/musb_hdrc/usb2':
    KERNELS=="usb2"
    SUBSYSTEMS=="usb"
    DRIVERS=="usb"
    ATTRS{configuration}==""
    ATTRS{bNumInterfaces}==" 1"
    ATTRS{bConfigurationValue}=="1"
    ATTRS{bmAttributes}=="e0"
    ATTRS{bMaxPower}=="  0mA"
    ATTRS{urbnum}=="76"
    ATTRS{idVendor}=="1d6b"
    ATTRS{idProduct}=="0002"
    ATTRS{bcdDevice}=="0206"
    ATTRS{bDeviceClass}=="09"
    ATTRS{bDeviceSubClass}=="00"
    ATTRS{bDeviceProtocol}=="00"
    ATTRS{bNumConfigurations}=="1"
    ATTRS{bMaxPacketSize0}=="64"
    ATTRS{speed}=="480"
    ATTRS{busnum}=="2"
    ATTRS{devnum}=="1"
    ATTRS{devpath}=="0"
    ATTRS{version}==" 2.00"
    ATTRS{maxchild}=="1"
    ATTRS{quirks}=="0x0"
    ATTRS{avoid_reset_quirk}=="0"
    ATTRS{authorized}=="1"
    ATTRS{manufacturer}=="Linux 2.6.35.9-x9 musb-hcd"
    ATTRS{product}=="MUSB HDRC host driver"
    ATTRS{serial}=="musb_hdrc"
    ATTRS{authorized_default}=="1"
 
device 0x2a0286d8 has devpath '/devices/platform/musb_hdrc'
  looking at parent device '/devices/platform/musb_hdrc':
    KERNELS=="musb_hdrc"
    SUBSYSTEMS=="platform"
    DRIVERS=="musb_hdrc"
    ATTRS{modalias}=="platform:musb_hdrc"
    ATTRS{mode}=="a_host"
    ATTRS{vbus}=="Vbus off, timeout 1100 msec"
 
device 0x2a028a58 has devpath '/devices/platform'
  looking at parent device '/devices/platform':
    KERNELS=="platform"
    SUBSYSTEMS==""
    DRIVERS==""

As the message at the beginning of the output tells us we can use parameters from the child and one of the parents in the rule.
So assuming that I have somehow determined that at the moment device /dev/ttyUSB1 is a Plugwise dongle and I would like to create a symlink
/dev/plugwise for it in the future would lead us to the following udev rule:

KERNEL=="ttyUSB*", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", ATTRS{serial}=="A100dj0d", SYMLINK+="plugwise"

So lets create a configuration file for it and restart the udev:

root@beaglemonitor# echo 'KERNEL=="ttyUSB*", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", ATTRS{serial}=="A100dj0d", SYMLINK+="plugwise"' > /etc/udev/rules.d/zz-plugwise.rules
root@beaglemonitor# /etc/init.d/udev restart
Stopping the hotplug events dispatcher: udevd.
Starting the hotplug events dispatcher: udevd.
root@beaglemonitor# ls -alFs /dev/plugwise
0 lrwxrwxrwx 1 root root 7 Dec 24 15:14 /dev/plugwise -> ttyUSB1

Based on a similar process the other device will get the following rule:

KERNEL=="ttyUSB*", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", ATTRS{serial}=="A600asCw", SYMLINK+="greenhouse"