Interface Arduino to RFID Read/Write
bhclowers
Posts: 3
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);
}
}
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
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).
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
Thanks
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
}
}
}
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.
//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
}
}
}
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.
http://arduino.cc/forum/index.php/topic,52811.0.html
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:
I did that for the part to write on the tag:
but it doesn't work :-/
//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
}
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