Please help with RFID program

Good morning everyone.
I just finally got an Arduino when SparkFun had their Free Day. ;D

Well, I had an RS232 RFID reader from Parallax and a 4x20 Blue/White LCD with a serial backpack laying around and decided to try something that I haven't tried in a while. I thought I would put them all together and see if I could get them to work together like good little children. :-/

Well, I got them to play nice but I still have a problem. The rfid reader reads the tags and sends the numbers to the arduino. The arduino checks the tags to see if it matches the one stored. If it matches, it lights up an led to simulate a door lock and tells you it's a good tag on the screen then resets. If it doesn't match, it tells you so on the screen then resets.

What I need help with is being able to have more than one tag number stored and be able to search through them all to see if the scanned tag matches any of the stored numbers. When I was using my PicAxe, I had no problem with that. I just don't know how to do it on the Arduino.

If anyone can help, I would be SOOooooooooo grateful.
I have included my code below. Any ideas on cleaning it up would be great too. :wink:

Thanx in advance.
Dan

// rfid_security.pde
// By Daniel Wright
// 2010.JAN 22
// daniel@thewrightproject.com
// www.thewrightproject.com

// This is a simple security system using the following hardware:
// Arduino Duemilanove + Parallax RS232 RFID Reader + 4x20 LCD with Serial Backpack

// The system waits for an RFID tag to be scanned and then verifies if it is valid. If it is valid, it displays
// a message on the screen indicating that it is valid and opens a door lock(red led for now).
// If it is invalid it says so on the screen and resets.

// The firmware currently only has one rfid tag coded into it as I don't yet know how to create a database
// and be able to check multiple tag numbers for a good one. That's coming as soon as I figure it out.

#include <SoftwareSerial.h>

#define TAG_LEN 12

char tag[12] = {'0', 'F', '0', '3', '0', '2', '8', '4', '8', '8'};


int  val = 0; 
char code[12]; 
int bytesread = 0; 

#define rxPin 8  // RFID reader SOUT pin connected to Serial RX pin 8
#define txPin 9  //Not used but needs declaring
#define rxPinl 4  //Not used but needs declaring
#define txPinl 14  //Output on Analog 0 to LCD

void setup()
{ 
  delay(3000);                // pause to allow LCD to start up
  pinMode(2,OUTPUT);       // Set digital pin 2 as OUTPUT to connect it to the RFID /ENABLE pin 
  digitalWrite(2, HIGH);    // De-Activate the RFID reader 
  pinMode(7,OUTPUT);       // Set digital pin 7 as OUTPUT to connect to Door Striker
  digitalWrite(7, LOW);    // De-Activate the Door Striker 
  pinMode(txPinl, OUTPUT);  //Set Analog pin 0 as output to LCD

}


