SoftwareSerial and Parallax RFID example, wierd results.

Hi, I followed the example in the playground here: Arduino Playground - PRFID

The first example, using the arduino UART serial works flawlessly. However if I use the SoftwareSerial example I get some strange behavior. The first read gives garbage as the 'code' but the second read works fine. This is what I get:

First read..
TAG code is: ÿÿÿÿ0ÿÿÿÿÿ
immediately after it reads fine..
TAG code is: 020083741A
TAG code is: 020083741A
TAG code is: 020083741A

If I remove RFID tag from reader for more than 5 seconds or so the next read is garbage..
TAG code is: ÿÿÿÿÿÿÿÿÿ0
TAG code is: 020083741A
TAG code is: 020083741A
TAG code is: 020083741A
TAG code is: 020083741A
TAG code is: 020083741A

wait 5 seconds or so..
TAG code is: 0ÿÿÿÿÿÿÿÿÿ
TAG code is: 02007FD125
TAG code is: 02007FD125

I do not see this behavior with the hardware serial. Is some state becoming corrupt with the SoftwareSerial method?

Thanks,
David Sandor

This code?

// Modified by Worapoht K.
#include <SoftwareSerial.h>

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

#define rxPin 8
#define txPin 9
// RFID reader SOUT pin connected to Serial RX pin at 2400bps to pin8

void setup()
{ 
  Serial.begin(2400);  // Hardware serial for Monitor 2400bps

  pinMode(2,OUTPUT);       // Set digital pin 2 as OUTPUT to connect it to the RFID /ENABLE pin 
  digitalWrite(2, LOW);    // Activate the RFID reader 
}


void loop()
{ 
  SoftwareSerial RFID = SoftwareSerial(rxPin,txPin); 
  RFID.begin(2400);

  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 10 digit read is complete 
      Serial.print("TAG code is: ");   // possibly a good TAG 
      Serial.println(code);            // print the TAG code 
    }
    bytesread = 0; 
    delay(500);                       // wait for a second
  } 
}

That looks extremely strange. I've never seen anyone try to make a new SoftwareSerial instance every time through loop, before.

void loop()
{ 
  SoftwareSerial RFID = SoftwareSerial(rxPin,txPin); 
  RFID.begin(2400);
...

Try this (not tested):

// Modified by Worapoht K.
#include <SoftwareSerial.h>

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

#define rxPin 8
#define txPin 9
// RFID reader SOUT pin connected to Serial RX pin at 2400bps to pin8

SoftwareSerial RFID (rxPin,txPin); 

void setup()
{ 
  RFID.begin(2400);
  Serial.begin(2400);  // Hardware serial for Monitor 2400bps

  pinMode(2,OUTPUT);       // Set digital pin 2 as OUTPUT to connect it to the RFID /ENABLE pin 
  digitalWrite(2, LOW);    // Activate the RFID reader 
}


void loop()
{ 

  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 10 digit read is complete 
      Serial.print("TAG code is: ");   // possibly a good TAG 
      Serial.println(code);            // print the TAG code 
    }
    bytesread = 0; 
    delay(500);                       // wait for a second
  } 
}

Even that modified code isn't very good. You should be checking for available bytes. More details here:

As written you are likely to get garbage (that is -1) which is ÿ in ASCII, which coincidentally is what you are getting.

A return of -1 from a serial read means "no data" which in the code above is just being blindly used as the RFID data. You have to check for it, at the very least.

For example:

    if (val != -1)
      {
      code[bytesread] = val;         // add the digit           
      bytesread++;                   // ready to read next digit  
      }

I've never seen anyone try to make a new SoftwareSerial instance every time through loop, before.

I have. Some know-nothing moron cobbled that example together, and, apparently was successful at reading one tag once, so posted the code on the internet, where everyone to lazy to understand why the code is bad tries to use it.

Thanks Nick for the helpful information. I did not even catch that the SoftwareSerial was being instantiated each loop.

Paul, people new to programming the arduino would be better served by the Playground if the code up there was following some semblance of a best practice. When people are trying to learn the correct way to program these devices it is not helpful to have poorly written examples on the main arduino website.

David

Unfortunately (?) the Playground is just people submitting stuff. It isn't necessarily best practice.