Pages: [1] 2   Go Down
Author Topic: Parallax RFID Read/Write Module 28440  (Read 4764 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 6
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Looking through the forums here and on parallax it looks like several people have had trouble getting the Parallax RFID Read/Write Module 28440 to correctly interface with the Arduino. The read/write module is a vast improvement over the old, read only module. The old module has numerous examples of how to code it for an Arduino. The new module is 4 times as fast, backwards compatible with with old reader tags and also supports write functionality.

I finally got it working so I thought I'd share my code. Note that this is a very rough and ugly code, but it works. I will be refining it over the next few days, but figured I'd post it as soon as I got it working to relieve frustration and also let others play with the code.

Here is the code for reading new style (EM4x50) tags.
Quote
//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.

Enjoy
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 6
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Here is code to read the old (EM4100) tags
Quote
//Interface Arduino USB with Parallax 28440 125 Khz UART RFID Reader/Writer
//Current program reads a legacy tag and lights an LED based on which tag it is.
//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

//Error Codes
//#define ERR_OK 0x01

NewSoftSerial mySerial(rxPin, txPin);
char statusCode;
int  val = 0;
char code[11];     //Note this is 11 for the extra null char?
int bytesread = 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_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(2, HIGH);          //light the Green LED
      }

      if (memcmp(code, TAG2, 10) == 0){
        digitalWrite(4, HIGH);        //light the Red LED
      }      
      delay(500);                       // wait for a 1/2 second
      digitalWrite(2, LOW);
      digitalWrite(4, LOW);            //reset LEDs to off
    } 
  } 

Logged

France
Offline Offline
Jr. Member
**
Karma: 0
Posts: 64
digital artist
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

about the write part?
I'm designing a patch in max/msp to encode bytes on rfid tags.

do you have an example of code to write on rfid tags from arduino?
Logged


Offline Offline
Newbie
*
Karma: 0
Posts: 6
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I haven't gotten around to sketching any code to write to RFID tags, but from the documentation provided for the 28440, it should be fairly easy. Just have to watch that the data you're writing is in byte.
Logged

Canada
Offline Offline
Newbie
*
Karma: 0
Posts: 16
Arduino N00b
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I tried your code exactly and I can't get anything to happen, well the led on the rfid flashes from red to green(or yellow) when a tag gets close but it doesn't print out... a little help please. Maybe I connected it wrong

Arduino D8 = RFID VCC
Arduino D6 = RFID SN
Arduino 5v = RFID SOUT
Arduino GND = RFID GND
« Last Edit: March 13, 2011, 12:07:54 am by RenRen » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 6
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Arduino 5v = RFID VCC (Vcc means positive voltage)
Arduino D6 = RFID SIN  (Serial In)
Arduino D8 = RFID SOUT (Serial Out)
Arduino GND = RFID GND (Ground)

Also, Here is the link to the tag writing code, I haven't reposted it cause I'm lazy.

http://forums.parallax.com/showthread.php?129430-Interface-Arduino-to-RFID-Read-Write
Logged

Tennessee
Offline Offline
Newbie
*
Karma: 0
Posts: 22
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

May I ask a stupid question?

In UberDude's code above (1st post), he shows the serial number of 2 of the tags he was using (they're commented out) 0800E28C60 and 0800D9E43E.  Both of these serial numbers have 10 digits (5 Bytes) but he is only reading 4 bytes with the code, and the .PDF on the tag states that the tag's serial number is 32 bit (4 bytes).  I'm lost...
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 15
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
In UberDude's code above (1st post), he shows the serial number of 2 of the tags he was using (they're commented out) 0800E28C60 and 0800D9E43E.  Both of these serial numbers have 10 digits (5 Bytes) but he is only reading 4 bytes with the code, and the .PDF on the tag states that the tag's serial number is 32 bit (4 bytes).

Fair enough to say, a legacy read gets you the serial number of a legacy tag
header+10 bytes(40 bits)+footer

So if you were using legacy tags, you would need to code for it.

A read of a read/write tag gets you a the data from the specified address (1-33)
status + 4 bytes(32 bits)

Each of the 33 data locations has 4 bytes!
Of these locations, 3-31 are writable!

So you need to write to a tag, before you will see anything meaningful

the status codes all not explicitly mentioned anywhere in the datasheet, are in the stamp example code.
http://www.parallax.com/Portals/0/Downloads/docs/prod/rf/28440-RFIDReadWrite-v1.0.pdf
Page 10 at the top

ERR_OK                   0x01   ' No errors
ERR_LIW                 0x02   ' Did not find a listen window
ERR_NAK                 0x03   ' Received a NAK, could be invalid command
ERR_NAK_OLDPW    0x04   ' Received a NAK sending old password (RFID_SetPass), could be incorrect password
ERR_NAK_NEWPW   0x05   ' Received a NAK sending new password (RFID_SetPass)
ERR_LIW_NEWPW    0x06   ' Did not find a listen window after sending old password (RFID_SetPass)
ERR_PARITY             0x07   ' Parity error when reading data
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 6
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The two tags that are commented out are from an earlier program which reads the legacy tags. You can also see the hex code for reading a legacy code (0x0F) also commented out. You can pretty much just use the code from the old read only module:

http://www.arduino.cc/playground/Learning/PRFID

To get a read on a legacy tag, hence I didn't bother posting that since its pretty much a solved problem. But as far as I could tell, no one had written any code for the read/write module. Good luck
Logged

Brooklyn, NY
Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

here is my slightly modified & (in my opinion) more elegant-looking version of uberdude's "read" code for the new (black) parallax RFID readers. I modified his code to suppress the "null reads" which occur when no card is present and quickly take up the whole monitor. I also suppressed  the error codes, as I saw no real need for them.

Quote
#include <NewSoftSerial.h>
#define RFID_READ 0x01
#define txPin 6
#define rxPin 8

NewSoftSerial mySerial(rxPin, txPin);
int val;
int runs = 0;

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

void suppressAll()                                //suppresses the "null result" from being printed if no RFID tag is present
{
    if(mySerial.available() > 0)
    { mySerial.read();
      suppressAll();
    }
}

void loop()
{
 int val;
  mySerial.print("!RW");
  mySerial.print(RFID_READ, BYTE);
  mySerial.print(32, BYTE);
  
  if(mySerial.available() > 0)
  {      
    val = mySerial.read();                        //The mySerial.read() procedure is called, but the result is not printed because I don't want the "error message: 1" cluttering up the serial monitor
      if (val != 1)                                   //If the error code is anything other than 1, then the RFID tag was not read correctly and any data collected is meaningless. In this case since we don't care about the resultant values they can be suppressed
       {suppressAll();}                              
  }      
 

 if(mySerial.available() > 0) {      
    val = mySerial.read();
    Serial.print("1st:");
    Serial.println(val, HEX);
    }

if(mySerial.available() > 0) {        
    val = mySerial.read();
    Serial.print("2nd:");
    Serial.println(val, HEX);
    }
    
if(mySerial.available() > 0) {      
    val = mySerial.read();
    Serial.print("3rd:");
    Serial.println(val, HEX);
    }
    
if(mySerial.available() > 0) {          
    val = mySerial.read();
    Serial.print("4th:");
    Serial.println(val, HEX);
    Serial.println("-----------------");
    }  
 
delay(750);
}

« Last Edit: June 21, 2011, 10:22:55 pm by vgrhcp » Logged

Did I help you? Tip me via bitcoin!
1GLKo59uimHjy8K6UbgvfS4AzqRSd3X1kw

Brooklyn, NY
Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

also, a huge thanks to uberdude for your original code. I am fairly new to programming and it would have taken me ages to figure out the basic functionality on my own...thanks!
Logged

Did I help you? Tip me via bitcoin!
1GLKo59uimHjy8K6UbgvfS4AzqRSd3X1kw

Brooklyn, NY
Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

after some more work, i was able to get the write operation working. Here is the code i used:

Quote
//Code to write data to Parallax RFID reader/writer 28440 from Arduino
//Program writes to one of the 29 user-defined addresses (3-31) as define by whichSpace
//The four bytes to be written are defined by first, second, third, and fourth
//Coded by vgrhcp

#include <NewSoftSerial.h>
#define RFID_WRITE 0x02
#define txPin 6
#define rxPin 8

#define whichSpace 4

#define first 1
#define second 26
#define third 3
#define fourth 27

NewSoftSerial mySerial(rxPin, txPin);

void setup()
{
  Serial.begin(9600);
  Serial.println("RFID Write Test");
  mySerial.begin(9600);
  pinMode(txPin, OUTPUT);    
  pinMode(rxPin, INPUT);      
}
 
 
void suppressAll()                            //Keeps error code & the "write confirmation" codes from being printed in the serial monitor      
{
    if(mySerial.available() > 0)
    { mySerial.read();
      suppressAll();
    }
}
 
 void loop()
{
  int val;
  
  mySerial.print("!RW");
  mySerial.print(RFID_WRITE, BYTE);
  mySerial.print(whichSpace, BYTE);
  mySerial.print(first, BYTE);
  mySerial.print(second, BYTE);
  mySerial.print(third, BYTE);
  mySerial.print(fourth, BYTE);

if(mySerial.available() > 0) {        
    val = mySerial.read();
    if (val == 1)                                        //If data was written successfully
      { Serial.println("Data written succesfully!");
        suppressAll();
      }
    else suppressAll();                                  //If an error occured during writing, discard all data recieved from the RFID writer
    }
delay(250);
}





I just have one problem now...my code writes data as bytes, as it must for the RFID writer to understand it (i tried writing as DEC and HEX, but it did not work). However, the read code that uberdude wrote and i modified prints the values it reads as HEX. So the issue is that if you write, say, 26 as one of the bytes onto a card and then read it, it will come up as 1A, which is the HEX value that corresponds to 26. To solve this, you must change the read procedure form printing HEX to DEC like so:

Quote
//Code to read data from Parallax RFID reader/writer 28440 via Arduino
//Program reads data from one of the 29 user-defined addresses (3-31) as define by whichSpace
//Writen by vgrhcp based on code by uberdude

#include <NewSoftSerial.h>
#define RFID_READ 0x01
#define txPin 6
#define rxPin 8

#define whichSpace 4

NewSoftSerial mySerial(rxPin, txPin);
int val;
int runs = 0;

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

void suppressAll()                                //suppresses the "null result" from being printed if no RFID tag is present
{
    if(mySerial.available() > 0)
    { mySerial.read();
      suppressAll();
    }
}

void loop()
{
  int val;
  mySerial.print("!RW");
  mySerial.print(RFID_READ, BYTE);
  mySerial.print(whichSpace, BYTE);
  
  if(mySerial.available() > 0)
  {      
    val = mySerial.read();                        //The mySerial.read() procedure is called, but the result is not printed because I don't want the "error message: 1" cluttering up the serial monitor
      if (val != 1)                               //If the error code is not 1, then there has been an error and the RFID tag was not read correctly.In this case we don't really care about the resultant values, so they can be suppressed
       {suppressAll();}                              
  }      
 

 if(mySerial.available() > 0) {      
    val = mySerial.read();
    Serial.print("1st:");
    Serial.println(val, DEC);
    }

if(mySerial.available() > 0) {        
    val = mySerial.read();
    Serial.print("2nd:");
    Serial.println(val, DEC);
    }
    
if(mySerial.available() > 0) {      
    val = mySerial.read();
    Serial.print("3rd:");
    Serial.println(val, DEC);
    }
    
if(mySerial.available() > 0) {          
    val = mySerial.read();
    Serial.print("4th:");
    Serial.println(val, DEC);
    Serial.println("-----------------");
    }  
 
delay(750);
}



these two codes are now fully compatible with each other; so long as the whichSpace is set to the same value (3-31) in each program, the reader will read whatever was written by the writer. Enjoy!
« Last Edit: June 22, 2011, 03:06:24 pm by vgrhcp » Logged

Did I help you? Tip me via bitcoin!
1GLKo59uimHjy8K6UbgvfS4AzqRSd3X1kw

Manchester (England England)
Offline Offline
Brattain Member
*****
Karma: 596
Posts: 33283
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Now all you have to learn is to use the # icon when posting code not the quote icon.
Logged

Brooklyn, NY
Offline Offline
Newbie
*
Karma: 0
Posts: 8
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

what do you mean?
Logged

Did I help you? Tip me via bitcoin!
1GLKo59uimHjy8K6UbgvfS4AzqRSd3X1kw

Manchester (England England)
Offline Offline
Brattain Member
*****
Karma: 596
Posts: 33283
Solder is electric glue
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

When posting code, select the code and hit the # icon not the quote icon next to it. Then you get a nice scrolling box and the software doesn't mess up square brackets and interpreted them as formatting.
Logged

Pages: [1] 2   Go Up
Jump to: