RedBee RFID reader problems

I’ve been trying to connect my RedBee RFID reader to my Arduino for quite some time now and have been tearing my hair out trying to get them to play nice together. I could really use some help on this one.

I have an XBee module on my RedBee RFID reader, and the jumpers set to send all serial data over Xbee. Then, on my Arduino I have an XBee Shield, again with the module connected and all jumpers set to send/receive serial data via XBee.

What I want to do is control an RGB lamp (that I’ve already built) based on the RFID tag passed over my RFID reader. So I actually saved all the tags I own locally on my RFID reader so I get a consistent packet structure into my Arduino.

My major problems are:

  1. Because I’m using XBee for communication, I cannot send serial data to my PC for debugging, so I’m totally blind when testing the system, save from changing the state of my LED on pin 13.
  2. I’m really confused about when to use int, char and String.

Here is my code so far:

const int NUM_TAGS = 8;

int incomingByte = 0;
boolean valid;
String tag;
String tags[NUM_TAGS]   = {"1080949666", "228015620207", "108020618361", "228015621675", "108015819165", "2280288799", "108020624739", "24804625544"};
int colors[NUM_TAGS][3] = {{100,0,0}, {0,100,0}, {0,0,100}, {100,0,100}, {100,100,0}, {0,100,100}, {50,80,15}, {60,10,80}};

void setup() {
  Serial.begin(9600);
  pinMode(13,OUTPUT);
}

void loop() {
  
  if(Serial.available() > 0) {
   
    // Valid tag packet will follow this structure:
    // T:ACK XXX XXX XXX XXX XXX\r\n>
    incomingByte = Serial.read();
    if( incomingByte == 'T' ) {
      Serial.read();  // ':'
    
      // Read the header
      incomingByte = Serial.read();
      if( incomingByte == 'N' ) {
        for(int i=0; i<4; i++)
          Serial.read();  // 'ACK '
      } else {
        for(int i=0; i<3; i++)
          Serial.read();  // 'CK '
      }
      
      // Read the tag itself
      incomingByte = Serial.read();
      tag = "";
      while( (incomingByte != 13) ) {
        if( incomingByte == 32 )  continue;
        tag += incomingByte;
        incomingByte = Serial.read();
      }      
      
      Serial.read();  // '\n'
      Serial.read();  // '>'
     
    }
      
  } else {
    //fadeTo(red);
  }
  
        
  // Look up the tag
  int index = -1;
  for(int i=0; i<NUM_TAGS; i++) {
    if( tag.equals(tag[i]) ) {
      index = i;
      break;
    }
  }
  
  if(index>-1)  analogWrite(13,255);
}

Result: The LED on pin 13 never turns on.

I’ve been working on this problem for a few weeks, so any help is really appreciated!

With 41 posts, you can probably anticipate the questions that will be asked. The first one is "Can you post a link to the RFID device?"

Initializers for an array do not all have to go on the same line. With vertical and horizontal scroll bar in the code window, and vertical and horizontal scroll bars for the browser window, it's hard to see all of your code. Make it easy by putting carriage returns after every other value, so the horizontal scroll bar goes away, please.

      if( incomingByte == 'N' ) {

Where did N come from? There is no N in the sample packet shown.

  if(Serial.available() > 0) {

This tests that there is at least one byte available to read. You then proceed to read way more than the one that you confirmed was there, without ever checking for more.

        if( incomingByte == 32 )  continue;

The continue statement is rarely used. Every time I see it, I have to look up what it does. Since you appear to be simply trying to avoid storing the space in the array, turn this statement around:

if(incomingByte != ' ')
   tag += incomingByte;

As the code is now, once the space is found, the code loops in that while loop, never doing anything else, unless I missed something.

You are making, throughout the code, the assumption that serial data is never lost. That is not a valid assumption.

You would be better off reading all the data, and then parsing the data that you read.

Here is a link to the RFID reader I'm talking about: http://www.roboticsconnection.com/p-99-redbee-rfid-reader.aspx

I didn't put the array initializers on multiple lines because its relatively useless information to read, so I didn't want to add a bunch of vertical length to my sketch unnecessarily.

Sorry, the line that refers to the letter N is because the invalid tag packet is the same as the valid tag packet, only with "NACK" instead of "ACK", like this:

Valid = T:ACK XXX XXX XXX XXX XXX\r\n>
Invalid = T:NACK XXX XXX XXX XXX XXX\r\n>

The while continues until the LF character is read ( \r = 13 ). Therefore that while loop should capture all characters, skipping spaces, until a LF code is reaches which begins the end of the packet.

Once the while loop is finished, the code should continue to the last part of the loop() method where I compare my captured tag with my array of known tags, saving the index of the tag if it is found.

Should I change the Serial.available() line to cause the program to wait for something like 10 bits or so? Packets from this reader have different lengths and can be as little as 5 or 6 bits sometimes ("sometimes just a ACK or NACK is sent).

Should I change the Serial.available() line to cause the program to wait for something like 10 bits or so? Packets from this reader have different lengths and can be as little as 5 or 6 bits sometimes ("sometimes just a ACK or NACK is sent).

You could do something like this:

char c = ' ';
while(Serial.available() > 0 && c != '\r' && c != '\n')
{
   c = Serial.read();
   // Do something with c (Add it to an array to be parsed later)
}

// When you get here, either there is no
// more data to read or the end of a packet
// was received. The value in c will tell you
// which is true.