RS485Serial.parseFloat() returns the float AND an extra float of 0.00

I want to better understand the parsefloat in my project and looking for help.
Every 10 seconds I send my float from the max485 driver with this "RS485Serial.println(sensorValue);" if I am plugged into the driver I get the expected number, but when I am plugged into the receiver I will get the scale weight plus another line with 0.00.
Sorry if this has been covered before but I would not find it in my search so I post now. ThanksI

ps. I added another IF statement in order to block the serial.println from following my real number with 0.00. This is a workaround that I would like to avoid.

void loop() {
  
  
  if (RS485Serial.available()) {
    // Read the received data
    float receivedData = RS485Serial.parseFloat();
    if (receivedData > 0){
      Serial.println(receivedData);
    }
  }
}

Welcome to the forum

parseFloat() is terminated by the first character that is not a floating point number. What do you think would happen if there were 2 line ending characters after the float, such as a Linefeed followed by a Carriage Return or vice versa ?

1 Like

there are parameters you can pass to adjust the behavior to your needs (see the doc)

Syntax

Serial.parseFloat()
Serial.parseFloat(lookahead)
Serial.parseFloat(lookahead, ignore)

Parameters

lookahead: the mode used to look ahead in the stream for a floating point number. Allowed data types: LookaheadMode. Allowed lookahead values:

  • SKIP_ALL: all characters other than a minus sign, decimal point, or digits are ignored when scanning the stream for a floating point number. This is the default mode.
  • SKIP_NONE: Nothing is skipped, and the stream is not touched unless the first waiting character is valid.
  • SKIP_WHITESPACE: Only tabs, spaces, line feeds, and carriage returns are skipped.

ignore: used to skip the indicated char in the search. Used for example to skip thousands divider. Allowed data types: char

I assumed it would just give me the data sent, but you are saying the driver sends the sequence followed by something like \n\r and the parseFloat is reporting the 0 in between the two line ending characters?
can this be prevented? I tried playing around with ".parseFloat(lookahead, ignore)" but failed.

thanks

it's a possibility; just print the bytes as they comes in and you'll see or you could check if after reading the float you still have some data

can you break down a sample code for my situation. I had tried some of these. Is it the "SKIP_WHITESPACE" that would fix the problem? I would love to "ignore" the problem but I don't know how to define the char I want to cancel.
thanks

Thanks I will try that asap

check something like that

void loop() {
   
  if (RS485Serial.available()) {
    // Read the received data
    float receivedData = RS485Serial.parseFloat();
    Serial.println(receivedData);
    if (RS485Serial.available())  {
      Serial.print("There is more to read ! First byte is 0x");
      Serial.print(Serial.peek(), HEX); // peek won't remove the byte from the buffer
    } 
  }
}

That is nearly what I had in mind

parseFloat() stops when it receives the \n in your example and returns the float value read immediately before it. The \r remains in the buffer so serial data is still available to the next call to parseFloat(). Once again data is read until the first non numeric value is read, ie the \r, so parseFloat() returns the value of zero

You could just read the \r after doing the parseFloat() and discard it or prevent it being sent in the first place. I am not clear where the data is coming from

it's possibly \r first and then \n (but it boils down to the same explanation)

so this is what was printed

"0.01

There is more to read ! First byte is 0xFFFFFFFF0.00"

So this proves what you guys are saying. I tried changing your "Serial.peek()" to Serial.readBytes() and it failed I would love to "see" the whole message being received in order to better understand this whole serial business.
Thanks

Sorry wrong code obviously you need to read form the right port…

void loop() {
   
  if (RS485Serial.available()) {
    // Read the received data
    float receivedData = RS485Serial.parseFloat();
    Serial.println(receivedData);
    if (RS485Serial.available())  {
      Serial.print("There is more to read ! First byte is 0x");
      Serial.println(RS485Serial.peek(), HEX); // peek won't remove the byte from the buffer
    } 
  }
}

I have a arduino nano that measures the weight of a grain hopper in order to shut off the motor before the grain runs dry. the weight is sent to an lcd on board, but now I want to send the reading to a 4 digit, 7 segment display in another building. I am going from the nano to a MAX485 then to a MAX485 receiver, then to another nano that will power my 7 segment display.

hope that answers.
cheers

So, you have control of the contents of what is sent. Why use Serial.println() when you could follow a Serial.print() of the value with a Serial.print() of say '\r' or '\n' or anything non numeric and read it with Serial.parseFloat() ?

because I am lost. I thought I tried the straight print, but will try again. thanks

Ok, so removing the println worked. This was giving the extra command.
thanks

A single straight print will not add a terminating character that will be used as a trigger for parseFloat() to stop reading input and return the value read.

It couid still work because parseFloat() will also return a value if no data is received for a period of one second, but if data keeps being received frequently enough it will never return a value.

You can change the timeout period using the Serial.setTimeout() function but adding your own data termination character is probably a better solution

How would I go about adding my own terminator? I like this Idea so that there is no chance this gets passed on to my display.

As I suggested previously

what is the syntax? like this
Serial.print(data from scale);
Serial.print(\n);
and then on the receiving end, the parsefloat will kill the parse once a non float is seen?
thanks