Shop OBEX P1 Docs P2 Docs Learn Events
Interface Arduino to RFID Read/Write — Parallax Forums

Interface Arduino to RFID Read/Write

bhclowersbhclowers Posts: 3
edited 2011-12-06 18:19 in Accessories
After mining the forums I've yet to see a fully working arduino sketch that demonstrates the use of the Parallax RFID Read/Write module. I was hoping that someone on this forum might be able to shed some light onto this issue and help what appear to be a sizable group of people out. For more background please see:

http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1285104792/all

I've basically tried the code posted on the above forum but seem to get read errors associated when a tag is placed in proximity to the reader. At this point I am not trying to write, only read. After diving into the documentation and looking at the returned error codes I am usually getting errors 2 and 3 followed by the occasional 7 (parity error).

I am using the following products specifically:

28440 RFID Read/Write Module

28142 50mm Round RFID Tag


Am I just a bonehead and using the wrong tag or is there something more wrong?

Below is the code that is run on the arduino. For the record I'm running using an Arduino Pro 5V/18MHz. I've tried running the system using the USB port and also from an external supply.

Cheers,

Brian

#####################
//Interface Arduino USB with Parallax 125 Khz UART RFID Reader/Writer
#include "NewSoftSerial.h"

#define rxPin 8
#define txPin 6

//Reader/Writer Commands
#define RFID_READ 0x01
#define RFID_WRITE 0x02

//Memory Locations for Data
#define DATA_ADDR_0 3
#define DATA_ADDR_1 4


//Error Codes
#define ERR_OK 0x01

NewSoftSerial mySerial(rxPin, txPin);
char statusCode;

void setup()
{
Serial.begin(9600);
pinMode(rxPin, INPUT);
pinMode(txPin, OUTPUT);
mySerial.begin(9600);
Serial.println("RFID Read/Write Test");
}

void loop()
{
Serial.println("Reading Tag Data...");
//1st 4 bytes
mySerial.print("!RW");
mySerial.print(RFID_READ, BYTE);
mySerial.print(32, DEC);

while(mySerial.available())
{
//this is where it halts..
}

Serial.print("Read Status:");
statusCode = mySerial.read();
if(statusCode == ERR_OK)
{
Serial.println("OK");
Serial.print("RFID Data:");
Serial.print(mySerial.read(), BYTE);
Serial.print(mySerial.read(), BYTE);
Serial.print(mySerial.read(), BYTE);
Serial.println(mySerial.read(), BYTE);
}
else
{
Serial.print("NOT OK. Error Code:");
Serial.println(statusCode, HEX);
}


}