void loop()
{ 
// SoftwareSerial setup for LCD
  SoftwareSerial mySerial = SoftwareSerial(rxPinl, txPinl);
  mySerial.begin(2400);  // Software serial for LCD 2400bps
   mySerial.print("?G420");   // set display geometry,  4 x 20 characters in this case
   delay(500);                // pause to allow LCD EEPROM to program

   mySerial.print("?Bff");    // set backlight to ff hex, maximum brightness
   delay(1000);                // pause to allow LCD EEPROM to program

   mySerial.print("?s6");     // set tabs to six spaces
   delay(1000);               // pause to allow LCD EEPROM to program

   mySerial.print("?f");                   // clear the LCD
   delay(10);                                              
   digitalWrite(2, LOW);    // Activate the RFID reader 
   mySerial.print("?x00?y1");              // move cursor to beginning of line 1
   mySerial.print("RFID Security");
   delay(500);
   mySerial.print("?x00?y3");              // move cursor to beginning of line 3
   mySerial.print("Please Scan Tag....");
   
// SoftwareSerial setup for RFID reader
  SoftwareSerial RFID = SoftwareSerial(rxPin,txPin); 
  RFID.begin(2400);
  
// Main program functions start here
  if((val = RFID.read()) == 10)
  {   // check for header 
    bytesread = 0; 
    while(bytesread<10)
    {  // read 10 digit code 
      val = RFID.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(strcmp(code, tag) == 0) {
   // if 10 digit read is complete 
   digitalWrite(2, HIGH);    // De-Activate the RFID reader 
   mySerial.print("?f");                   // clear the LCD
   delay(10);                                              
   mySerial.print("?x00?y1");              // move cursor to beginning of line 1
   mySerial.print("RFID Tag Valid");
   mySerial.print("?x00?y2");              // move cursor to beginning of line 2
   mySerial.print("Tag #: ");
   mySerial.print(code);     // print the TAG code 
  digitalWrite(7, HIGH);    // De-Activate the RFID reader 
    delay(3000);                       // wait for a couple seconds
  digitalWrite(7, LOW);    // De-Activate the RFID reader 
   }
     else {
   digitalWrite(2, HIGH);    // De-Activate the RFID reader 
   mySerial.print("?f");                   // clear the LCD
   delay(10);                                              
   mySerial.print("?x00?y1");              // move cursor to beginning of line 1
   mySerial.print("RFID Tag Invalid!");
   delay(3000);
   }
    bytesread = 0; 
   mySerial.print("?f");                   // clear the LCD
   delay(500);                                              
   mySerial.print("?x00?y2");              // move cursor to beginning of line 2
   mySerial.print("Please Wait....");
    
  } 
}

:sunglasses:

There has to be a better way to store the tag values. Can you store the full tag as a string in an array rather then each individual character. So see if you can set the array up to have multiple tags listed and have it compared to the RFID reading. I don't now how the reader works and stores the code. So i'm not sure how you'll get it stored for the comparison. But if it reads one character of the code at a time you'll need some code that combines the readings into a string for the comparison.

int tags[] = {'0F03028488', '0F03028489', .... ect};

But i don't think thats possible. You may have to have a separate string per tag ID. So you'll have something like this.

char tag1[12] = {'0', 'F', '0', '3', '0', '2', '8', '4', '8', '8'};
char tag2[12] = {'0', 'F', '0', '3', '0', '2', '8', '4', '9', '9'};

Then you need to compare them.

you want to store the tags one of the memories.

If the tags are fixed, you know all of them in advance, and they don't change, then you can just store them in the Flash.

If you need to 'learn' them, or they change, then you store them in the eeprom.

If you only have a relatively small number of them, storing them the way you do (character arrays) is okay. If you have a lot of them, you would want to store them as bits. For example:

unsigned int[3] = { 0x0f, 0x0302U, 0x8488U }

Although they don't mention it, arrays can be multidimensional, so you can say:
unsigned int a[3][2] = {0x0f, 0x3442, 0xa23f, 0x13, 0x4c45, 0xe344};

Then you can use nested for loops to cycle through the tags (second index) and the "words" (first index) to do your comparisons instead of the strcmp. When you read the bytes, you need to assemble the bits. the way to do that is probably an "if" for 9 or less, subtracts ascii '0' if 9 or less and subtracts ascii 'f' + 10 if a or greater. You then shift left by 4 bits and add.

if val <= '0') code = code <<4 + (val - 48); //48 is ascii '0'
else code = code*<<4 + (val - 47); //47 is ascii '9' (57) plus 10*
You have to remember to initialize code*. You can use i = bytesread % 3, although modulo isn't particularly efficient.*
To store the tags in flash, see:
*http://arduino.cc/en/Reference/PROGMEM*_
To store the tags in eeprom, see:
*http://arduino.cc/en/Reference/EEPROM*_

*In your program, the most glaring error is that you have the lcd and rfid initialization code in loop() instead of setup(). The code that has the .begin and geometry, backlight and tabs, etc., belongs in setup(). The code that does RFID.begin belongs in setup(). *
It would be easier to read if you used the braces around the if(bytesread == 10)

brtech,

In your program, the most glaring error is that you have the lcd and rfid initialization code in loop() instead of setup(). The code that has the .begin and geometry, backlight and tabs, etc., belongs in setup(). The code that does RFID.begin belongs in setup().

