Using the RDM630 RFID Tag Reader and NewSoftwareSerial library

Hi all,
Some of you may have seen my previous post regarding NewSoftwareSerial library, and I'm sorry to bother you all again, but my newbie brain has run into another wall :wink: . I'm trying to get a RDM630 RFID Tag Reader (See below for datasheet) to read an RFID tag and send the serial ID to my PC. The reader uses a serial interface to connect to the Arduino, and so I need to use the NewSoftwareSerial library to connect to the reader. What is supposed to happen in the Serial Monitor is this:

Computer to Arduino Serial Ready
RFID to Arduino Serial Ready
Awaiting Tag
RFID Tag ID: (Tag's ID Here)

However, what is actually happening is this:

Computer to Arduino Serial Ready
RFID to Arduino Serial Ready
Awaiting Tag
RFID Tag ID: ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ

If you swipe the tag again, the ID appears as normal. But, if you were to swipe a DIFFERENT tag, the ID would be the same as the first tag on the first swipe, and then would return to the second tag's ID. From this, I get the feeling that it is 'one behind' the whole time, like the data is being sent to the PC first and then the Arduino is recieving data, although that is obviously not the case from my code (Which is yet to include XOR Checksum functionality because of this speedbump):

/*==Libraries==*/
#include <SoftwareSerial.h>

/*==Pin Definitions==*/
#define RFID_LED 2
#define RFID_RX 3
#define RFID_TX 4

/*==Variables==*/
char RFID_Data[15];
boolean RFID_Data_Stored = false;

SoftwareSerial RFID =  SoftwareSerial(RFID_RX, RFID_TX);

void setup() {
  Serial.begin(57600); //Setup connection to Computer via HardwareSerial
  Serial.println("Computer to Arduino Serial Ready"); //Acknowledge connection establihment to Computer
  
  RFID.begin(9600); //Setup connection to RFID Reader via SoftwareSerial
  pinMode(RFID_TX, OUTPUT);//Define RFID TX pin as OUTPUT (Not nessesary)
  pinMode(RFID_RX, INPUT);//Define RFID RX pin as INPUT (Nessesary)
  Serial.println("RFID to Arduino Serial Ready");//Acknowledge connection establishment to RFID Reader
  Serial.println("Awaiting Tag");//Provide Arduino's current status
}


void loop() {
  if(digitalRead(RFID_LED) == LOW) { //Wait for LED pin from RFID Reader to go LOW
    Recieve_RFID(); //And go to 'Recieve_RFID' function
  }
  
  if(RFID_Data_Stored) { //If the RFID Reader has been read, then:
    Serial.print("RFID Tag ID: "); //Print to the computer the Tag ID
    for(int i = 1; i <=14; i++) {
      Serial.write(RFID_Data[i]);
    }
    Serial.println("");
    
    RFID_Data_Stored = false; //Say that the data has been printed
    delay(500); //Delay to avoid false readings
  }
}
void Recieve_RFID() {
  for(int i = 1; i <= 14; i++) { //Recieve data coming from RFID Reader
    RFID_Data[i] = RFID.read(); //Store it in a string
    if(i == 14) {
      RFID_Data_Stored = true; //Tell the Arduino that there is data stored
    }
  }
}

Oh, and here is the Reader datasheet: http://australianrobotics.com.au/sites/default/files/RDM630-Spec..pdf

Thanks for all your help,
Koop

You are not waiting for all the data to be sent before reading it. Your rubbish characters are the result of getting -1 from the read because there is nothing to read. Then by the time the data has arrived in the buffer you have stopped reading it until next time.
You have to ensure that there is something to trad EACH TIME you read the serial.

SoftwareSerial RFID =  SoftwareSerial(RFID_RX, RFID_TX);

  pinMode(RFID_TX, OUTPUT);//Define RFID TX pin as OUTPUT (Not nessesary)
  pinMode(RFID_RX, INPUT);//Define RFID RX pin as INPUT (Nessesary)

You have told the SoftwareSerial instance that the pins are its to manage. So, why are you diddling with them?

void Recieve_RFID() {
  for(int i = 1; i <= 14; i++) { //Recieve data coming from RFID Reader
    RFID_Data[i] = RFID.read(); //Store it in a string
    if(i == 14) {
      RFID_Data_Stored = true; //Tell the Arduino that there is data stored
    }
  }
}

As soon as the reader senses a tag, you expect the data to be available in the serial buffer to be read. At 9600 baud, that is a most unrealistic expectation. The data trickles in slowly. By the time you get frustrated, and wave the tag again, the first set of data has arrived. If you wave a second tag, all you will read is the first tag's data.

This function needs to block (not indefinitely, though) and WAIT for the 14 bytes to arrive, before trying to read them. Why does the first byte get stored in the second position in the array? Array indices start at 0.

More on this subject here

Thanks all,
I changed the Recieve_RFID Function to this, but it still won't work :confused:

void Recieve_RFID() {
if(RFID.available() >= 13) {
for(int i = 0; i <= 13; i++) { //Recieve data coming from RFID Reader
RFID_Data* = RFID.read(); //Store it in a string*

  • if(i == 13) {*
  • RFID_Data_Stored = true; //Tell the Arduino that there is data stored*
  • }*
  • }*
  • }*
    }
    [/quote]
    And AWOL, I know! That was my original post :wink:

Sorry, this is the code, actually:

void Recieve_RFID() {
if(RFID.available() >= 13) {
for(int i = 0; i <= 13; i++) { //Recieve data coming from RFID Reader
RFID_Data = RFID.read(); //Store it in a string

  • if(i == 13) {*
  • RFID_Data_Stored = true; //Tell the Arduino that there is data stored*
  • }*
  • }*
  • } else {*
  • delay(1);*
  • }*
    }
    [/quote]

So, if there are 13 bytes, it's OK to read all 14 of them. Hmmm. I don't think so.

Since you are not using the hardware serial port to talk to the RFID reader, that means that you can use the hardware serial port to debug the issue. I'd suggest that you do that.

By the way, I really don't think your code looks like what you posted. Using the quote button is inappropriate for code. Use the code button, instead (the one with the # on it).

Oh sorry about that. I just hit 'Copy for Forum' in the IDE. Thanks for your help. If I figure it out, I'll be sure to post it up here!

I just hit 'Copy for Forum' in the IDE.

They really need to fix that button, or get rid of it completely.

Are there any framing characters to let you know when a tag begins and ends? Those might be useful to check for.

Note: Your new code is reading 14 characters (0-13).

Try a test sketch that echoes characters from SoftwareSerial() to the serial monitor:

const int RFID_RX = 3;
const int RFID_TX = 4;
SoftwareSerial RFID =  SoftwareSerial(RFID_RX, RFID_TX);

void setup() {
  Serial.begin(57600); //Setup connection to Computer via HardwareSerial  
  RFID.begin(9600); //Setup connection to RFID Reader via SoftwareSerial
  Serial.println("Awaiting Tag");//Provide Arduino's current status
}

void loop()
    {
    if (RFID.available())
       {
       char val = RFID.read();
       Serial.print(val, HEX);
       Serial.print(" ");
       if (val == 10 || val == 13)
           Serial.println();
       }
    }

Awesome, guys! I adapted my Receive_RFID function so that if there is not 14 bytes, then it waits 1 millisecond and tries again, and it works fine! Here is the completed code:

/*==Libraries==*/
#include <SoftwareSerial.h>

/*==Pin Definitions==*/
#define RFID_LED 2
#define RFID_RX 3
#define RFID_TX 4

/*==Variables==*/
char RFID_Data[15];
boolean RFID_Data_Stored = false;

SoftwareSerial RFID =  SoftwareSerial(RFID_RX, RFID_TX);

void setup() {
  Serial.begin(57600); //Setup connection to Computer via HardwareSerial
  Serial.println("Computer to Arduino Serial Ready"); //Acknowledge connection establihment to Computer
  
  RFID.begin(9600); //Setup connection to RFID Reader via SoftwareSerial
  pinMode(RFID_TX, OUTPUT);//Define RFID TX pin as OUTPUT (Not nessesary)
  pinMode(RFID_RX, INPUT);//Define RFID RX pin as INPUT (Nessesary)
  Serial.println("RFID to Arduino Serial Ready");//Acknowledge connection establishment to RFID Reader
  Serial.println("Awaiting Tag");//Provide Arduino's current status
}


void loop() {
  if(digitalRead(RFID_LED) == LOW) { //Wait for LED pin from RFID Reader to go LOW
    Recieve_RFID(); //And go to 'Recieve_RFID' function
  }
  
  if(RFID_Data_Stored) { //If the RFID Reader has been read, then:
    Serial.print("RFID Tag ID: "); //Print to the computer the Tag ID
    for(int i = 0; i <=13; i++) {
      Serial.write(RFID_Data[i]);
    }
    Serial.println("");
    
    RFID_Data_Stored = false; //Say that the data has been printed
    delay(500); //Delay to avoid false readings
  }
}

void Recieve_RFID() {
  Wait_Loop:
  if(RFID.available() >= 14) {
    for(int i = 0; i <= 13; i++) { //Recieve data coming from RFID Reader
      RFID_Data[i] = RFID.read(); //Store it in a string
      if(i == 13) {
        RFID_Data_Stored = true; //Tell the Arduino that there is data stored
      }
    }
  } else { 
    delay(1);
    goto Wait_Loop;
  }
}

Now all I need to do is do some verification, and I'm done!

Johnwasser: Yes there are, and to the Serial Monitor, they appear as spaces. I think that they are ASCII beginning and end of transmission decimal values (that is, they are 002 and 003) the code for understanding them will be added in for verification.

goto Wait_Loop;

A "while" loop would attract a lot less flak.

Edit: typo "look" -> "loop"

Why, AWOL?

Why, AWOL?

Because in 30 years of writing C/C++ code, I have yet to use a single goto.

You want there to be 14 bytes to read. So,

while(Serial.available() < 14)
{
  // Do nothing
}

makes it very clear that you are waiting for 14 characters.

Your goto mess does not.

Your goto mess does not.

Why is Goto considered a 'mess', may I ask?

Because it is mostly unnecessary (I have written one in the last thirty years, but it was deep in a Linux device driver, and required to be signed-off by a director), and has the potential of producing spaghetti code.

SoftwareSerial RFID =  SoftwareSerial(RFID_RX, RFID_TX);

pinMode(RFID_TX, OUTPUT);//Define RFID TX pin as OUTPUT (Not nessesary)
 pinMode(RFID_RX, INPUT);//Define RFID RX pin as INPUT (Nessesary)



You have told the SoftwareSerial instance that the pins are its to manage. So, why are you diddling with them?

I'm changing their pinModes (even though its not really needed) because thats what it does in the SoftwareSerial tutorial:

AWOL:
Because it is mostly unnecessary (I have written one in the last thirty years, but it was deep in a Linux device driver, and required to be signed-off by a director), and has the potential of producing spaghetti code.

Fair enough. It just seemed convenient and quick. Its not like I used it a lot, only once.

Once is once too many.
Simply a GOTO is not a structured piece of code, it can be used to jump into the middle of structures that have not been set up with totally unpredictably consequences.
If you feel the need to use a GOTO then you have not thought out the problem correctly.

See what I mean about attracting flak? :wink: