Serial Comms - problem with float values

Hi Spark Gurus,
I’ll make the obligatory “I’m no programmer, newbie, project manager” statement up front - so please have mercy. I tried the following code on an Arduino UNO - and as expected it echoed back the float values entered from the Arduino IDE monitor. If I try the same with a Spark Core, using an Android tablet as the power supply and serial terminal monitor (USB OTG lead to tablet - Serial Monitor light as the terminal app) the output of the Spark core is 0 - no matter what float value i send to it. Eg: enter 55.00 - output is 0.
Code is as follows:
void setup ()
{
Serial.begin (9600);
}
void loop()
{
while (Serial.available() == 0);
float val = Serial.parseFloat();
Serial.println(val);
}

Any ideas about what’s wrong here would be greatly appreciated - happy to learn, so point me at a tutorial if this is just too obvious…

try:

void loop()
{
  if (Serial.available() == 1)
  {
    float val = Serial.parseFloat( );
    Serial.print(val);
  }
}
1 Like

Hi Bulldog,
Got the core working - but then had trouble with my serial monitor. To get around the tablet monitor / USB problem, I used an FTDI (3.3v) interface direct to serial pins (substituting Serial1. for serial. in the code).

Tried your suggestion but got no output at all, even substituting Serial.print(val); with Serial.println(val);
Your code varied as follows:

void loop()
{
  if (Serial1.available() == 1)
  {
    float val = Serial1.parseFloat( );
    Serial1.print(val);
  }
}

But I did manage to get my original code working as per the Arduino UNO - float value shows correctly followed by 00.00
Code is as follows 
void setup ()
{
Serial1.begin (9600);
}
void loop()
{
while (Serial1.available() == 0);
float val = Serial1.parseFloat();
Serial1.println(val);
}

Only problem now is to get rid of that pesky 00.00 - I think Serial1.parseFloat(); terminates the tx - so maybe the CR is depicted as a zero.

To select the number of digits past the decimal place to print, do it thusly:

Serial1.println(val,4);

Default is two

Use zero for none

1 Like

First of - welcome to the Spark world :wink:
Next, if you want to add a code block to your post, try to enclose your code with a line only containing three ` characters before and after the code (see here for more)

Next you need to know that the Core normally needs to keep in touch with the cloud, so you shouldn’t have any loops or other actions in your code that may stop the Core from communicating with the cloud for more than five (max. ten) seconds.
So you may rewrite your while like this

  ...
  while(!Serial1.available())
    SPARK_WLAN_Loop();  // ensure to keep in touch with cloud
  ...

  // or better not stay inside loop() at all
  ...
  while (Serial1.available())
  { // only read if there is something available
    float val = Serial1.parseFloat();
    Serial1.println(val, 2);
    Serial1.flush(); // to get rid of any remaining bytes
  }
  ...

But since your serial communication is running async you might get “half-transfered” readings if you only check for the presence of any byte.
To make things safer you should apply some way of start-count-stop checking in addition, to ensure that you actually catch the first and all following bytes of one float but no more than that.


BTW: @BulldogLowell, never check for Serial.available() == 1! In standard situations you’ll have most the time zero or more than one byte in the buffer. Your code should never assume to get only a fix count of bytes - always expect the unexpected :wink: or at least be prepared for it.

yeah, I meant that... shame on me

...except for the blocking nature of parseInt( ) which will sit there waiting for setTimeout() or a non-numeric, correct? or does the Stream class behave as differently on Spark as delay( ) (versus Arduino)?

That might be, but given the possibility that the initial transfer has already placed more than one byte in the buffer, your if will never enter and hence the blocking nature of parseXXX() will never come to work.

Since you are dealing with an asynchronous system you have to be prepared for more bytes to have arrived since your last iteration of loop() than you might think of - especially if you go up with your baud rate.


If you look at the implementation, you'll find that it doesn't initially break for non-numerics but only for timeout. Only once actual parsing has started non-numerics will terminate the parsing. Leading non-numerics are just discarded.

OK, Guys – had some time to test the various suggestions you’ve made with some pretty strange results. Firstly, Bulldog: whether I use the “if” or “while” statements in your code I get no output at all. Code is as follows:

void loop()
{
  if (Serial1.available() == 1) // also used “while” statement
  {
    float val = Serial1.parseFloat( );
    Serial1.println(val,2);
  }
} 
'''
On the other hand, my code as originally posted – and the addition of the SPARK_WLAN_Loop();  and Serial1.flush(); lines works fine, returning a float value as input and 00.00 following, which I now believe is the enter command used on the terminal. The last example is as follows:
''' cpp
void setup ()
{
Serial1.begin (9600);
}
void loop()
{
while(!Serial1.available())
    SPARK_WLAN_Loop();  // ensure to keep in touch with cloud
  { // only read if there is something available
    float val = Serial1.parseFloat();
    Serial1.println(val, 2);
    Serial1.flush(); // to get rid of any remaining bytes
  }
}

BUT, and this is a big BUT… This code in either of my iteration or ScruffR’s locks up the Spark Core!
By lock up, I mean the Spark operates fine, breathing cyan and happily echoing incoming float values after it’s been flashed, but it is thereafter impossible to flash new code from the WEB IDE to it. I constantly get the following messages (on the WEB IDE):
“Flashing code…if it does not flash magenta, verify your code and try again.”
“The request seems to take longer than usual. Please be patient…”
“The server has failed to process the request on time. Please try again.”
If I do a factory reset on my Spark, then reclaim it using Tinker – no problem, I can flash any other code (including Bulldog’s) many times without a hitch.

My co-developer (who is a programmer and very capable) is having the same result.

Oh, and sorry, ScruffR - I used the ‘’'cpp wrap on the code but didn’t work?

Hi @DRCO

The markup is three back-quotes with cpp on one line at the start, and three back-quotes on a line at the end. No spaces are or any other things are allowed. I fixed your post for you, but here is how it should look:

   ```cpp
     code here

I have not been following this thread closely but it sure looks like you have some misplaced curly-braces near your while loop. I would look around there.

this works on arduino:

void setup() 
{
    Serial.begin(9600);
}

void loop()
{
  while (Serial.available() > 0)
  {
    float val = Serial.parseFloat();
    Serial.println(val, 4);
  }
}

but won’t work on Spark…

I guess I don’t know about parseFloat( ) on Spark

parseInt( ) won’t work like I would expect either…

this works like I would expect:

void setup() 
{
    Serial.begin(9600);
}

void loop()
{
  while (Serial.available() > 0)
  {
    String val = Serial.readString();
    Serial.println(val);
    float newVal = val.toFloat();
    Serial.println(newVal,4);
  }
}
1 Like

Hi @BulldogLowell

It looks like Serial.parseFloat() depends on Serial.peek() which is the subject of this github issue:

So I believe this will be fixed in a few weeks. It would also work on Serial1 or 2 since it is only broken on the USB serial side.

I am not sure what is going on the with second sketch. It doesn’t look like readString() uses peek but I didn’t follow it all the way through.

Doh… Thanks

1 Like

Hi Bulldog, just a note to let you know I tested your code and it works in echoing the input float value - the output is repeated, with a line space eg:
input = 55.66
output:
55.66
//line space
55.66
Maybe it’s my terminal app

1 Like

maybe its your terminal… Are you sending a CR and/or LF behind your numbers?

Hi Bulldog, just as a final note - my co-developer advises the data throughflow between microcontrollers is accurate and reliable. So thanks for your great input.

1 Like