Pages: [1] 2   Go Down
Author Topic: rfid compare tag code  (Read 4200 times)
0 Members and 1 Guest are viewing this topic.
Ghent, Belgium
Offline Offline
Newbie
*
Karma: 1
Posts: 38
lovin it!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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.pde

It 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  :-[
Code:
#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 smiley-sad 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 Offline
Faraday Member
**
Karma: 8
Posts: 2526
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
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:
Code:
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.

Quote
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 Offline
Newbie
*
Karma: 1
Posts: 38
lovin it!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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  smiley-sad , but again could be my semi-noobness smiley

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 Offline
Faraday Member
**
Karma: 8
Posts: 2526
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:

Code:
#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 Offline
God Member
*****
Karma: 0
Posts: 731
skcor oniudrA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
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/PRFID

It's for a parallax, but there might be something in it you could use.
Logged

Underhill Center, Vermont, USA
Offline Offline
Jr. Member
**
Karma: 0
Posts: 71
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
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 Offline
Newbie
*
Karma: 1
Posts: 38
lovin it!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

@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
Code:
'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 Offline
God Member
*****
Karma: 0
Posts: 731
skcor oniudrA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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 Offline
Newbie
*
Karma: 1
Posts: 38
lovin it!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

@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 smiley-sad
This is it:

Code:
#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 Offline
God Member
*****
Karma: 0
Posts: 731
skcor oniudrA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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/TextString

So 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 Offline
God Member
*****
Karma: 0
Posts: 731
skcor oniudrA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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/30

I'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 Offline
Newbie
*
Karma: 1
Posts: 38
lovin it!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Nice!  smiley

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 Offline
God Member
*****
Karma: 0
Posts: 731
skcor oniudrA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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 Offline
Newbie
*
Karma: 1
Posts: 38
lovin it!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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:

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 Offline
God Member
*****
Karma: 0
Posts: 731
skcor oniudrA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Very nice, congrats!
Logged

Pages: [1] 2   Go Up
Jump to: