Serial Read reliability [SOLVED!]

I have a ADAM CPWplus - 300 digital scale that transmits its weight values over a serial connection. I have been able to successfully read the serial stream and pull the number value out of it. The trouble is I tend to get weird readings every now and again and I would like this to be a more reliable stream.

Here is what the Scale puts out over serial.

SNG/W+   0.0  lb
OR
UNG/W+   0.6  lb
//the S is for stable weight while the U is for unstable

I have managed to get this result:

A: +443.8
B: +448.6
C: +448.6
A: +503.6
B: +575.2
C: +575.2
A: +601.6
B: ++
C: +479.2
A: +4.0
B: +4.0
C: +3.6
A: +2.0
B: +2.0
C: +1.0

As you can see there are some funky values in there and i would like to have the program only update a string with the current value ( serial input remember) but only if its a valid input.

And of course here is the code that I have right now:
NOTE: this code is designed to be able to read 3x Scales I just have one for my tests.

String scaleValue = "";
void setup()
{
  Serial.begin(9600);
  Serial1.begin(9600);
}

void loop()
{
  Serial.print("A: ");
  readScale0();
  delay(400);
  Serial.print("B: ");
  readScale0();
  delay(400);
  Serial.print("C: ");
  readScale0();
  delay(400);  
}

void sPrint()
{
  Serial.println(scaleValue);
  scaleValue = "";
}

void readScale0(){
  char inByte;
  for(int i =0; i < 30; i++){
    inByte = Serial1.read();
    if (isdigit(inByte))
    {
      scaleValue += inByte;
    }
   //if you need to know if the value is positive or negitive.
    else if(inByte == '+' || inByte == '-'){
      scaleValue += inByte;
    }
    else if(inByte == '.'){
      scaleValue += inByte;
      i = 28;
    }
  }
  sPrint();
}
void readScale0(){
  char inByte;
  for(int i =0; i < 30; i++){
    inByte = Serial1.read();

So, it doesn’t matter whether there is data to read, or not? You just KNOW that there always will be 30 bytes to read.

How do you KNOW that?

Well, I don't but, I do know that there wont be more than 30 before i get to a "." When a byte comes in as a decimal point I set i=28 so it only reads one more byte after that then exits the loop. However sometimes it seems to miss that byte and make for some weird results.

Usually i end up with impossibly large numbers (ex: 35647.5) or numbers with 2 or more digits after the decimal point.(ex: 463.68) this is usually followed by the next reading being truncated (ex: .6) Also the frequently come in with one side or the other missing the numbers (ex: .5 or 354.)

Well, I don't

Don't you think it would be a Good Idea to check first?

AWOL:
Don't you think it would be a Good Idea to check first?

Sure, um... but how ?

I have also tried this method and it works pretty well but has the same issues as the other.

void readScale3(){
  char inByte;
  String scaleValue = "";
    while(Serial3.available()){
        inByte = Serial3.read();
        if (isdigit(inByte)){
          scaleValue += inByte;
        }
        else if(inByte == '.'){
          scaleValue += inByte;
          inByte = Serial3.read();
          scaleValue += inByte;
          csv3 = scaleValue;
          Serial.println(csv3);
          break;
        }
        else if (inByte == 'l'){
        break;
        }
    }
}

Xzeion:

AWOL:
Don’t you think it would be a Good Idea to check first?

Sure, um… but how ?

You could check just about any of the Serial examples and noticed a certain method by the name available.

I have also tried this method and it works pretty well but has the same issues as the other.

Yes, it does. It also assumes that if one byte of data is available, then there will be lots of bytes available to read. That is an incorrect assumption.

The scale must send some kind of end-of-packet marker, or I'd be tossing it in the scrap bin. You need to figure out what that end-of-packet marker is, and read the data, as it arrives, whenever it arrives, and store it until the end of packet marker arrives.

When that happens, you can parse and use the stored data.

while(Serial3.available())

About the only thing that may be keeping this on the edge of just about working is the Serial.println later on.
Don't rely on it.
Typically, there may be only one character available to read, so that while loop isn't going to iterate very much.

More accuratly this is what comes in over the serial without any filtering

 UNG/W+   0..6
  lb  
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
 SNG/W+   0..6
  lb  
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
 SNG/W+   0..6
  lb

I am going to guess that the y (or char 152 on the ascii table) is my stop bit ?

I may be having trouble here because of this little nugget

SNG/W+   0..ÿ <-- note the y where a digit should be...
6  lb

I dont have a choice on the hardware i am reading from. I just have to figure out how to make arduino play nice.

is there an “easy” way to check the results that i am getting in over the serial to see if the output is valid or not ?

ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
 SNG/W+   0ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
..6
  lb  
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ

gota be kidding me.....

Never mind the reads lets look at best way to qualify the data as good or bad.

A few points:
Don't guess.
You never see a stop bit.
The umlaut y is the -1 you get when you read a character that isn't there.

Firstly don't call delay, that's simply asking for lost characters!

Secondly that dump of raw serial bytes looks like might have forgotten to call available again.
Show the code please...

Xzeion:
I have also tried this method and it works pretty well but has the same issues as the other.

void readScale3(){

char inByte;
  String scaleValue = "";
    while(Serial3.available()){
        inByte = Serial3.read();
        if (isdigit(inByte)){
          scaleValue += inByte;
        }
        else if(inByte == '.'){
          scaleValue += inByte;
          inByte = Serial3.read();
          scaleValue += inByte;
          csv3 = scaleValue;
          Serial.println(csv3);
          break;
        }
        else if (inByte == 'l'){
        break;
        }
    }
}

See reply #8.

MarkT:
Firstly don't call delay

If i dont put a delay between the reads only one out of every 3 or so reads even has a value. The final program wont use just a delay but a timer.
Thank you all for your help thus far but i could really use a schooling on how to properly "not guess" at my serial reads. How do I determine precisely when the reads start and stop so i don't get the bad results?
Would using the W or the "+" from before the digits be a good start point? and the L from lb be a good closing bit? I just need the numerical value.

How would i go about setting this up if that would work ? Spell it out for me friends.

If i dont put a delay between the reads only one out of every 3 or so reads even has a value

Every read returns a value.
If you check that there's something available to read before you read it, you'll ensure that you never see the -1 that read returns when there is nothing to be read.
If your device sends a CR or LF code at the end of the reading, use that to decide that you've read everything there is to read.

AWOL:
If your device sends a CR or LF code at the end of the reading, use that to decide that you've read everything there is to read.

I can already get it to read just the numbers but pretty inconsistently. Never mind all of that. Tell me of these CR and LF codes.

CR == carriage return
LF == line feed

How do i check for a carriage return or line line feed
I can change the settings on the scales to have a parity bit?