If I put that part in the setup section, I start getting errors like this one:

In function 'void loop()';
error: 'RFID' was not declared in this scope

If I move the rfid stuff back to the loop the error goes away.

Put the constructor (SoftwareSerial RFID = SoftwareSerial(rxPin,txPin) in the outer global variable area (before void setup()). Do the same with the LCD constructor.

Move...

  SoftwareSerial RFID = SoftwareSerial(rxPin,txPin);

... to just before....

void setup()

... and you'll be able to put things like...

RFID.begin(2400);

... in setup, where they ought to be.

And do the same with....

SoftwareSerial mySerial = SoftwareSerial(rxPinl, txPinl);

... so the mySerial stuff can be in the right places. Some mySerial... and RFID... stuff will remain in loop(), of course.

===
Above notes done at a desk with no Arduino... apologies if not EXACTLY right... someone else jump in and tweak if needed, please?

brtech,
Thanx for the tip. Works good now.
Have any idea on how to create functions for if you have a good tag or a bad tag instead of having it right in the main loop? I tried but my code won't compile. I keep getting an error when it hits the first call to GoodTag().

In function 'void loop()':
error: 'GoodTag' was not declared in this scope

Thanx again. All help is appreciated.

// rfid_security.pde
// By Daniel Wright
// 2010.JAN 22
// daniel@thewrightproject.com
// www.thewrightproject.com

// This is a simple security system using the following hardware:
// Arduino Duemilanove + Parallax RS232 RFID Reader + 4x20 LCD with Serial Backpack

// The system waits for an RFID tag to be scanned and then verifies if it is valid. If it is valid, it displays
// a message on the screen indicating that it is valid and opens a door lock(red led for now).
// If it is invalid it says so on the screen and resets.

// The firmware currently only has one rfid tag coded into it as I don't yet know how to create a database
// and be able to check multiple tag numbers for a good one. That's coming as soon as I figure it out.

#include <SoftwareSerial.h>

#define TAG_LEN 12

char tag1[12] = {'0', 'F', '0', '3', '0', '2', '8', '4', '8', '8'};
char tag2[12] = {'0', 'F', '0', '3', '0', '2', '8', '4', '9', '9'}; 



int  val = 0; 
char code[12]; 
int bytesread = 0; 

#define rxPin 8  // RFID reader SOUT pin connected to Serial RX pin 8
#define txPin 9  //Not used but needs declaring
#define rxPinl 4  //Not used but needs declaring
#define txPinl 14  //Output on Analog 0 to LCD

  SoftwareSerial mySerial = SoftwareSerial(rxPinl, txPinl);
  SoftwareSerial RFID = SoftwareSerial(rxPin,txPin); 

void setup()
{ 
  delay(3000);                // pause to allow LCD to start up
  pinMode(2,OUTPUT);       // Set digital pin 2 as OUTPUT to connect it to the RFID /ENABLE pin 
  digitalWrite(2, HIGH);    // De-Activate the RFID reader 
  pinMode(7,OUTPUT);       // Set digital pin 7 as OUTPUT to connect to Door Striker
  digitalWrite(7, LOW);    // De-Activate the Door Striker 
  pinMode(txPinl, OUTPUT);  //Set Analog pin 0 as output to LCD

// SoftwareSerial setup for LCD
  mySerial.begin(2400);  // Software serial for LCD 2400bps
   mySerial.print("?G420");   // set display geometry,  4 x 20 characters in this case
   delay(500);                // pause to allow LCD EEPROM to program

   mySerial.print("?Bff");    // set backlight to ff hex, maximum brightness
   delay(1000);                // pause to allow LCD EEPROM to program

   mySerial.print("?s6");     // set tabs to six spaces
   delay(1000);               // pause to allow LCD EEPROM to program

// SoftwareSerial setup for RFID reader
  RFID.begin(2400);    

}

void loop()
{ 
  // Main program functions start here. 
   mySerial.print("?f");                   // clear the LCD
   delay(10);                                              
   digitalWrite(2, LOW);    // Activate the RFID reader 
   mySerial.print("?x00?y1");              // move cursor to beginning of line 1
   mySerial.print("RFID Security");
   delay(500);
   mySerial.print("?x00?y3");              // move cursor to beginning of line 3
   mySerial.print("Please Scan Tag....");
  

//Program reads tag from RFID Reader.
  if((val = RFID.read()) == 10)
  {                                   // check for header 
    bytesread = 0; 
    while(bytesread<10)
    {                                  // read 10 digit code 
      val = RFID.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(strcmp(code, tag1) == 0)
    {
    GoodTag(); //if tag matches, Do GoodTag Function
    }
     else
    {
    BadTag; //If tag doesn't match, Do BadTag Function
    }
    }
    {
    if(strcmp(code, tag2) == 0)
    {
    GoodTag; //if tag matches, Do GoodTag Function
    }
     else
    {
    BadTag; //If tag doesn't match, Do BadTag Function
    }
    }
   }
  }
  void GoodTag()
   {
   // if 10 digit read is complete 
   digitalWrite(2, HIGH);    // De-Activate the RFID reader 
   mySerial.print("?f");                   // clear the LCD
   delay(10);                                              
   mySerial.print("?x00?y1");              // move cursor to beginning of line 1
   mySerial.print("RFID Tag Valid");
   mySerial.print("?x00?y2");              // move cursor to beginning of line 2
   mySerial.print("Tag #: ");
   mySerial.print(code);     // print the TAG code 
  digitalWrite(7, HIGH);    // Activate Door Lock 
    delay(3000);                       // wait for a couple seconds
  digitalWrite(7, LOW);    // De-Activate Door Lock 
  bytesread = 0; 
   mySerial.print("?f");                   // clear the LCD
   delay(500);                                              
   mySerial.print("?x00?y2");              // move cursor to beginning of line 2
   mySerial.print("Please Wait....");
   return;
   };
   void BadTag()
    {
   digitalWrite(2, HIGH);    // De-Activate the RFID reader 
   mySerial.print("?f");                   // clear the LCD
   delay(10);                                              
   mySerial.print("?x00?y1");              // move cursor to beginning of line 1
   mySerial.print("RFID Tag Invalid!");
   delay(3000);
   bytesread = 0; 
   mySerial.print("?f");                   // clear the LCD
   delay(500);                                              
   mySerial.print("?x00?y2");              // move cursor to beginning of line 2
   mySerial.print("Please Wait....");
   return;
  };
}

