Parallax RFID Read/Write Project Serial.print issues

Hello Everyone.

I’m new to this sort of thing, but I’ve taken on a fairly large RFID project (by my standards anyway). I won’t bore you with the details, save for the pertinent ones. :stuck_out_tongue:

What I’m trying to do is this:

  • RFID read/write module is in an idle state.
  • A read command is received from Serial (in this case ‘r’)
  • The RFID card becomes active, searches for a tag for a yet undetermined length of time (using a ‘for loop’).
  • If that time passes, it idles and waits for the ‘r’ command again.
  • If it detects a tag, it attempts to read that tag’s static ID. If the read is successful, it breaks the ‘for loop’ and returns to an idle state to await the next ‘r’ command.
  • After a successful read, the four byte static ID is combined into a String, and then is written to Serial (via println)

What really happens:

  • RFID card is in an idle state
  • The read command is received and the card begins searching for a tag. The tag is successfully read and printed to Serial.
    HOWEVER
  • the first attempt at reading the tag does not always appear to be successful. However, when the ‘r’ command is sent again, that tags ID is immediately written, whether or not the tag is actually present.
  • sometimes the wrong information is printed after the first tag read attempt, but again, as soon as ‘r’ is sent again, the correct ID is immediately written.
  • once that first tag has been read, it will continue to print that tags ID as soon as the ‘r’ command is sent.
  • it takes at least three attempts at sending the ‘r’ command with a different tag constantly in the vicinity of the reader before it will recognize the new tag. It seems that the ‘for loop’ is no longer working at this point. And again, the new tag’s ID will be immediately written with every new ‘r’ command.

At this point I’m not sure what I need to do next, so here I am. :slight_smile:

#include <SoftwareSerial.h>
#define RFID_READ 0x01
#define txPin 6
#define rxPin 7

SoftwareSerial RFIDSerial(rxPin, txPin);
int id1;                                          //integer for ID byte 1
int id2;                                          //integer for ID byte 2
int id3;                                          //integer for ID byte 3
int id4;                                          //integer for ID byte 4
int err;                                          //integer for Error Status byte
int led = 13;                                     //PICNDUINO Onboard LED
int led2 = 9;                                     //PICNDUINO Onboard LED
int command;                                      //integer for command received from C#

void setup()
{
  Serial.begin(9600);
  RFIDSerial.begin(9600);
  pinMode(txPin, OUTPUT);    
  pinMode(rxPin, INPUT); 
  pinMode(led, OUTPUT);
  pinMode(led2, OUTPUT);  
}

void idSend()                                      //Combines individual bytes into a string and sends it to serial monitor
{
  String ID1 = String(id1,HEX);
  String ID2 = String(id2,HEX);
  String ID3 = String(id3,HEX);
  String ID4 = String(id4,HEX);
  String cardid = String(ID1 + ID2 + ID3 + ID4);
  Serial.println(cardid);
}

void readTagID()                                   //Reads built in tag ID         
{      
  for(int long i = 0; i < 500; i++)                //For loop to search for tag
  {
    digitalWrite(led, HIGH);                         //visual search cue turned on
    RFIDSerial.print("!RW");                       
    RFIDSerial.write(byte(RFID_READ));
    RFIDSerial.write(byte(32));
    if(RFIDSerial.available() > 0)
    {      
      err = RFIDSerial.read();                        //The mySerial.read() procedure is called, but the result is not printed because I don't want the "error message: 1" cluttering up the serial monitor
      if (err == 1)                                   //If the error code is anything other than 1, then the RFID tag was not read correctly and any data collected is meaningless. In this case since we don't care about the resultant values they can be suppressed
      {
        if(RFIDSerial.available() > 0)                    //wait for next byte  
        {   
          id1 = RFIDSerial.read();
        }
        if(RFIDSerial.available() > 0)                    //wait for next byte
        {
          id2 = RFIDSerial.read();
        }
        if(RFIDSerial.available() > 0)                    //wait for next byte
        {
          id3 = RFIDSerial.read();
        }
        if(RFIDSerial.available() > 0)                    //wait for next byte
        {
          id4 = RFIDSerial.read();
        }
        digitalWrite(led, LOW);
        break; 
      }
    }
    digitalWrite(led, LOW);                           //visual search cue turned on
  }
}

void loop()
{
  if(Serial.available() > 0)
  {
    command = Serial.read();
    if(command = 72, HEX)                             //receive command from serial to search for and read card
    {
      readTagID();
      idSend(); 
    }
  }
  delay(750);
}

Thanks in advance.

if ( command == 'r' )		//receive command from serial to search for and read card

Good eye! Although adding that missing = doesn't seem to have much effect on the program. Now it will attempt to read the tag (output the wrong value or 0000), and then it will write the correct value the next time 'r' is sent through Serial. I cannot read a second card at all at this point without hitting the hardware reset button first.

Any documentation on what the RFID tag returns to the buffer?

I’m not sure what you are asking. Are you looking for the commands and error codes document, which can be found at the bottom right corner of this page in a pdf doc:
http://www.parallax.com/StoreSearchResults/tabid/768/txtSearch/rfid/List/0/SortField/4/ProductID/688/Default.aspx

Or asking me to find out what is actually entering the buffer when I attempt to scan the card?

No, you got it the first time.

Thanks.

I decided to start over to see if I could locate where I went wrong. I started using the code from:
http://playground.arduino.cc/Learning/ParallaxRFIDreadwritemodule (2nd code).

The above code works as advertised. Then, leaving everything else alone, I tried to add the ability for the RFID card to remain idle until the ‘r’ command is received. Now the problems start already.

Assuming the tag is already in range (as it should only run through the code once, since there is no looping function yet), the first attempt to send the ‘r’ command returns nothing in the Serial monitor.

The second time I send the ‘r’ command, the proper output is displayed in the Serial monitor, with or without a tag present. The third time (no tag) displays nothing, the fourth time as well. The fifth time (different tag) displays nothing, and the sixth time will display the second tag’s information. Basically it will display whatever was read previously on the second attempt, which leads me to think my print functions need to be somewhere else in the code, although I’m not sure exactly where. For reference, here is the code I’m currently dealing with:

#include <SoftwareSerial.h>
#define RFID_READ 0x01
#define txPin 6
#define rxPin 7

SoftwareSerial mySerial(rxPin, txPin);
int val;
int runs = 0;

void setup()
{
  Serial.begin(9600);
  Serial.println("RFID Read/Write Test");
  mySerial.begin(9600);
  pinMode(txPin, OUTPUT);    
  pinMode(rxPin, INPUT);      
}

void suppressAll()                                //suppresses the "null result" from being printed if no RFID tag is present
{
  if(mySerial.available() > 0)
  { 
    mySerial.read();
    suppressAll();
  }
}

void loop()
{
  if(Serial.available() > 0)
  {
    int command = Serial.read();
    if(command == 'r')
    {
      int val;
      mySerial.print("!RW");
      mySerial.write(byte(RFID_READ));
      mySerial.write(byte(32));

      if(mySerial.available() > 0)
      {      
        val = mySerial.read();                        //The mySerial.read() procedure is called, but the result is not printed because I don't want the "error message: 1" cluttering up the serial monitor
        if (val != 1)                                   //If the error code is anything other than 1, then the RFID tag was not read correctly and any data collected is meaningless. In this case since we don't care about the resultant values they can be suppressed
        {
          suppressAll();
        }                              
      }      


      if(mySerial.available() > 0) {      
        val = mySerial.read();
        Serial.print("1st:");
        Serial.println(val, HEX);
      }

      if(mySerial.available() > 0) {        
        val = mySerial.read();
        Serial.print("2nd:");
        Serial.println(val, HEX);
      }

      if(mySerial.available() > 0) {      
        val = mySerial.read();
        Serial.print("3rd:");
        Serial.println(val, HEX);
      }

      if(mySerial.available() > 0) {          
        val = mySerial.read();
        Serial.print("4th:");
        Serial.println(val, HEX);
        Serial.println("-----------------");
      }  

      delay(750);
    }
  }
}

