How slow is SoftwareSerial?

Sorry if this has been asked, I did search and read a lot and learned a lot but nothing that really answered my question.

I am useing an Ardunio Pro Mini, Software Serial on pins 4 and 5. String of data comes in every 1 second. The UART is being used to communicate with a LCD panel that just will not work with SS for whatever reason.
Example incoming Data,
123,25.5,30,26.0,456,25.5,60,26,224,25.5,30,22.0,123,25.5,30,26.0,0,0,0,0,13.9,28.9,25,90;

The ";" is my end of packet character. It never seems to be reached (i'm turning on pin 13 LED when the incoming character is ';'). The exact same code works fine on the regular UART so I am guessing that the SS can't read the entire string fast enough before the next one comes in thus the end ";" character is never reached.

Is one second enough time to clear the buffer?
I can't post code publicly but if you want to take a look I can send it to you in a PM if I can attach it or email it to you.

It might just be crappy coding, Although I try to learn from you guys :wink:

thanks

If you can't post your code, at least post a quick sketch that will reproduce your problem.

Because that takes time, something I am in short supply. I'll see what I can do.

Ok, here is the function in question. I had a chance to try it once, the LED never flickers, but might be too fast to see. I didn't get a chance to try some delays.

The other issue is that the entire program might have to much going on, so it's possible doing a sketch with just this one thing might work and I'm no further forward. That is why I would rather someone look at the entire program.

#include<SoftwareSerial.h>

#define EOP  ';'

SoftwareSerial SSerial(4,5); // RX, TX

int Data[25];

int c; 
int Voltage; 
int Percent[4];
int iTemp;
int TD; 
int Low; 
int High;
int Ff;
int Fg; 
int Fb;
int Fa;

byte Index = 0; //Data index

void setup() 
{
  // put your setup code here, to run once:
  SSerial.begin(9600);
}

void loop()
{
  digitalWrite(13,LOW);
  ReadTankData();
}

void ReadTankData() // DIGITAL
{
  
  if(SSerial.available())
    {
    c = SSerial.read();
    if(c >= '0' && c <= '9')
      {
      iTemp = iTemp * 10 + (c - '0');
      }
    else if(c == ',') // Record Data and move to next index
      {
      Data[Index] = iTemp;
      Index++;
      iTemp = 0;
      }
    else if(c == EOP) // Record data and exit loop
      {
      digitalWrite(13,HIGH);
      Data[Index] = iTemp;
      Index = 0;
      iTemp = 0;
      Percent[0]  = Data[2];
      Percent[1]  = Data[6];
      Percent[2]  = Data[10];
      Percent[3]  = Data[14];
      Ff          = Data[3];
      Fg          = Data[7];
      Fb          = Data[11];
      Fa          = Data[15];
      TD          = Data[16];
      Voltage     = Data[20];
      Low         = Data[22];
      High        = Data[23];
      }
    }
}
// End ReadData()

If SoftwareSerial couldn't read fast enough, that it couldn't read one character before another arrived, it would be useless. Your problem lies elsewhere.

Now that I see your excerpted code, I can't see anything wrong (except you are not handling decimal points).

Possibly the problem is in the code you don't post.

The SoftwareSerial buffer is 64 bytes. That means you can muck around doing other stuff, as long as you empty the buffer before it reaches 64 bytes.

Your string quoted above is 90 bytes. Thus, if you spend a lot of time doing something else, the buffer may fill up by the time you go to read from it.

I am ignoring the decimal, I don't need it.

It's possible that some other part of the code is casing to slow even more like you say. If I use the code on the Hardware UART everything works. Also, everything else works in my code, it just shows 0's for all that data because the ";" is never reached so the data doesn't update to current values.The LED never turns ON. I'll do more testing.

OK , using the code i posted above, I commented out the line that turns the LED OFF, so it should at least turn the LED on if the EOP is reached. at least once. The LED never comes on. So either it is getting over written by the next line coming in or ??? I'm stumped. And nothing else in the way, just that snippet.

Jassper:
I am ignoring the decimal, I don't need it.

Maybe, but by ignoring it, you will treat 25.5 as 255.

What baud rate are you running at? Your posted code doesn't seem to initialize SoftareSerial.

Right, 255 is what I want, not the 25.5, easier to handle in the rest of the code then I stick the . back in for the display.

I edited the code and added the SSerial.begin(9600); in the Setup, Thanks, now I got to go re-test lol.

OK, now that I have corrected my test sketch (I did call out the baud rate in the complete sketch) I now get a flicker on the LED about every second, so the EOP is being reached.

I'll have to really go over my code, I'm just not seeing where the hangup is. Getting late so tomorrow. It's really pretty simple for that part, it supposed to gather all the data then update a touchscreen after it reads all the data. I look at it after a few hours of sleep.

Try using one of the examples in serial input basics to receive all of the data before you try to parse any of it.

...R

Robin2:
Try using one of the examples in serial input basics to receive all of the data before you try to parse any of it.

...R

Thanks for the info, nice read but I think that is what I am doing with the EOP is it not? I don't handle the data until the ";" is received, and that's the whole issue. It's not being received.

Next,
Here is another test file that does not work.

#include<SoftwareSerial.h>

#define EOP  ';'

SoftwareSerial SSerial(4,5); // RX, TX

int Data[25];

int c; 
int Voltage; 
int Percent[4];
int iTemp;
int TD; 
int Low; 
int High;
int Ff;
int Fg; 
int Fb;
int Fa;

byte Index = 0; //Data index

void setup() 
{
  // put your setup code here, to run once:
  SSerial.begin(9600);
}

void loop()
{
  digitalWrite(13,LOW);
  doFirstCall();
  //ReadTankData();
}

void doFirstCall()
{
  ReadTankData(); 
}
void ReadTankData() // DIGITAL
{
  if(SSerial.available())
    {
    c = SSerial.read();
    if(c >= '0' && c <= '9')
      {
      iTemp = iTemp * 10 + (c - '0');
      }
    else if(c == ',') // Record Data and move to next index
      {
      Data[Index] = iTemp;
      Index++;
      iTemp = 0;
      }
    else if(c == EOP) // Record data and exit loop
      {
      digitalWrite(13,HIGH);
      Data[Index] = iTemp;
      Index = 0;
      iTemp = 0;
      Percent[0]  = Data[2];
      Percent[1]  = Data[6];
      Percent[2]  = Data[10];
      Percent[3]  = Data[14];
      Ff          = Data[3];
      Fg          = Data[7];
      Fb          = Data[11];
      Fa          = Data[15];
      TD          = Data[16];
      Voltage     = Data[20];
      Low         = Data[22];
      High        = Data[23];
      }
    }
}
// End ReadData()

The only difference is the serial function is being called from within another function. And that seems to break it. My test LED no longer flickers like it does without the added function call.
It is being called this way in my main sketch as well so I will do some altering on it and see what happens.

Jassper:
Thanks for the info, nice read but I think that is what I am doing with the EOP is it not? I don't handle the data until the ";" is received, and that's the whole issue. It's not being received.

There is a lot of stuff in your ReadTankData() which is not in my examples - so why not try to do it the simple way first. That way you can send the raw data back to the PC as a check on the correct reception.

Also the line ReadTankData; will not work without its ()

...R

Robin2:
Also the line ReadTankData; will not work without its ()

...R

Yeah, I corrected it after posting it. Sorry about that.

I will try your suggestions, I see what your saying, I'm just asking the questions so I can better understand what is really happening. As stated before if I switch this all over the hardware UART, everything works as is. So it may be that SS is just to slow for this application, or at least I will need to handle it differently.

I stripped my test code down to just the following. The LED will flicker as I would expect about once per second. If I set the delay to anything over 2, the the LED either will not flicker at all, or it will blink erratically.

#include<SoftwareSerial.h>

#define EOP  ';'

SoftwareSerial SSerial(4,5); // RX, TX

int Data[25];

int c; 
int Voltage; 
int Percent[4];
int iTemp;
int TD; 
int Low; 
int High;
int Ff;
int Fg; 
int Fb;
int Fa;

byte Index = 0; //Data index

void setup() 
{
  // put your setup code here, to run once:
  SSerial.begin(9600);
}

void loop()
{
  if(SSerial.available())
    {
    c = SSerial.read();
    if(c >= '0' && c <= '9')
      {
      iTemp = iTemp * 10 + (c - '0');
      }
    else if(c == ',') // Record Data and move to next index
      {
      Data[Index] = iTemp;
      Index++;
      iTemp = 0;
      }
    else if(c == EOP) // Record data and exit loop
      {
      digitalWrite(13,HIGH);
      Data[Index] = iTemp;
      Index = 0;
      iTemp = 0;
      Percent[0]  = Data[2];
      Percent[1]  = Data[6];
      Percent[2]  = Data[10];
      Percent[3]  = Data[14];
      Ff          = Data[3];
      Fg          = Data[7];
      Fb          = Data[11];
      Fa          = Data[15];
      TD          = Data[16];
      Voltage     = Data[20];
      Low         = Data[22];
      High        = Data[23];
      }
    }
    delay(2);
    digitalWrite(13,LOW);
}
// End ReadData()

To me that don't sound right but, I still have LOTs to learn. I will also try a new Arduino Pro Mini as soon as they arrive just in case something is wrong with this one.

I will start playing with your examples now, like you said, I may need to just get all the data in first, then play with it later.

Thanks

What part of "keep it simple" do you not understand?

...R

Robin2:
What part of "keep it simple" do you not understand?

...R

WTF?
Don't post if you don't want to help.

And by the way, your test examples - the EXACT same result.
So, are you also saying that your own example isn't simple enough???

This code works for me. This program will print a message "Software serial begin" if you reset the micro when you hook up your usb to ttl adapter. If you don't see that you need to find out what is wrong with your usb to ttl setup, I think.

/*
 
  read software serial
  convert to decimal, place in array and print array contents at end of record
  non blocking

  test string:
  123,25.5,30,26.0,456,25.5,60,26,224,25.5,30,22.0,123,25.5,30,26.0,0,0,0,0,13.9,28.9,25,90;
  
*/
#include <SoftwareSerial.h>

SoftwareSerial SoftSerial(10, 11); // RX, TX

const uint16_t buffSize = 25; // size as necessary

uint16_t inBuff [ buffSize ] = { 0 };

uint16_t buffIndex = 0;      // keep track of array entries

uint8_t inChar;

uint16_t inVal;

void setup()
{
   Serial.begin ( 9600 );
   Serial.println ( F ( "Hardware serial begin." ) );
   

   SoftSerial.begin ( 9600 );
   SoftSerial.println ( F ( "Software serial begin." ) );
   
} // setup


void loop ()
{
  
  while ( SoftSerial.available () > 0 ) 
  {
    inChar = SoftSerial.read ();  

    switch ( inChar )
    {
      
    case ';': // end of record, enter last data
    
      if ( buffIndex < ( buffSize -1 ) ) 
      {
           inBuff [ buffIndex ] = inVal;
      }
      // print out array content for demo
      SoftSerial.println ( F ( "End of data, print out array: " )  );
      
      for ( byte x = 0; x <= buffIndex ; x++ )
      {
        SoftSerial.println ( inBuff [ x ] );
      }
      
      buffIndex = 0;  // reset vars for next record
      inVal     = 0;
    
    break; 
        
    case '0' ... '9': // capture the numeric ascii input and convert to decimal
    
      inVal = inVal * 10 + inChar - '0'; 
      
    break;
      
    case ',':   // field data complete, update array
      
      if ( buffIndex < ( buffSize -1 ) ) 
      {
      inBuff [ buffIndex ] = inVal;
      buffIndex++; // set for next var
      }

      inVal = 0;  // reset
 
    break;

    } // switch 
      
  } // while 
  
} // loop

Jassper:
And by the way, your test examples - the EXACT same result.

Your code in Reply #15 is not the simple code from my example. It would help me to help you if you use my exact code and post the version that you use that does not give you the correct answer. I need to see which of my examples you have used and exactly how you have used it.

If that shows an error in my code then I will be able to update my example.

...R