What's wrong with:
long long tags[] = {0x0F03028488, 0x0F03028489, .... etc};  ?

What's wrong with:
Code:

long long tags[] = {0x0F03028488, 0x0F03028489, .... etc};

?

I don't know. I am new to the Arduino. I don't even know how I would use that in my program. I assume that would take the place of the two lines that I have to specify the tag numbers, but how would I compare that with the code that is read?
:-?

Move the definitions of GoodTag and BadTag above the loop definitions.

I personally don't know how to use something defined as
long long tags[], but I gave you the basic idea of how you use bits instead of strings. I used tags[3][n] for a two dimensional array. It's a bit inefficient to use double indexed arrays, because the compiler usually needs to use multiply. Standard space/time tradeoff.

The idea I gave you was to convert strings of hex characters into hex nibbles, and shift/add them to create words (unsigned ints).

comparing is easy, you just compare the integers directly (although you need a loop if you do it with two dimensional arrays like I suggested).

I personally don't know how to use something defined as
long long tags[]

You may not, but the compiler does.
"long long"s are 64 bit integers, so a maximum of 16 hex digits.
The tags shown are 10 hex digits in length, so too long (no pun intended) to store in a "long" (32 bit) integer, which can only hold eight hex digits..

I thank you all for your ideas and I actually have the code working good now using functions for the goodtag and badtag. I am just using the if else statements to verify the tags. It is not the most ideal, but it is reliable and works good.

I am not ready to delve into converting things to hex and all that jazz right now as I've only been working with the Arduino for less than a week now. I do appreciate the advise though and might look into that stuff in the future.

Thanx again to all.

Now .... on to something challenging ..... :wink: ;D