Wednesday, July 24, 2013

Decoding/reading 125kHz RFID tags - live at GitHub

Initially I would like to create a system that could use any existing RFID-tag. That way we could use existing tags we already had from our jobs, transportation etc. So I ordered a 125kHZ RFID kit and a 13.56MHz Mifare kit. Both kits included both a reader circuit and a couple of sample cards.

When the 125kHz kit arrived I did not have the courage to connect it to my Arduino, as I was afraid of toasting the inputs with RS232 level signals. I waited for my DSO Quad pocket oscilloscope to arrive (more about that in a later post) and hooked it up. It revealed that the claim about onboard level converters for RS232 was bogus. Pin 3 was only an inverted signal of pin 2. The good thing was that I only needed the TTL level signals and that it worked great as soon as I connected pin 2 (TX) to the Arduino pin 10 and ran this sketch:
/*
 Receives from software serial, sends to hardware serial. 
 RX is digital pin 10 (connect to TX of other device)
 */
#include <SoftwareSerial.h>
SoftwareSerial mySerial(10, 11); // RX, TX

void setup() {
  Serial.begin(9600);
  Serial.println("Scan card...");
  mySerial.begin(9600); // set the data rate for the SoftwareSerial port
}

void loop() { // run over and over
  if (mySerial.available()) {
    Serial.write(mySerial.read());
  }
}

Using the serial console in the Arduino IDE I received a steady stream of lines:
4E000194380003
4E000194380003
4E000194380003
4E000194380003
Somehow I had started suspecting the cards to be EM4100 compatible, and that is a 64 bit chip.
But each line is only 14 digits - and I expected 16 hexadecimal digits (for 64 bits).
The RFID receiver circuit has a pin labelled "Manchester code output", so I decided to try and decode that signal myself. Not yet comfortable with the Arduino platform I used the tool I knew best: PHP.
My PC could not directly interface with the manchester output pin, so I used the oscilloscope's ability to dump the captured trace to a CSV-file, and then parsed the CSV using PHP.
While working on my parser I found out about two things:

  1. The 64 bits on the EM4100 chip includes 11 header bits, a stop bit and 14 parity bits. This leaves 8 bits for a facility code and 32 bits for the UID.
  2. Another eBay dealer sells the same kit - and he includes a description of the serial output: 2 hex digits facility code, 10 decimal digits UID and 2 digits parity data.  

Not every trace was parsable, but I ended up with parsable CSV-files for each of the cards supplied with the kit. The Awid chip used for access control at my old work place however could not be parsed - it seems not to be EM4100 compatible.
Using "php dump.php DATA-Thick-card-500us.csv 3 70 12 18" I can get this output:
4E 0001943800
- which almost looks like the serial output from the receiver circuit. However I have given up on the 2 parity digits - I cannot fit 14 bits in 2 hex digits ;-) But who cares - the parity data is redundant.

The dump.php program tries both manchester and biphase decoding.

Printed on the card is "0001943800 029,43256". Initially I did not get it - but it is simply the 32 bit UID as a 10 digit decimal number followed by the high and low 16 bits as decimal:  29 * 2^16 + 43256 = 0001943800.

The next step was to implement almost the same functionality on the Arduino. I was inspired by the Arduino Cookbook to use Input Capture on the 16 bit Timer/Counter1. The result was an Arduino library (EM4100) that can capture EM4100 data from a manchester signal. It is available on https://github.com/Sthing/AccessThing/tree/master/Arduino/libraries/EM4100.

About the "any tag" idea: Well - I have become (a little) wiser. There are a lot of RFID standards and de facto standards - and a lot of custom implementations. I will have to settle for less - and EM4100 and MIFARE seems like good candidates.

Now it is getting really late and in the morning my brother and I are going canoing. I should get some sleep ;-)

2 comments: