Offline
Newbie
Karma: 0
Posts: 5
|
 |
« on: February 19, 2011, 12:59:50 pm » |
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. //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
Newbie
Karma: 0
Posts: 5
|
 |
« Reply #1 on: February 19, 2011, 01:01:11 pm » |
Here is code to read the old (EM4100) tags //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
Jr. Member
Karma: 0
Posts: 63
digital artist technology-driven
|
 |
« Reply #2 on: February 24, 2011, 06:55:57 am » |
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
Newbie
Karma: 0
Posts: 5
|
 |
« Reply #3 on: February 24, 2011, 08:35:09 pm » |
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
Newbie
Karma: 0
Posts: 16
Arduino N00b
|
 |
« Reply #4 on: March 13, 2011, 12:06:10 am » |
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
|
|
|
|
|
|
|
Tennessee
Offline
Newbie
Karma: 0
Posts: 22
|
 |
« Reply #6 on: March 29, 2011, 10:26:36 am » |
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
Newbie
Karma: 0
Posts: 15
Arduino rocks
|
 |
« Reply #7 on: March 29, 2011, 04:24:09 pm » |
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.pdfPage 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
Newbie
Karma: 0
Posts: 5
|
 |
« Reply #8 on: March 29, 2011, 05:09:30 pm » |
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/PRFIDTo 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
Newbie
Karma: 0
Posts: 8
|
 |
« Reply #9 on: June 21, 2011, 09:45:46 pm » |
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. #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
Newbie
Karma: 0
Posts: 8
|
 |
« Reply #10 on: June 21, 2011, 09:47:19 pm » |
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
Newbie
Karma: 0
Posts: 8
|
 |
« Reply #11 on: June 22, 2011, 10:04:08 am » |
after some more work, i was able to get the write operation working. Here is the code i used: //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: //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
Brattain Member
Karma: 278
Posts: 25577
Solder is electric glue
|
 |
« Reply #12 on: June 22, 2011, 12:09:54 pm » |
Now all you have to learn is to use the # icon when posting code not the quote icon.
|
|
|
|
|
Logged
|
|
|
|
|
Brooklyn, NY
Offline
Newbie
Karma: 0
Posts: 8
|
 |
« Reply #13 on: June 22, 2011, 12:13:42 pm » |
what do you mean?
|
|
|
|
|
Logged
|
Did I help you? Tip me via bitcoin! 1GLKo59uimHjy8K6UbgvfS4AzqRSd3X1kw
|
|
|
|
Manchester (England England)
Offline
Brattain Member
Karma: 278
Posts: 25577
Solder is electric glue
|
 |
« Reply #14 on: June 22, 2011, 12:23:19 pm » |
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
|
|
|
|
|
|