Using a particle function to pass multiple floats in one function call

I’m trying to use a couple of particle functions to remotely configure my device in the field.

One function would send sensor calibration parameters; the other would send environmental calibration parameters. All of the parameters are double-precision floating point.

Ideally, there would be only two functions (one sensor, one environmental) where each function sets 3 parameters. (so 6 parameters total.) Currently, the parameters are stored as retained variables (so they don’t disappear if I “sleep deep”). Eventually, the parameters would be stored using the eeprom emulation capabilities so that they would survive even power cycles.

I tentatively wanted to pass the parameters as a command-separated list, but I’m having trouble parsing that from the function command string.

The first approach that I tried was to convert the string class argument holding the comma-separated list into a character array, then parse the character array using sscanf. sscanf always returned zero (meaning it converted zero characters) and the variables that it was supposed to update were unchanged. I added debug prints to the code to confirm that the function was being called and that the string arguments were really there (both before and after the conversion to a character array). All of that looked good.

I also tried passing only one argument (no commas). Still sscanf did nothing.

What does work is to directly convert a single argument (no commas) to a float using the String class “toFloat()” method… but then I need a separate function call for each argument – so six separate functions rather than two.

I suspect I could come up with a loop to parse through the String class string, and call toFloat on multiple comma-separated substrings. This is probably the best and right way, but I figured that I’d ask and see if anyone has suggestions.

BTW, the following code does as expected if compiled and run on my Linux box. I.e., it prints 6.400000,9.200000,-2.784260 whereas I would expect to get 100.000000,101.000000,102.000000 if I tried it on my electron, based on the behavior I’ve seen so far. (Didn’t actually try this exact code on the electron.)

Thanks,

Jeff

#include "stdio.h"
static const char mystring[] = “6.4,9.2,-2.78426”;

double a = 100;
double b = 101;
double c = 102;

void main() {
sscanf( mystring, “%lf,%lf,%lf”, &a, &b, &c );
printf( “%f,%f,%f\n”, a, b, c );
}

1 Like

I’ve used sscanf() for integers with success, I’d have to try doubles then.

But for the “manual” approach have a look at strtok() and atof() - at least this is what I’d do (I don’t like String ;-))

I’ve had trouble using %f to read float values with sscanf in the past. Like Scruffr said, atof is a good alternative.

Googling a bit suggests that this is a common issue and one workaround (for Teensy and some other ARMs) was using asm(".global _printf_float"); and asm(".global _scanf_float");, but that doesn’t help here.

There’s another reference that might help too
http://www.cypress.com/knowledge-base-article/floating-point-support-printf-and-scanf-gnu-arm-compiler-kba89724

I was about to ping @mdma or @jvanier about this

1 Like

I seem to recall this is one of those things that gets optimized out on embedded builds, but this is a really useful function to have, I filed a bug for this here since this cost me some time this morning:

Thanks!
David

2 Likes

A quick followup to my original question in this thread… I ended up using the string class methods to find the commas and do the conversion. The code isn’t very pretty/reusable right now, but it works.

Thanks to those who replied. At least I now know I wasn’t the only one unable to sscanf floats.

Jeff

1 Like

Yeah, burned a bunch of time to get sscanf() to work with floats/doubles until I came here. Big waist of time. Sscanf() should work ‘as normal’ or removed altogether imho.

Have you read the reasoning in the linked GitHub issue?

Nope! It does work for integers and strings.
Breaking code for others because it's not doing everything you were expecting is not the way to go IMHO.

@ScruffR; no didn’t see the reasoning in GitHub - not sure if I should. From my point; I have lost valuable business time on a function that I have used for years only to find out it is halfway implemented. That is just … annoying. If sscan() wasn’t supposed to be implemented in its entirety; perhaps it should have been named sscanf() in the first place. Oh well, history I guess.

Of course I understand your point about code breaking; but I would like particle to understand that ‘code clarity’ and documentation (of some sort) is important also.

'nuff said, I am not ranting nor do I want to start one :wink:

Just for the records the f in sscanf() (or scanf() for non-*storage-/-s*tring-based input) stands for format(ted) not float and it’s not uncommon for systems without dedicated floating point instruction sets not to support floats (in these libraries) by default.

That’s the reason why this topic is also broadly discussed on the web and not isolated on Particle devices.

3 Likes