Wednesday, January 26, 2011

RFID with Arduino

If you ever wanted to integrate RFID functionality into your project, this small tutorial might help you accomplish that. I used the RDM630 module from seeedstudio in its UART version. It comes on a small board with presoldered connectors which fits perfectly on a breadboard. You only need to connect the antenna to the two pin socket. You also can connect a LED to indicate if the antenna picks up a signal. The signal output can be easily read by using the NewSoftSerial library and assigning the RX TX ports.

Here are the setup schematics:


The signal readings are transmitted in byte blocks. The first byte (02) is the start of text byte in HEX-ASCII format. Then following is the 10 byte data for the ID which has been recognized. After that a 2 byte checksum is transmitted. Followed by the last byte (03).
To translate the 10 byte HEX-ASCII data to the unique ID, you only have to map the bytes to the according ASCII character. For details have a look into the datasheet.

This is an example code which checks if the data was received correctly. It prints the ID and checks if the transmitted checksum is equal to the calculated checksum of the ID.
#include "NewSoftSerial.h"
#define stx 2
#define etx 3

NewSoftSerial mySerial(6, 7);
int counter;
byte data[14];
byte hexBlock1,hexBlock2,hexBlock3,hexBlock4,hexBlock5;
byte hexCalculatedChecksum,hexChecksum;

void setup() {
  Serial.begin(9600);
  mySerial.begin(9600);
}

void loop() {
  if (mySerial.available() > 0) {
    data[counter] = mySerial.read();
    counter++;
    if(counter > 13) {
      //we read the whole message, so reset counter
      counter = 0;
      //check if start of text and end of text is correct
      if(data[0] == stx && data[13] == etx) {
        Serial.println("Start of text and end of text correctly received.");
        Serial.print("ID: ");
        //show ID
        for(int x = 1; x < 11; x++) {
          Serial.print(data[x], BYTE);
        }
        Serial.println("");
        Serial.print("Checksum: ");
        //show checksum
        Serial.print(data[11], BYTE);
        Serial.println(data[12], BYTE);

        //Hex ID blocks. Two transmitted Bytes form one Hex ID block.
        //Hex ID blocks:      6   2  |  E   3  |  0   8  |  6   C  |  E   D
        //Transmitted Bytes: 36H 32H | 45H 33H | 30H 38H | 36H 43H | 45H 44H
        hexBlock1 = AsciiCharToNum(data[1])*16 + AsciiCharToNum(data[2]);
        hexBlock2 = AsciiCharToNum(data[3])*16 + AsciiCharToNum(data[4]);
        hexBlock3 = AsciiCharToNum(data[5])*16 + AsciiCharToNum(data[6]);
        hexBlock4 = AsciiCharToNum(data[7])*16 + AsciiCharToNum(data[8]);
        hexBlock5 = AsciiCharToNum(data[9])*16 + AsciiCharToNum(data[10]);
       
        //Transmitted checksum.
        hexChecksum = AsciiCharToNum(data[11])*16 + AsciiCharToNum(data[12]);

        //XOR algorithm to calculate checksum of ID blocks.
        hexCalculatedChecksum = hexBlock1 ^ hexBlock2 ^ hexBlock3 ^ hexBlock4 ^ hexBlock5;
        if ( hexCalculatedChecksum == hexChecksum )
        {
          Serial.println("Calculated checksum matched transmitted checksum.");
        }
        else {
          Serial.println("Calculated checksum didn't match transmitted checksum. Corrupt data!");
        }
      }
    }
  }
}

uint8_t AsciiCharToNum(byte data) {
  //First substract 48 to convert the char representation
  //of a number to an actual number.
  data -= '0';
  //If it is greater than 9, we have a Hex character A-F.
  //Substract 7 to get the numeral representation.
  if (data > 9)
    data -= 7;
  return data;
}
 
An example reading would look like this:
Start of text and end of text correctly received.
ID: 4200442C01
Checksum: 2B
Calculated checksum matched transmitted checksum.
Here is a demonstration of the RFID reader in action:

14 comments:

  1. Hi.. Nice code...

    Any ideas how to code a small user database into your code? So only "hardcoded" tags are allowed to, ex. open a door?

    ReplyDelete
  2. Well the easiest way would be to define those IDs which should be allowed to enter as byte arrays or as their hex representation and compare them against your transmitted ID. You could store them on the Arduinos EEPROM so you save some programming space.

    ReplyDelete
  3. Hey Hallo very cool program
    Im working with arduino 1 and the board arduino mega 1280
    RFID chip RDM630 wiegand,


    i wannt to do the same example, but it doesnt works,

    i just know that in arduino1 ist not necessary to put the NewSoftserial library, i made all the changes in my programm but it doesnt works, im testing with many options and but nobody hat experience with de new arduino software, im not a expert with programming but if could me say 1 or 2 tips would be very nice,,
    thanks

    ReplyDelete
  4. I hadn't much time yet to look into Arduino 1.0. I also noticed that some libraries didn't work anymore and needed to be updated. Since I am in the process of writing a book, I don't have time right now to try it myself with Arduino 1.0. You should post your problem and a link to the blog entry so people can see the code at the Arduino Forums. They are really helpful and maybe someone there had the same problem.

    http://arduino.cc/forum/

    ReplyDelete
  5. Hi Mario, I recently purchased the same module but I'm having trouble getting the LED to react to the read. Did you have to do anything special to get it to work?

    ReplyDelete
    Replies
    1. Hi Simon,

      if you connect everything like shown above in the Fritzing diagram and apply my code then you should be fine. I didn't have to do anything special. Just make sure that your LED is connected with the correct polarity and maybe test it with a small circuit to make sure that it is working at all.

      Is it just the LED which isn't working correctly? Do you receive correct tag readings at least?

      Regards,
      Mario

      Delete
    2. Yeah, everything works just fine. I tried to connect my device just the way you shown and, no luck. Now, there's one small difference between your device and mine (I believe) which is, yours is a RDM630 and mine is a RDM6300. From everything I read about it, it seems to be 100% compatible with the RDM630. The main difference seems to be the distance at which it can read the tag.

      The LED works just fine, as it stays on all the time.

      Thanks for your quick reply! Hope I can figure this out :)

      Delete
    3. I also have a RDM6300 and the LED is also continuous on.
      Another thing: the checksum is displayed as wrong when using this code. I ll try to find out what goes wrong.

      Delete
  6. sir mario this error appear,

    'NewSofSerial' does not name a type:

    As of Arduino 1.0, the 'BYTE' keyword is no longer supported.
    Please use Serial.write() instead.

    i look forward for your response thank you

    ReplyDelete
    Replies
    1. Bakasi, that's because you don't have NewSoftSerial installed.

      Just use "SoftwareSerial.h" in include instead.
      And change lines to

      Serial.write(data[x]);


      Or search google for NewSoftSerial and install :P

      Delete
  7. Btw, Mr. Mario, your code works perfect for me, apart from one thing:
    The ID gets read 8 times and then not anymore. Have to reset the Arduino for it to read again. And once more, 8 times and that's it...

    Any idea? How could I test if it's a serial problem or antena problem?

    ReplyDelete
  8. Hi Simon,
    I'm doing a project with RDM630 with Wiegand interface and I can not edit the module correctly in Fritzing, I'm using the part editor but I can not leave as nice as you have in your sketch. Would you be kind enough to comment on how you got to create the component in Fritzing?
    Thank you!

    ReplyDelete
  9. Hi,

    Can you post schematics for this project?
    .fzz or .fzpz files

    thanks..

    ReplyDelete
  10. As part of a project for opening garage doors, I've rewritten the code above.
    It takes less RAM, probably less ROM too. In the code above, in case a byte from the RFID module gets lost, the code above will loose sync and will no longer be capable of reading tags until you reset it. The code below fixes this.
    https://github.com/LieBtrau/Aiakos

    ReplyDelete