Comments

  • FranklinFranklin Posts: 4,747
    edited 2011-02-08 19:48
    Have you tried the code posted in your link by DIXIS? He said it worked. Or this http://www.arduino.cc/playground/Learning/PRFID
  • bhclowersbhclowers Posts: 3
    edited 2011-02-08 20:03
    Yes, I have tried to modify that code to work with the RFID Reader/Writer. The code you are referring to you is specifically for the RFID reader which apparently has a different interface that the read/write module. Most notably is the serial interface with the reader is at 2400 baud and the read/writer at 9600. Additionally, it is my understanding that with the read/write module a specific command sequence must be send to tell the module to either read or write, whereas the reader module does not require a serial command and can be turned on by a simple hi/lo sequence. So you see, the RFID Reader appears to work fine, but the read/write module is a different beast.
  • Mike GreenMike Green Posts: 23,101
    edited 2011-02-08 22:34
    Your mySerial.print( 32, DEC) should probably be mySerial.print( 32, BYTE) since its really byte data, not strings of decimal digits.

    Similarly Serial.print( mySerial.read(), BYTE) should probably be Serial.print( mySerial.read(), HEX).

    You really have to keep straight what's for human consumption (DEC / HEX) and what's for electronic consumption (BYTE).
  • bhclowersbhclowers Posts: 3
    edited 2011-02-10 06:44
    Thanks Mike,

    That is a good catch. Unfortunately, that doesn't seem to solve the problem. I still just observe errors 2,3, and occasionally 7 back from the module. I'm totally stumped and at the limits of my knowledge. Any help from the community would be fantastic.

    Cheers,

    Brian
  • uberdudeuberdude Posts: 7
    edited 2011-02-10 17:14
    I've been having the same problems getting my 28440 to work. I can get the LED to flash red very quickly when I send a !RW command but no response from the unit. Is the LED supposed to flash or, when things are functioning properly, is it solid red?

    Thanks
  • uberdudeuberdude Posts: 7
    edited 2011-02-12 15:29
    Using a modified version of your code, I was able to get the reader to work. Unfortunately, I only have legacy tags. I need to get some updated tags to test all the functionality.

    Even if we never figure out how to fully interface this with an Arduino, we at least get a reader that works at 9600 baud rather than 2400. Also thanks to djmagic for part of the code.

    //Interface Arduino USB with Parallax 125 Khz UART RFID Reader/Writer
    #include "NewSoftSerial.h"

    #define rxPin 8
    #define txPin 6

    //Reader/Writer Commands
    //#define RFID_READ 0x01
    //#define RFID_WRITE 0x02
    #define RFID_LEGACY 0x0F

    //Memory Locations for Data
    //#define DATA_ADDR_0 3
    //#define DATA_ADDR_1 4

    //Error Codes
    #define ERR_OK 0x01

    NewSoftSerial mySerial(rxPin, txPin);
    char statusCode;
    int val = 0;
    char code[10];
    int bytesread = 0;
    void setup()

    {
    Serial.begin(9600);
    pinMode(rxPin, INPUT);
    pinMode(txPin, OUTPUT);
    mySerial.begin(9600);
    Serial.println("RFID Read/Write Test");
    }

    void loop()
    {
    // Serial.println("Reading Tag Data...");
    mySerial.print("!RW");
    mySerial.print(RFID_LEGACY, BYTE);
    //mySerial.print(32, BYTE);

    if(mySerial.available() > 0) { // if data available from reader

    if((val = mySerial.read()) == 10) { // check for header
    bytesread = 0;
    while(bytesread<10) { // read 10 digit code
    if( mySerial.available() > 0) {
    val = mySerial.read();
    if((val == 10)||(val == 13)) { // if header or stop bytes before the 10 digit reading
    break; // stop reading
    }
    code[bytesread] = val; // add the digit
    bytesread++; // ready to read next digit
    }
    }
    if(bytesread == 10) { // if 10 digit read is complete
    Serial.print("TAG code is: "); // possibly a good TAG
    Serial.println(code); // print the TAG code
    }
    bytesread = 0;
    delay(500); // wait for a 1/2 second
    }
    }
    }
  • uberdudeuberdude Posts: 7
    edited 2011-02-14 02:01
    After looking over you code, I think I see your problem, bhclowers. Specifically, you define statusCode as a char. In comparison to my code, I define val as an int. Try int statusCode and see if that works. I believe this manifests itself as a problem in the line if(statusCode == ERR_OK). There, you are comparing a char to a Hex value. I ran into several problems when I tried to do comparisons on the stuff I was getting from the legacy tags (code to follow in next post). Another thing you can try is the function memcmp rather than a == (see next post for an example). The arduino environment seems to do funny things when using a == on two different data types (i.e. char and Hex).

    Finally, have you tried doing something like:
    mySerial.print("!RW");
    mySerial.print(RFID_READ, BYTE);
    mySerial.print(32, BYTE);

    if(mySerial.available() > 0) {
    Serial.print("RFID Data:");
    Serial.println(mySerial.read(), HEX);
    Serial.print(mySerial.read(), HEX);
    Serial.print(mySerial.read(), HEX);
    Serial.print(mySerial.read(), HEX);
    Serial.print(mySerial.read(), HEX);
    }

    and seeing what you get. Even if you get garbage, at least you know something is flowing off the tag, into the reader and into the arduino, you just need to figure out how to interpret it. Though, if all you are getting is 0xFF (which shows up as a y with dots over it on the serial monitor) that could mean you're not getting anything. I'm not sure if it comes from the reader or the arduino, but it seems like 0xFF is what is returned if no data is available. I've gotten some partial tag reads and the last few bytes come out as 0xFF. Good luck! My read/write tags are in the mail so I hope you're able to get this working.
  • uberdudeuberdude Posts: 7
    edited 2011-02-14 02:06
    As promised, here is the code I wrote. It is just a simple program to turn on a green LED if one tag is identified and turn on a red LED if the other tag is identified. I was running into all sorts of problems trying to compare strings and char arrays and values etc. But memcmp finally did the trick.

    //Interface Arduino USB with Parallax 125 Khz UART RFID Reader/Writer
    #include "NewSoftSerial.h"

    #define rxPin 8
    #define txPin 6

    //Reader/Writer Commands
    //#define RFID_READ 0x01
    //#define RFID_WRITE 0x02
    #define RFID_LEGACY 0x0F

    //Error Codes
    #define ERR_OK 0x01

    NewSoftSerial mySerial(rxPin, txPin);
    char statusCode;
    int val = 0;
    char code[11];
    int bytesread = 0;

    //Tags
    char TAG1[10] = {'0','8','0','0','E','2','8','C','6','0'};
    char TAG2[10] = {'0','8','0','0','D','9','E','4','3','E'};

    void setup()

    {
    Serial.begin(9600);
    pinMode(rxPin, INPUT);
    pinMode(txPin, OUTPUT);
    pinMode(2, OUTPUT);
    pinMode(4, OUTPUT);
    mySerial.begin(9600);
    Serial.println("RFID Read/Write Test");
    }

    void loop()
    {
    mySerial.print("!RW");
    mySerial.print(RFID_LEGACY, BYTE);
    //mySerial.print(32, BYTE);

    if(mySerial.available() > 0) { // if data available from reader

    if((val = mySerial.read()) == 10) { // check for header
    bytesread = 0;
    while(bytesread<10) { // read 10 digit code
    if( mySerial.available() > 0) {
    val = mySerial.read();
    if((val == 10)||(val == 13)) { // if header or stop bytes before the 10 digit reading
    break; // stop reading
    }
    code[bytesread] = val; // add the digit
    bytesread++; // ready to read next digit
    }
    }
    if(bytesread == 10) { // if 10 digit read is complete
    Serial.print("TAG code is: "); // possibly a good TAG
    Serial.println(code); // print the TAG code
    }
    bytesread = 0;

    if (memcmp(code, TAG1, 10) == 0){
    digitalWrite(4, HIGH); //light the Red LED
    }

    if (memcmp(code, TAG2, 10) == 0){
    digitalWrite(2, HIGH); //light the green LED
    }
    delay(500); // wait for a 1/2 second
    digitalWrite(2, LOW);
    digitalWrite(4, LOW); //reset LEDs to off
    }
    }
    }
  • uberdudeuberdude Posts: 7
    edited 2011-02-19 09:36
    Got it! Here is my super simple code that reads a read/write tag and prints the data to the screen. This is nothing fancy and honestly is pretty ugly code (should have used a loop), but it gets the job done.
    //Interface*Arduino*USB*with*Parallax*28440*125*Khz*UART*RFID*Reader/Writer
    //Program*reads*a*EM4x50*tag*and*reports*the*ID*on*the*serial*monitor.
    //Coded*by*Uberdude

    #include*"NewSoftSerial.h"
    #define*txPin*6
    #define*rxPin*8

    //Reader/Writer*Commands
    #define*RFID_READ*0x01
    //#define*RFID_WRITE*0x02
    //#define*RFID_LEGACY*0x0F

    NewSoftSerial mySerial(rxPin, txPin);
    int val = 0;
    //char*code[6];*****//Note*this*is*11*for*the*extra*null*char?
    //int*bytesread*=*0;
    //int*flag*=*0;

    //Tags
    //char*TAG1[11]*=*"0800E28C60";
    //char*TAG2[11]*=*"0800D9E43E";

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

    **// pinMode(2, OUTPUT);
    **// pinMode(4, OUTPUT);
    **pinMode(txPin, OUTPUT); //pin 6
    **pinMode(rxPin, INPUT); //pin 8

    **Serial.println("RFID Read/Write Test");
    }

    void loop()
    {
    **mySerial.print("!RW");
    **mySerial.print(RFID_READ, BYTE);
    **mySerial.print(3, BYTE);

    **//0th read
    **if(mySerial.available() > 0) { // if data available from reader
    ****val*=*mySerial.read();
    ****if(val != 255){
    ******Serial.print("Error Code:");
    ******Serial.println(val, HEX);
    ****}
    **}*

    **//1st byte
    **if(mySerial.available() > 0) { // if data available from reader
    ****val*=*mySerial.read();
    ****if(val != 255){
    ******Serial.print("1st:");
    ******Serial.println(val, HEX);
    ****}
    **}*

    **//2nd byte
    **if(mySerial.available() > 0) { // if data available from reader
    ****val*=*mySerial.read();
    ****if(val != 255){
    ******Serial.print("2nd:");
    ******Serial.println(val, HEX);
    ****}
    **}*

    **//3rd byte
    **if(mySerial.available() > 0) { // if data available from reader
    ****val*=*mySerial.read();
    ****if(val != 255){
    ******Serial.print("3rd:");
    ******Serial.println(val, HEX);
    ****}
    **}*

    **//4th byte
    **if(mySerial.available() > 0) { // if data available from reader
    ****val*=*mySerial.read();
    ****if(val != 255){
    ******Serial.print("4th:");
    ******Serial.println(val, HEX);
    ****}
    **}*

    **delay(500); // wait for a 1/2 second
    }**

    Note that if you have a rectangular read/write tag from parallax like I have, they come pre loaded with 0xFEEDBEEF in the first data address. If you didn't get your tags from there, or have a round tag, it should show up as 4 zeros. Alternately just change the the mySerial.print(3, BYTE); to mySerial.print(33, BYTE); which will read the unique serial ID. One thing that screwed me up for a long time is that the first byte of data in the ID could be a 1 which I was thinking was the error code. Hence why I went to this ugly code explicitly stating what the bytes I was getting.

    There are vast improvements which could be made on this code. I will continue to refine it, but figured I'd post something as soon as I got it working.
  • uberdudeuberdude Posts: 7
    edited 2011-02-19 10:03
    Link to Arduino forum topic I posted where the code formatting is better:

    http://arduino.cc/forum/index.php/topic,52811.0.html
  • gluontronicgluontronic Posts: 6
    edited 2011-02-24 04:15
    working on this (too)
    final target: max msp patch to encode my own rfid tags through arduino.

    any piece of code to do that ?

    I read carefully page 4 of the datasheet:
    0x02: RFID_Write
    Write data to a specified address
    Input: Address location (1 byte), valid locations are 3-31 decimal + data (4 bytes)
    Output: Status byte (1 byte)
    Example:
    ' Write $FEEDBEEF to address 3 (User Data Area)
    SEROUT RFID_TX, Baud, ["!RW", RFID_Write, 3, $FE, $ED, $BE, $EF]
    SERIN RFID_RX, Baud, [err] ' Get status byte
    Note: After writing the specified data to the tag, the RFID Read/Write Module automatically performs a
    read function to verify that the data has properly been written.

    I did that for the part to write on the tag:
    mySerial.print("!RW");
    mySerial.print(0x02, BYTE);
    mySerial.print(3, BYTE);
    mySerial.print(0, BYTE);
    mySerial.print(1, BYTE);
    mySerial.print(2, BYTE);
    mySerial.print(3, BYTE);

    but it doesn't work :-/
  • uberdudeuberdude Posts: 7
    edited 2011-03-09 15:40
    Finally got around to writing this, its been working for me. Good luck.


    //Interface Arduino USB with Parallax 28440 125 Khz UART RFID Reader/Writer
    //Program reads a EM4x50 tag and reports the ID on the serial monitor.
    //Coded by Uberdude

    #include "NewSoftSerial.h"
    #define txPin 6
    #define rxPin 8

    //Reader/Writer Commands
    #define RFID_READ 0x01
    #define RFID_WRITE 0x02
    #define RFID_LOGIN 0x03
    #define RFID_PROTECT 0x05
    //#define RFID_LEGACY 0x0F

    NewSoftSerial mySerial(rxPin, txPin);
    int val = 0;
    //char code[6]; //Note this is 11 for the extra null char?
    //int bytesread = 0;
    //int flag = 0;

    //Tags
    //char TAG1[11] = "0800E28C60";
    //char TAG2[11] = "0800D9E43E";

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

    // pinMode(2, OUTPUT);
    // pinMode(4, OUTPUT);
    pinMode(txPin, OUTPUT); //pin 6
    pinMode(rxPin, INPUT); //pin 8

    Serial.println("RFID Write Normal");
    }

    void loop()
    {
    mySerial.print("!RW");
    mySerial.print(RFID_WRITE, BYTE);
    mySerial.print(3, BYTE);
    mySerial.print(0xCC, BYTE);
    mySerial.print(0xCC, BYTE);
    mySerial.print(0xCC, BYTE);
    mySerial.print(0xCC, BYTE);

    //Error code read
    if(mySerial.available() > 0) { // if data available from reader
    val = mySerial.read();
    if(val != 255){
    Serial.print("Write Error Code:");
    Serial.println(val, HEX);
    }
    }

    mySerial.print("!RW");
    mySerial.print(RFID_READ, BYTE);
    mySerial.print(3, BYTE);

    //0th read
    if(mySerial.available() > 0) { // if data available from reader
    val = mySerial.read();
    if(val != 255){
    Serial.print("Read Error Code:");
    Serial.println(val, HEX);
    }
    }

    //1st byte
    if(mySerial.available() > 0) { // if data available from reader
    val = mySerial.read();
    if(val != 255){
    Serial.print("1st:");
    Serial.println(val, HEX);
    }
    }

    //2nd byte
    if(mySerial.available() > 0) { // if data available from reader
    val = mySerial.read();
    if(val != 255){
    Serial.print("2nd:");
    Serial.println(val, HEX);
    }
    }

    //3rd byte
    if(mySerial.available() > 0) { // if data available from reader
    val = mySerial.read();
    if(val != 255){
    Serial.print("3rd:");
    Serial.println(val, HEX);
    }
    }

    //4th byte

    if(mySerial.available() > 0) { // if data available from reader
    val = mySerial.read();
    if(val != 255){
    Serial.print("4th:");
    Serial.println(val, HEX);
    }
    }

    delay(500); // wait for a 1/2 second
    }
  • YKKYKK Posts: 1
    edited 2011-12-06 18:19
    Hello all,

    So, like a few of you I have the Reader/Write working-*ish*. I can read any address & write to any address, BUT not execute more than one write operation. I am not using an Arduino board exactly(sorry forum-nazis I looked for a non-arduino thread) but I am using the Atmega324p with dual UARTs configured as specified with 9600baud/8N1. I am writing in C and here is a sample. Anyone have thoughts? I have tried so many things...

    void Write_RFID(uint8_t start_addr, uint8_t byte1, uint8_t byte2, uint8_t byte3, uint8_t byte4){
    uint8_t static err = -1;
    while(err != 1){
    UART2_Print("!RW");
    _delay_ms(1);
    UART2_TX(0x02);
    _delay_ms(1);
    UART2_TX(start_addr);
    _delay_ms(1);
    UART2_TX(byte1);
    _delay_ms(1);
    UART2_TX(byte2);
    _delay_ms(1);
    UART2_TX(byte3);
    _delay_ms(1);
    UART2_TX(byte4);
    _delay_ms(1);
    err = UART2_RX();
    }
    }

    void Read_RFID(uint8_t addr){
    uint8_t static byte1, byte2, byte3, byte4;
    err = -1;
    while(err != 1){
    UART2_Flush();
    UART2_Print("!RW");
    _delay_ms(1);
    UART2_TX(0x01);
    _delay_ms(1);
    UART2_TX(addr);
    err = UART2_RX();
    byte1 = UART2_RX();
    byte2 = UART2_RX();
    byte3 = UART2_RX();
    byte4 = UART2_RX();
    UART1_Flush();
    UART2_Flush();
    UART1_Print(itoa(byte1, buf, 16));
    UART1_Print(itoa(byte2, buf, 16));
    UART1_Print(itoa(byte3, buf, 16));
    UART1_Print(itoa(byte4, buf, 16));
    UART1_Flush();
    UART2_Flush();
    }
    }

    From my main file:

    ...



    Write_RFID(10, sample[0], sample[1], sample[2], sample[3]);
    UART1_Print("\r\nReading address:");
    Read_RFID(10);
    Write_RFID(11, sample[4], sample[5], sample[6], sample[7]);
    UART1_Print("\r\nReading address:");
    Read_RFID(11);
    Write_RFID(12, sample[8], sample[9], sample[10], sample[11]);
    UART1_Print("\r\nReading address:");
    Read_RFID(12);
    UART1_Print("\r\nReading Serial:");
    Read_Serial_RFID();
    UART1_Print("\r\nReading Family:");
    Read_Family_RFID();
    UART1_Flush();
    UART2_Flush();

    ...

    To make this work, I MUST use only one of the Write_RFID calls at a time, power cycle, comment out the used one, uncomment the next, recompile, and it will write the next address as requested. It will NOT do consecutive calls to the Write_RFID. It's driving me crazy, really. I can't see any reason why I can't increment the address by one, write the next 4 bytes of a string, and repeat so long as I am still within the user data write area of 116 bytes. Is there something I need to do about the auto-read operation after each write?

    -YKK
Sign In or Register to comment.