Odd behaviour from RFID reader

I have a parallax RFID reader hooked up to the Arduino Duemilanove. For the past hour I've been trying to set up a system where the arduino will send a valid/invalid signal via usb to a computer based on whether the tag code is in an array in the program or not. The full code follows.

/**
 * author Benjamin Eckel
 * date 10-17-2009
 *
 */
#define RFID_ENABLE 2   //to RFID ENABLE
#define CODE_LEN 10      //Max length of RFID tag
#define VALIDATE_TAG 1  //should we validate tag?
#define VALIDATE_LENGTH  200 //maximum reads b/w tag read and validate
#define ITERATION_LENGTH 2000 //time, in ms, given to the user to move hand away
#define START_BYTE 0x0A 
#define STOP_BYTE 0x0D

char tag[CODE_LEN];  

void setup() { 
  Serial.begin(2400);  
  pinMode(RFID_ENABLE,OUTPUT);   
}

void loop() { 
  enableRFID(); 
  getRFIDTag();
  if(isCodeValid()) {
    disableRFID();
    sendCode();
    delay(ITERATION_LENGTH);
  } 
  else {
    disableRFID();
    Serial.println("Got some noise");  
  }
  Serial.flush();
  clearCode();
} 

/**
 * Clears out the memory space for the tag to 0s.
 */
void clearCode() {
  for(int i=0; i<CODE_LEN; i++) {
    tag[i] = 0; 
  }
}

/**
 * Sends the tag to the computer.
 */
void sendCode() {
  int card=1;         // if card = 1 then the rfid tag being scanned is valid. If card = 0 then it is invalid.

  int i=0;            // i is the number of times the next while loop has completed.

  int card1[10];      //this is the accepted RFID tag. card1[0]-card1[9] is the individual digits of the tag.

  card1[0]=2;
  card1[1]=2;
  card1[2]=0;
  card1[3]=0;
  card1[4]=5;
  card1[5]=2;
  card1[6]=7;
  card1[7]=6;
  card1[8]=9;
  card1[9]=0;

  Serial.print("TAG:");

  while(i<CODE_LEN){               //i is less than max tag length
    Serial.print(tag[i]);          //print out stored tag next to read tag.
    Serial.print(card1[i]);

    if(tag[i]!=card1[i]){          //if the read tag is different from the stored tag then an invalid tag has been read and an error will show.
      Serial.print("ERROR:");      //print out error and show which digits don't match.
      Serial.print(tag[i]);
      Serial.print(card1[i]);
      card=0;                      //set tag as invalid
      i++;                         //increment i by 1
    } 

    else
      i++;                           //increment i by 1
  }
  Serial.print('\n');              //print new line
  if(card==0){                     //if invalid print Not Valid
    Serial.print("Not Valid");
  }
  else if(card==1){               //if valid, print Card Is Valid
    Serial.print("Card Is Valid");
  }
}

/**************************************************************/
/********************   RFID Functions  ***********************/
/**************************************************************/

void enableRFID() {
  digitalWrite(RFID_ENABLE, LOW);    
}

void disableRFID() {
  digitalWrite(RFID_ENABLE, HIGH);  
}

/**
 * Blocking function, waits for and gets the RFID tag.
 */
void getRFIDTag() {
  byte next_byte; 
  while(Serial.available() <= 0) {
  }
  if((next_byte = Serial.read()) == START_BYTE) {      
    byte bytesread = 0; 
    while(bytesread < CODE_LEN) {
      if(Serial.available() > 0) { //wait for the next byte
        if((next_byte = Serial.read()) == STOP_BYTE) break;       
        tag[bytesread++] = next_byte;                   
      }
    }                
  }    
}

/**
 * Waits for the next incoming tag to see if it matches
 * the current tag.
 */
boolean isCodeValid() {
  byte next_byte; 
  int count = 0;
  while (Serial.available() < 2) {  //there is already a STOP_BYTE in buffer
    delay(1); //probably not a very pure millisecond
    if(count++ > VALIDATE_LENGTH) return false;
  }
  Serial.read(); //throw away extra STOP_BYTE
  if ((next_byte = Serial.read()) == START_BYTE) {  
    byte bytes_read = 0; 
    while (bytes_read < CODE_LEN) {
      if (Serial.available() > 0) { //wait for the next byte      
        if ((next_byte = Serial.read()) == STOP_BYTE) break;
        if (tag[bytes_read++] != next_byte) return false;                     
      }
    }                
  }
  return true;   
}

I'm borrowing the bulk of the code from Benjamin Eckel who gave a really good tutorial on hooking up the arduino and parallax RFID reader.

I added in this part for my own particular needs:

void sendCode() {
  int card=1;         // if card = 1 then the rfid tag being scanned is valid. If card = 0 then it is invalid.

  int i=0;            // i is the number of times the next while loop has completed.

  int card1[10];      //this is the accepted RFID tag. card1[0]-card1[9] is the individual digits of the tag.

  card1[0]=2;
  card1[1]=2;
  card1[2]=0;
  card1[3]=0;
  card1[4]=5;
  card1[5]=2;
  card1[6]=7;
  card1[7]=6;
  card1[8]=9;
  card1[9]=0;

  Serial.print("TAG:");

  while(i<CODE_LEN){               //i is less than max tag length
    Serial.print(tag[i]);          //print out stored tag next to read tag.
    Serial.print(card1[i]);

    if(tag[i]!=card1[i]){          //if the read tag is different from the stored tag then an invalid tag has been read and an error will show.
      Serial.print("ERROR:");      //print out error and show which digits don't match.
      Serial.print(tag[i]);
      Serial.print(card1[i]);
      card=0;                      //set tag as invalid
      i++;                         //increment i by 1
    }

    else
      i++;                           //increment i by 1
  }
  Serial.print('\n');              //print new line
  if(card==0){                     //if invalid print Not Valid
    Serial.print("Not Valid");
  }
  else if(card==1){               //if valid, print Card Is Valid
    Serial.print("Card Is Valid");
  }
}

My problem is that whenever I test a valid tag, it always comes back invalid for every single digit regardless of whether it is actually equal to the stored tag or not. I finally ended up narrowing down the error to the first if statement (I think) but I haven't been able to determine what is actually messing it up. This is probably due to the fact that I haven't done any serious coding since I took my first programming class about six months ago. Can someone look through the code and try to help me out? Thanks!

I had a similar problem, turned out that there was some 'invisible' characters in the id when the arduino got it from the reader, I fixed that by using this where i check the bytes for each character, and filter away the 'invisible' ones.

int DOOR_LOCKED = 180; // 0-180
int DOOR_UNLOCKED = 0; // 0-180
long interval = 1000; //How long the doorwill stay unlocked

boolean locked = true;

#include <SoftwareServo.h>
SoftwareServo myservo;  // create servo object to control a servo

#include <WString.h>
#include <NewSoftSerial.h>

NewSoftSerial RFID(2, 3);
String msg = String(60);
String ID = String(60);  //string to store allowed cards

long previousMillis = 0; //Store when the door got unlocked
long previousServo = 0; //Store when servo was last set
String temp = "";

boolean debug = true;

void setup()  
{
  ID.append("3A008602358B");
  
  myservo.attach(4);  // attaches the servo on pin 4 to the servo object
  
  Serial.begin(9600);
  Serial.println("Serial Ready");

  RFID.begin(9600);
  Serial.println("RFID Ready");
  
  Serial.print("Allowed ID: ");
  Serial.println(ID);  
  
  myservo.write(DOOR_LOCKED); //Move the servo to the locked position
}

char c;

void loop()
{
  if (!locked)
  {
    if(millis() - previousMillis > interval) //Lock after being unlocked the amount of time defined by interval
    {
      locked = true; //Change it back to locked
      myservo.write(DOOR_LOCKED); //Move the servo to the locked position
    }
  }
  
  while(RFID.available() > 0)
  {
    c=RFID.read();
    msg.append(c);
  }
  
  if(msg.length() >= 12) //Check if it is a valid ID
  {
    int length = msg.length();
    for (int i=0; i <= length; i++) //Run through the string
    {
      if (byte(msg.charAt(i)) >= 32) //Check if the char is more, or 32 byte
      {
        temp.append(msg.charAt(i)); //Add it to the temp message holding the ID
        if (debug) Serial.println(temp);
      }
    }
    verifica(); //Validate the ID
  }
  
  msg=""; //Empty the message
  temp = ""; //Empty the string holding the ID temp
  
  if(millis() - previousServo > 50) //Check if it is time to set the servo position again
  {
    previousServo = millis();
    SoftwareServo::refresh();
  }
}

void verifica()
{
  if (debug) Serial.println(temp);  //Uncomment to view your tag ID
  
  if(ID.contains(temp))
  {
    Serial.println("> Access granted.");
    myservo.write(DOOR_UNLOCKED); //Move the servo to the unlocked position
    locked = false;
    previousMillis = millis();
  }
  else
  {
    Serial.println("> Access denied.");
    myservo.write(DOOR_LOCKED); //Move the servo to the locked position, just to be sure
  }
}

It is not 100% the same as what you got, but you might be able to take something from it and use it for your own :slight_smile:

Thanks, your suggestion about the numbers that weren't showing up really helped me out. I used a different method to verify the RFID code and changed the int to a float. Pretty sure there was an issue with trying to verify a char against an int so I switched both. I was only using float to make absolutely sure that I wasn't getting decimels. It seems to work so I'm not going to touch the code. Probably will later just to streamline everything.

I'll leave the new code here on the off chance it helps out someone with a similar problem.

/**
 * Sends the tag to the computer.
 */
void sendCode() {
  int valid = 1;          //if valid == 1 then scanned RFID code is valid, 0 is invalid.
  float cardA[] = {50.00,50.00,48.00,48.00,53.00,50.00,55.00,54.00,57.00,48.00};  //stored RFID code.
  Serial.print("TAG:");  
  //Serial.println(tag);
  for(int i=0; i<CODE_LEN; i++) {        //replaced while loop with for
    Serial.print(tag[i]);
    Serial.print("-");
    if(cardA[i]==tag[i]){
      Serial.print("Valid");
    }else {
      Serial.print("Invalid");
      valid = 0;
    }
  } 
  Serial.print('\n');
  if(valid!=1){
    Serial.print("invalid");
    Serial.print('\n');
  } else {
    Serial.print("valid");
  }
}

The above raises a nice example of why "bottom up development" is so important.

If working on something like this, I would have, early in the day, have had a stage where my Arduino was showing me, in detail, what it had read from the Parallax reader. Then I wouldn't have been struggling to overcome the "extra" characters.

In the final version of the program the printing out of what the tag said could be remmed out... but early in the building of that program, it would have been there.

Often we see questions saying "everything's wired up correctly, but..." How do you know? If, say, a button is involved, there ought to be a ReadButton function, and during the bottom up development, there ought to be a point where you just call the ReadButton function and turn an LED on or off. THEN you know the button is wired up, and can go on to the next thing.

Quite so. I should have changed the program at the very beginning to do as you had described but I didn't because I both didn't think of it and I thought it would be a quick little edit to the code. That quick little edit ended up taking more time than it should have.

You should not use float to store the rfid codes, because of floating point format truncates some values and i wont work.

stere them as integers o byte values