I admit to being to lazy to attempt debugging your code. Mainly because I don’t have the hardware needed.

But I’m not to lazy to make an attempt of my own for you to try. If it doesn’t work sorry for wasting your time.

// <http://forum.arduino.cc/index.php?topic=166216.new#new>

#include <SoftwareSerial.h>

#define A_SIZEOF(ARRAY)     (sizeof(ARRAY) / sizeof(ARRAY[0]))

const uint8_t   pinVISUAL_CUE_LED   = 13;   // PICNDUINO Onboard LED
const uint8_t   pinLED_2            = 9;    // PICNDUINO Onboard LED

const uint8_t   pinTX               = 6;
const uint8_t   pinRX               = 7;

const uint8_t   LED_OFF             = LOW;
const uint8_t   LED_ON              = HIGH;

const uint8_t   RFID_READ           = 0x01;

SoftwareSerial serialRFID(pinRX, pinTX);

uint8_t buffID[sizeof(long)];

void idSend()
{
    for ( int i = 0; i < A_SIZEOF(buffID); i++ )
    {
        Serial.print(buffID[i], HEX);
    };

    Serial.print("\n");
}


// Reads built in tag ID

void readTagID()
{
    digitalWrite(pinVISUAL_CUE_LED, LED_ON);

        int     err;
        do
        {
            // flush software serial buffer

            while ( serialRFID.available() > 0 )
            {
                (void)serialRFID.read();
            }
            

            serialRFID.print("!RW");
            serialRFID.write(byte(RFID_READ));
            serialRFID.write(byte(32));


            // wait for data to become available

            while ( serialRFID.available() < 1 )
            {   }

            err = serialRFID.read();
        } while ( err != 1 );


        // wait for all 4 bytes of data to become available

        while ( serialRFID.available() < 4 )
        {   }

        int count = 0;
        do
        {
            buffID[count++] = serialRFID.read();
        } while ( count < sizeof(long) );

    digitalWrite(pinVISUAL_CUE_LED, LED_OFF);
}

void loop()
{
    if ( Serial.available() > 0 )
    {
        int command = Serial.read();
        switch ( command )
        {
            // receive command from serial to search for and read card
            case 'r':
                readTagID();
                idSend();
                
                break;
            
            default:
                break;
        }
    }

    delay(750);
}

void setup()
{
    Serial.begin(9600);


    // ... software serial I/O pins ...

    pinMode(pinTX, OUTPUT);
    pinMode(pinRX, INPUT);
    serialRFID.begin(9600);


    // ... on-board LED pins ...

    pinMode(pinVISUAL_CUE_LED, OUTPUT);
    pinMode(pinLED_2, OUTPUT);
}

EDIT: Made slight change waiting for input from ‘serialRFID’ of at least 1 character.

No such thing as time wasted. Thanks for your help, I will give it a try tomorrow and let you know.

Well isn’t that something. It seems to work 9/10 times. Every once and awhile it will print 0000, but I put some error handling in my Visual Studio part of this project to catch that. Going through your code, I have some questions:

What exactly is this doing?

#define A_SIZEOF(ARRAY)     (sizeof(ARRAY) / sizeof(ARRAY[0]))

Is there a specific reason you use uint8_t instead of int? (I had to look it up to see what it was :slight_smile: )
Edit: Is it because of the sizeof(long) that you should define the integers as 8 bits?

How does this work? There is nothing in the curly braces?

            while ( serialRFID.available() < 1 )
            {   }

For this code, could I use other commands, such as ‘w’ and then put my write functions under that case?

        switch ( command )
        {
            // receive command from serial to search for and read card
            case 'r':
                readTagID();
                idSend();
                
                break;
            
            default:
                break;

Thank you again for all your help. Sorry about all the questions, but I’m trying to make sure I actually understand how it works for when I make changes.

MobiusRx7:
Well isn’t that something. It seems to work 9/10 times. Every once and awhile it will print 0000, but I put some error handling in my Visual Studio part of this project to catch that. Going through your code, I have some questions:

What exactly is this doing?

#define A_SIZEOF(ARRAY)     (sizeof(ARRAY) / sizeof(ARRAY[0]))

The compile time operator ‘sizeof’ returns the number of bytes an entity occupies. In this case the entities are the size of a complete array and the size of an element of the array. Given the size of the array divided by the size of a single element of the array we can determine the count of elements in an array whose elements are specified at compile time.

Is there a specific reason you use uint8_t instead of int? (I had to look it up to see what it was :slight_smile: )
Edit: Is it because of the sizeof(long) that you should define the integers as 8 bits?

Is this question directed at any particular piece of code? I’m not quite sure where to direct a reply unless we narrow the question down a bit.

Sorry.

How does this work? There is nothing in the curly braces?

while ( serialRFID.available() < 1 )

{   }

Personal preference I suppose as I don’t like any of the following -

while ( serialRFID.available() < 1 )
    ;

… or …

while ( serialRFID.available() < 1 )     ;

… to me my version clearly shows that we do nothing other than loop waiting for the condition to be satisfied.

For this code, could I use other commands, such as ‘w’ and then put my write functions under that case?

switch ( command )

{
    // receive command from serial to search for and read card
    case ‘r’:
        readTagID();
        idSend();
               
        break;
           
    default:
        break;

Yes, as long as it’s a single character command, and that’s why I did it that way so you could expand on it.

Thank you again for all your help. Sorry about all the questions, but I’m trying to make sure I actually understand how it works for when I make changes.

Not a problem. That is why I prefer to post code that can be questioned as it allows me to determine what you know or don’t know. As well as to expose you to different solutions than those shown in the tutorials.

Feel free to ask about anything and I’ll do my best to answer within the context of what I think you already know limited by my free time at the moment.

The compile time operator 'sizeof' returns the number of bytes an entity occupies. In this case the entities are the size of a complete array and the size of an element of the array. Given the size of the array divided by the size of a single element of the array we can determine the count of elements in an array whose elements are specified at compile time.

Gotcha

Is this question directed at any particular piece of code? I'm not quite sure where to direct a reply unless we narrow the question down a bit.

I was referring to all of this:

const uint8_t   pinVISUAL_CUE_LED   = 13;   // PICNDUINO Onboard LED
const uint8_t   pinLED_2            = 9;    // PICNDUINO Onboard LED

const uint8_t   pinTX               = 6;
const uint8_t   pinRX               = 7;

const uint8_t   LED_OFF             = LOW;
const uint8_t   LED_ON              = HIGH;

const uint8_t   RFID_READ           = 0x01;

SoftwareSerial serialRFID(pinRX, pinTX);

uint8_t buffID[sizeof(long)];

Is there a reason you used uint8_t instead of int? Or was it personal preference?

That's what I thought you might be referring to but I wasn't certain.

If you're familiar with header files then you're likely familiar with function declarations. Looking in the header file "Arduino.h" you'll find the function declarations for some common Arduino routines. The following is pulled from Arduino.h.

void pinMode(uint8_t, uint8_t);
void digitalWrite(uint8_t, uint8_t);
int digitalRead(uint8_t);
int analogRead(uint8_t);
void analogWrite(uint8_t, int);

So the answer is because that is what the API is expecting. Yes it is common that others let the compiler do type conversion but I prefer to give the compiler the correct types as per the function declarations. So yes it is a preference but it's also really the right thing to do.

Oh and these ...

const uint8_t   LED_OFF             = LOW;
const uint8_t   LED_ON              = HIGH;

... should really be ...

const int   LED_OFF             = LOW;
const int   LED_ON              = HIGH;

... as functions such as ...

int digitalRead(uint8_t);

really return 'int' types.

These are intended to be self-documenting synonyms to make the code easier to read lessening the need for unnecessary comments that can get out of sync with the actual code over time.