Read data using mySerial.available()

Hi,
I am communicating with an RFID reader using “SoftwareSerial mySerial(2, 3); //pin2 Rx, pin3 Tx”.

I can send the “read tag” command on the tx line, but I am not always able to read the response.
Please see my code below.

#include <SD.h>
#include <Wire.h>
#include <SoftwareSerial.h>
SoftwareSerial mySerial(2, 3); //pin2 Rx, pin3 Tx 

//RFID Stuff*****
#define BUFSIZE    15  // Size of receive buffer (in bytes) (10-byte unique ID + null character)

//************************************************************************************************************************************************************************************************************************************************************
void setup(void)
{
Serial.begin(9600);
Serial.println("Determining read response times for the RFID reader:\n"); 
// set the data rate for the SoftwareSerial port 
mySerial.begin(9600); 

  
}

//*************************************************************************************************************************************************************************************************************************************************************
//*************************************************************************************************************************************************************************************************************************************************************
//*************************************************************************************************************************************************************************************************************************************************************

void loop()
{
delay(5000);
Serial.println("Turning on now");
long setime = millis();
mySerial.write(0x53);//This command sets the reader active (Command SRA)
mySerial.write(0x52);//**
mySerial.write(0x41);//**
mySerial.write(0x0d);//**
  while(millis() - setime < 1500){

    char rfidData[BUFSIZE];  // Buffer for incoming data
    rfidData[0] = 0;         // Clear the buffer
    char offset = 0;         // Offset into buffer      

    while (mySerial.available()) {
      byte C = mySerial.read();
      rfidData[offset] = C;
      offset++;
      Serial.print(C); //***** For some reason, the code will not work without this line. It seems to act like a delay to give time for the next byte...??  
    }
    if(offset == 17){
    Serial.println(" ");
    Serial.println(rfidData);
    break;
    }
    
  }
mySerial.write(0x53);//This command sets the reader deactive (Command SRD)
mySerial.write(0x52);//**
mySerial.write(0x44);//**
mySerial.write(0x0d);//**
long setime2 = millis();
long responset = (setime2 - setime);
Serial.print(responset);
Serial.println ("   milliseconds");
  }

I have found that if I do not give the arduino something to do during the " while (mySerial.available()" loop it does not work. In my case I ave put in “Serial.print(C)”. It seems that the arduino is expecting the data faster, and exits the loop thinking it has finished…??
Can anyone explain what is happening?

If you have any questions, please ask.

Attached is the spec of the RFID reader.

Thanks, Micheál.

rfidrw-e-ttl.pdf (543 KB)

Yes, serial data is slow slow slow compared to the code that reads it. Either use an if and check for all the bytes to be there already or send start and end markers with your data and accumulate it into an array until you get to the end. Right now available is true for the first byte but you read and test again before the second byte gets there.

Look for Robin2's great thread on Serial Input Basics to see code examples.

Link to Serial Input Basics

...R

Hi,
Thanks for your input. I tried a whole load of different methods, but I still seem to have the same problem.
What I did is I have looked at the differences between the Uno and the Mega using an oscilloscope. Please see the attached pictures.

The Uno seems to wait while data is coming in on the soft serial port, even though I have no “while available” loop. (There is nothing between commands SRD and SRA).
What do you think of this?

This is my code:

#include <SD.h>
#include <Wire.h>
#include <SoftwareSerial.h>
SoftwareSerial mySerial(2, 3); //pin2 Rx, pin3 Tx 

//RFID Stuff*****
#define BUFSIZE    15  // Size of receive buffer (in bytes) (10-byte unique ID + null character)
//************************************************************************************************************************************************************************************************************************************************************
void setup(void)
{
Serial.begin(9600);
Serial.println("Determining read response times for the RFID reader:\n"); 
// set the data rate for the SoftwareSerial port 
mySerial.begin(9600); 

  
}

//*************************************************************************************************************************************************************************************************************************************************************
//*************************************************************************************************************************************************************************************************************************************************************
//*************************************************************************************************************************************************************************************************************************************************************

void loop()
{
delay(10);
//Serial.println("Turning on now");
long setime = millis();
mySerial.write(0x53);//This command sets the reader active (Command SRA)
mySerial.write(0x52);//**
mySerial.write(0x41);//**
mySerial.write(0x0d);//**
  while(millis() - setime < 150){

    char rfidData[BUFSIZE];  // Buffer for incoming data
    rfidData[0] = 0;         // Clear the buffer
    char offset = 0;         // Offset into buffer    

    while (mySerial.available()) {
      byte C = mySerial.read();
      rfidData[offset] = C;
      offset++;
      delay(1);
      //Serial.print(C); //***** For some reason, the code will not work without this line. It seems to act like a delay to give time for the next byte...??  
    if (C == 13 && offset == 17){
      Serial.println(rfidData);
      break;
    }}
  }
mySerial.write(0x53);//This command sets the reader deactive (Command SRD)
mySerial.write(0x52);//**
mySerial.write(0x44);//**
mySerial.write(0x0d);//**
long setime2 = millis();
long responset = (setime2 - setime);
//Serial.print(responset);
//Serial.println ("   milliseconds");
  }

Thanks, Micheal.

SoftwareSerial only works on pins that support pin change interrupts. Not all pins on the Mega do. The pins that can be used on the Mega are documented on the SoftwareSerial page.

Though why you think you need to use SoftwareSerial on a device with 4 hardware serial ports is a real mystery.

I have tryied various different pins, including the hardware serial pins. I am planning on using 5 serial devices on mega. This is why I am planning on using other than the hardware pins. Can anyone shed some light on the subject?

Rgds, Micheal.

I have tryied various different pins

But not shown any proof...

I am communicating with an RFID reader using "SoftwareSerial mySerial(2, 3); //pin2 Rx, pin3 Tx".

I'm curious why. You did NOT connect a mySerial to the pins, so why the stupid name for the instance? Wouldn't it be far clearer what you are reading from if you were using RFID.available() and RFID.read()?

Hi,

I have gone back and tried the pins which support interrupts again. It all seems to work well this time. Don't know where I went wrong the last time.

I only use this for in times of desperation, but I think it would be in inexperienced users like myselfs best interest if you could refrain from using condescending comments like:

so why the stupid name for the instance?

But other than that, thanks for the input.

You should use AltSoftSerial if pins 46 & 48 on the Mega (8 & 9 on the UNO) are available. After that, you should try NeoSWSerial on any of the pins supported by SoftwareSerial. SoftwareSerial is very inefficient because it blocks interrupts for the entire character RX or TX time. It’s just sitting in a loop waiting for ~1ms (at 9600), preventing anything else from happening, like simultaneous TX and RX. :frowning:

Cheers,
/dev

P.S. Images can be embedded:

6d7e65d089f003ef6253e4a3511ab518030b45a6.jpg

9c006689c1e6a24535532799e165348412013785.jpg

Technique described here.

Moral is don't use 9600 baud... Why anyone wouldn't immediately choose the highest supported serial rate is a mystery to me.