Ghent, Belgium
Offline
Newbie
Karma: 1
Posts: 30
Arduino rocks
|
 |
« on: August 27, 2007, 12:46:16 pm » |
Hello everybody, After weeks of intense testing I succeeded in reading tag codes from the 13.56Mhz APSX RW-210 rfid reader! This is the code: http://www.technicum.net/rfid/rfid_read.pdeIt sends the read command via software serial to the rfid reader. Next it reads in the Tag code via hardware serial. Finally it prints a nice tag code to the computer! Now the problematic part; As a next step I wanted to compare the tag code to a list of known tags and then do a certain action (for example blink a led). I've been struggling with this for a week now so I decided to ask for some help. This is one of my numerous attempts :-[ #include <SoftwareSerial.h>
#define rxPin 7 #define txPin 2
// set up a new serial port SoftwareSerial mySerial = SoftwareSerial(rxPin, txPin); int serIn; // var that will hold the bytes-in read from the serialBuffer byte serInString[12]; // array that will hold the different bytes int serInIndx = 0; // index of serInString[] in which to inser the next incoming byte int serOutIndx = 0; // index of the outgoing serInString[] array; int ledPin = 13; // LED connected to digital pin 13 char Tag1[] = "001B4EC1D014E0D57B"; //known tag code, should become a list of 50+ tags
void setup() { // define pin modes for tx, rx, led pins: pinMode(rxPin, INPUT); pinMode(txPin, OUTPUT); pinMode(ledPin, OUTPUT); // sets the digital pin as output mySerial.begin(19200); // set the data rate for the SoftwareSerial port Serial.begin(19200); // opens serial port, sets data rate to 19200 bps }
void loop () { mySerial.print(0xfa, BYTE); // request tag code // only if there are bytes in the serial buffer execute the following code if(serialAvailable()) { //keep reading from serial untill there are bytes in the serial buffer while (serialAvailable()){ serIn = serialRead(); //read Serial serInString[serInIndx] = serIn; //insert the byte you just read into the array at the specified index serInIndx++; //update the new index } //feedback that something was received Serial.println ("Processing Tag"); } //do somenthing else perhaps wait for other data. Serial.println ("NO TAG "); //print out later in the loop the sentence only if it has actually been collected; if( serInIndx > 0) { Serial.print("Tag ID="); //loop through all bytes in the array and print them out for(serOutIndx=0; serOutIndx < serInIndx; serOutIndx++) { Serial.print((serInString[serOutIndx]), HEX ); //print out the byte at the specified index if((serInString[12], HEX) == Tag1[19]) { //compare received tag code to known tag code digitalWrite(ledPin, HIGH); // if true blink led delay(500); digitalWrite(ledPin, LOW); delay(500); digitalWrite(ledPin, HIGH); delay(500); digitalWrite(ledPin, LOW); delay(500); } //serInString[serOutIndx] = ""; //optional: flush out the content } //reset all the functions to be able to fill the string back with content Serial.flush(); //flush serial buffer serOutIndx = 0; serInIndx = 0; } //slows down the visualization in the terminal Serial.println(); delay(200); }
The tag code "001B4EC1D014E0D57B" is the code that I have copied from serial monitor after reading a tag. All my attempts won't make the led blink  Can someone please help me, I would like to put 50+ tags in the memory that trigger a certain action. Kind Regards, Loïc
|
|
|
|
« Last Edit: August 27, 2007, 03:38:39 pm by Loic »
|
Logged
|
|
|
|
|
0
Offline
Faraday Member
Karma: 6
Posts: 2504
|
 |
« Reply #1 on: August 28, 2007, 09:10:13 am » |
The tag code "001B4EC1D014E0D57B" is the code that I have copied from serial monitor after reading a tag. This is probably the hex representation of a binary number, not really a string. try initializing your target array like this: char target[] = {0x00, 0x1b, 0x4e, 0xc1, 0xd0, 0x14, 0xe0, 0xd5, 0x7b }; Also, I just glanced at it but your loop function doesn't look right. You are asking for a new tag every time you run loop and apparently assuming that the data will be returned immediately. This is not necessarily the case. You are also assuming that the data is made available in a single uninterupted stream, and this is almost certainly wrong. Look at the part of the code where you are reading the data; that section probably needs a re-write. I would like to put 50+ tags in the memory that trigger a certain action. Hmm, the ATmega8 only has 1k of RAM, and your target strings are about 10 bytes long, so that's half the available memory just to store the strings you are matching against. It'll probably work, as long as the rest of your code isn't too memory intensive, but you should be aware you are approching the limits of the device and method you're using. Of course, the 168 has twice the RAM and there are methods for storing data in program space (flash), but they're not as straightforward as the methods you use now. -j
|
|
|
|
|
Logged
|
|
|
|
|
Ghent, Belgium
Offline
Newbie
Karma: 1
Posts: 30
Arduino rocks
|
 |
« Reply #2 on: August 29, 2007, 09:10:58 am » |
Thank you kg4wsv, I've been trying your suggestions for the last 24hours but with no success. The code that prints the tag code back to the serial monitor was modified from code I found on the web, I'm not such good coder to be able to rewrite it with a new approach to getting the tag codes reported. But as far as printing nice unique tag codes to the serial monitor this code works perfectly, so I'm not sure the "compare tag code to list" problem I'm having is to find in the way this original code works. But being a "C" noob I could be totally wrong. Next thing I tried was using the <string.h> library, trying memcmp and strcmp. No succes  , but again could be my semi-noobness  The last weeks I've been looking at this basic stamp code that does exactly what I want to do http://www.digitaldawgpound.org/wp-content/uploads/2007/03/rw210_rfid_reader.bse (from this project http://www.digitaldawgpound.org/nick84/post=189) trying to understand the data types and sizes to work with (bytes vs chars etc). Could someone who understands the basic stamp code please help me on the right way? I really appreciate your help. Regards, Loïc
|
|
|
|
« Last Edit: August 29, 2007, 09:12:43 am by Loic »
|
Logged
|
|
|
|
|
0
Offline
Faraday Member
Karma: 6
Posts: 2504
|
 |
« Reply #3 on: August 29, 2007, 02:41:15 pm » |
String functions are not appropriate, as you are working with chinks of binary data, not strings. Specifically, C strings are null terminated arrays, which means a byte containgin 0x00 will occur after the contents of the string. In the example you are playing with, there is a null in the first array element, which means that is a zero length string as far as strcmp() and friends are concerned. memcmp may be better, but I haven't checked the docs on that one myself. Your look function needs to look something like this: #define TAG_LEN 8 char target_tag[] = {0x00, 0x1b, 0x4e, 0xc1, 0xd0, 0x14, 0xe0, 0xd5, 0x7b }; void loop() { byte bytes_read=0; char tag_read[TAG_LEN]; // code to request tag data goes here
// loop here until we get the required number of bytes back from the reader // this code will fail unpredicably in the event of communication errors while (bytes_read < TAG_LEN) while (Serial.available() > 0) tag_read[bytes_read++] = Serial.read();
// compare the tag we read to see if it matches if (memcmp(tag_read, target_tag, TAG_LEN)) do_something(); } This is off the cuff, so there may be errors, especially at the boundary conditions... -j
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
God Member
Karma: 0
Posts: 731
skcor oniudrA
|
 |
« Reply #4 on: August 29, 2007, 07:14:53 pm » |
Thank you kg4wsv, I've been trying your suggestions for the last 24hours but with no success.
Ouch, I think most of us know that all too well. Have you perhaps tried hacking this code:- http://www.arduino.cc/playground/Learning/PRFIDIt's for a parallax, but there might be something in it you could use.
|
|
|
|
|
Logged
|
|
|
|
|
Underhill Center, Vermont, USA
Offline
Jr. Member
Karma: 0
Posts: 71
Arduino rocks
|
 |
« Reply #5 on: August 29, 2007, 08:05:36 pm » |
String functions are not appropriate, as you are working with chinks of binary data, not strings.
The Parallax RFID Reader from Grand Designs sends a start byte of 0x0A, then ten hexadecimal digits in ASCII, then a stop byte 0x0D. Its all 'printable ASCII' so string functions are appropriate. Tie off the ID string by replacing the stop byte with 0x00, then use strcmp() to match to your array of valid IDs. cheers ... BBR
|
|
|
|
|
Logged
|
|
|
|
|
Ghent, Belgium
Offline
Newbie
Karma: 1
Posts: 30
Arduino rocks
|
 |
« Reply #6 on: August 30, 2007, 12:18:01 pm » |
@John Ryan: In the past I've tried to modify the parallax rfid code for weeks in a row without any succes (see my other forum post: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1186246253/15). After this I finally succeeded in printing the the tag codes to serial monitor by modifying some other code I found on the web. But with this last code (the code I posted at the beginning of this topic) I noticed that by changing the variable "serInString" from char to byte the output was always smaller and more equal in length rather than being always different from tag to tag. This is the output for 3 tags using a "char" variable: 00FFFFFFDDFFFFFF8EFFFFFF96E014FFFFFFE010FFFFFFC8 00FFFFFF989FFFFFF96E014FFFFFFE0FFFFFF857B 001B4EFFFFFFC1D014FFFFFFE0FFFFFFD57B This is the output for the same 3 tags using a "byte" variable: 00DD8E96E014E010C8 0098996E014E0857B 001B4EC1D014E0D57B These are all printed with the command "Serial.print((serInString[serOutIndx]), HEX );" I mention all this because maybe the whole problem of comparing the tags to a list is related to this. I've also spotted in the basic stamp code that the tags are in this format 'Valid tags
Tag1 DATA $00, $00, $7B, $7D, $90, $F2, $36, $07, $07, $F2, $03, $7D
Tag2 DATA $00, $00, $7D, $7D, $1E, $1F, $E0, $E6, $EF, $6E, $04, $04 Thus being 12 hex numbers while I only have 9 in two tags and even one tag (0098996E014E0857B) with 17 character that I even can't split into HEX (if you know what I mean) @brianbr: I've tried the "strcmp" command but with no succes, the led flashes, but only when wrong tags a presented. Maybe it's related to the problems described above. Does anyone see any light in this mess? :-/ Any help is really appreciated. Kind Regards, Loic
|
|
|
|
« Last Edit: August 30, 2007, 12:19:09 pm by Loic »
|
Logged
|
|
|
|
|
0
Offline
God Member
Karma: 0
Posts: 731
skcor oniudrA
|
 |
« Reply #7 on: September 02, 2007, 12:41:07 am » |
I've got the same problem, in a round about kind of way. While, my tag checking will be handled outside Arduino, I'd still like a more portable version checking tags inside Arduino.
But, converting char to string I haven't found a means to do that yet, and have spent the better part of two days searching.
|
|
|
|
|
Logged
|
|
|
|
|
Ghent, Belgium
Offline
Newbie
Karma: 1
Posts: 30
Arduino rocks
|
 |
« Reply #8 on: September 02, 2007, 12:39:47 pm » |
@John Ryan: I would be happy to work together to solve this! I've reworked my previous code based on the all suggestions. Still no luck This is it: #include <SoftwareSerial.h>
#define rxPin 7 #define txPin 2
#define TAG_LEN 12
// set up a new serial port SoftwareSerial mySerial = SoftwareSerial(rxPin, txPin);
int ledPin = 13; int serIn; byte code[TAG_LEN]; // var that will hold the bytes-in read from the serialBuffer byte bytes_read = 0; char target_tag[] = {0x00, 0x1b, 0x4e, 0xc1, 0xd0, 0x14, 0xe0, 0xd5, 0x7b };
void setup() { // define pin modes for tx, rx, led pins: pinMode(rxPin, INPUT); pinMode(txPin, OUTPUT); pinMode(ledPin, OUTPUT); mySerial.begin(19200); // set the data rate for the SoftwareSerial port Serial.begin(19200); // opens serial port, sets data rate to 19200 bps }
void loop () { mySerial.print(0xfa, BYTE); //request Tag code // only if there are bytes in the serial buffer execute the following code if(serialAvailable()) { //keep reading from serial untill there are bytes in the serial buffer while (serialAvailable() && bytes_read < TAG_LEN){ //read Serial code[bytes_read] = serialRead(); //insert the byte you just read into the array at the specified index bytes_read++; //update the new index } //feedback that something was received Serial.println ("Processing Tag"); } //do somenthing else perhaps wait for other data. Serial.println ("NO TAG "); //print out later in the loop the sentence only if it has actually been collected; if( bytes_read >= TAG_LEN) { Serial.print("Tag ID= "); //loop through all bytes in the array and print them out for(bytes_read=0; bytes_read < TAG_LEN; bytes_read++) { Serial.print((code[bytes_read]), HEX); //print out the byte at the specified index //serInString[serOutIndx] = ""; //optional: flush out the content } if (memcmp(code, target_tag, TAG_LEN) > 0) { //if received tag code == to listed tag code digitalWrite(ledPin, HIGH); //do something (blink a led) delay(500); digitalWrite(ledPin, LOW); delay(500); } //reset all the functions to be able to fill the string back with content bytes_read = 0; } //slows down the visualization in the terminal Serial.flush(); //flush serial buffer Serial.println(); delay(200); }
I really can't think of anything else to do. Any help is appreciated. Regards, Loïc
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
God Member
Karma: 0
Posts: 731
skcor oniudrA
|
 |
« Reply #9 on: September 02, 2007, 03:13:32 pm » |
That would be good. I need to compare the char variable that the tag is stored, against literals eg. "3300960185". It's not mission critical in my case, but the problems become a nag that I'd like to solve, and it would be nice to have a portable version. My latest discoveries:- http://www.arduino.cc/en/Tutorial/TextStringSo I'll take a look at it this evening and see what it does. Someone here also got 3 tags individually recognized, the english is broken, and I couldn't find any code. http://www.sarades.no/index.php?paged=2
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
God Member
Karma: 0
Posts: 731
skcor oniudrA
|
 |
« Reply #10 on: September 02, 2007, 05:30:37 pm » |
ok, so that solved my problem. Here's the revised code including the TextString library:- http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1185507207/30I'm reading from 8 input switches, if one is pressed, then a reading is taken from the Parallax RFID. If a tag is recognized, all 8 LED's in the 3rd array of 8 LED's flashes. Otherwise, a LED corresponding to the switch pressed, is flashed. So that's handy for when I need to demo a standalone version. Otherwise, the intent is to check valid tags against a database of tag's stored in a web based .txt file. That parts handled by processing/php so a connection is needed for it to operate (till I buy an Arduino BT).
|
|
|
|
|
Logged
|
|
|
|
|
Ghent, Belgium
Offline
Newbie
Karma: 1
Posts: 30
Arduino rocks
|
 |
« Reply #11 on: September 02, 2007, 07:02:38 pm » |
Nice!  I'll try it with my reader code first thing tomorrow. It's 2pm now (Belgium), so I better start off fresh tomorrow morning. I'll keep you updated. Thanx again for helping me out. Cheers, Loïc
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
God Member
Karma: 0
Posts: 731
skcor oniudrA
|
 |
« Reply #12 on: September 03, 2007, 03:36:31 am » |
You should be able to use comma's to separate the tags:-
TextString myTags = TextString(5500); // enough for about 500 with comma's
myTags.setArray("1010101010,1010101011,1010101012,");
Then add a comma after the tag is scanned, and use:-
if (myTags.contains("1010101010,")) { // checks if myString contains the subString "1010101010," }
The 168 should hold over a thousand unique tags, not bad considering the readers ex China off eBay store 500 and cost about the same as an Arduino, but don't do all the cool stuff Arduino's can do.
|
|
|
|
|
Logged
|
|
|
|
|
Ghent, Belgium
Offline
Newbie
Karma: 1
Posts: 30
Arduino rocks
|
 |
« Reply #13 on: September 07, 2007, 04:10:35 pm » |
Finally it works!!! This code reads the tag and compares it to a multidimensional array of known tags. If the tag matches to one in the array then an action is executed (blinking a led). Here's the code: #include <SoftwareSerial.h>
#define rxPin 7 #define txPin 2
#define TAG_LEN 12 #define ARR_LEN 2 // set up a new serial SoftwareSerial mySerial = SoftwareSerial(rxPin, txPin);
int ledPin = 13; int serIn; byte code[TAG_LEN]; // var that will hold the bytes-in read from the serialBuffer int bytes_read = 0; char target_tag[ARR_LEN][TAG_LEN] = {{0x00, 0x00, 0xdd, 0x8e, 0x96, 0x0e, 0x00, 0x01, 0x04, 0xe0, 0x10, 0xc8 }, {0x00, 0x00, 0x1b, 0x4e, 0xc1, 0x0d, 0x00, 0x01, 0x04, 0xe0, 0xd5, 0x7b}};
void setup() { // define pin modes for tx, rx, led pins: pinMode(rxPin, INPUT); pinMode(txPin, OUTPUT); pinMode(ledPin, OUTPUT); mySerial.begin(19200); // set the data rate for the SoftwareSerial port Serial.begin(19200); // opens serial port, sets data rate to 19200 bps }
void loop () { mySerial.print(0xfa, BYTE); //request Tag code if(serialAvailable()){ //keep reading from serial untill there are bytes in the serial buffer while (serialAvailable() && bytes_read < TAG_LEN){ //read Serial code[bytes_read] = Serial.read(); bytes_read++; // ready to read next digit } } //do somenthing else perhaps wait for other data. Serial.println ("NO TAG "); //print out later in the loop the sentence only if it has actually been collected; if( bytes_read >= TAG_LEN){ for(int i=0; i<bytes_read; i++){ Serial.print(code[i], HEX); //print out the byte at the specified index Serial.print(","); } for(int i = 0; i < ARR_LEN; i++) { if(memcmp(code, target_tag[i], TAG_LEN) == 0 ) { digitalWrite(ledPin, HIGH); delay(500); digitalWrite(ledPin, LOW); delay(500); } } Serial.flush(); //flush serial buffer }
Serial.println(); delay(100); bytes_read = 0; }
Now I'll start cleaning up the code and post a tutorial at the Arduino Playground. Thank you everybody for the support! Kind Regards, Loïc
|
|
|
|
« Last Edit: September 07, 2007, 04:14:23 pm by Loic »
|
Logged
|
|
|
|
|
0
Offline
God Member
Karma: 0
Posts: 731
skcor oniudrA
|
 |
« Reply #14 on: September 07, 2007, 06:51:22 pm » |
Very nice, congrats!
|
|
|
|
|
Logged
|
|
|
|
|
|