Go Down

Topic: no sprintf float formatting... come back five year (Read 167 times) previous topic - next topic

xpatch

I've seen this topic covered but I couldn't reply/modify it http://forum.arduino.cc/index.php?topic=44262.0

There's no %f in sprintf you can use various ways to bypass but there's no warning or alert even when verbose logging is enabled. It wasted a fair bit of time and required printf debugging to sort out. It spits out a ? character... Which only makes sense if while banging my head on it a coin poped out.

Going to dig around but if someone has the repo or lib that should be modified to fix an alert up plx reply.


Krupski

#1
Aug 26, 2015, 06:40 pm Last Edit: Aug 26, 2015, 06:40 pm by Krupski
I've seen this topic covered but I couldn't reply/modify it http://forum.arduino.cc/index.php?topic=44262.0

There's no %f in sprintf you can use various ways to bypass but there's no warning or alert even when verbose logging is enabled. It wasted a fair bit of time and required printf debugging to sort out. It spits out a ? character... Which only makes sense if while banging my head on it a coin poped out.

Going to dig around but if someone has the repo or lib that should be modified to fix an alert up plx reply.


The Arduino IDE lacks several desperately needed features that everyone asks for and (hopefully) doesn't hold their breath waiting for.

One of these is floating point support. Another it "print_P" and "println_P" to be able to directly print strings in PROGMEM (how hard can that be folks? I added it to my Print.cpp with less than a dozen lines of code).

As for floating point, even though people rarely run out of program storage space, the ability to optionally link in the floating point code has been non-existent until recently... now it can be done with the newest IDE... albeit with a barely documented procedure.

Again, how hard can it be to add a simple checkbox to "Preferences" to turn it on and off at will (I did that too... again a dozen lines of code or so... maybe 2 dozen at best).

I mean... linking to the floating point code makes the sketch maybe (are you sitting down?) a whopping 2.5K larger. Yes that's K. Not megs, not gigs, not smoldering burned out overloaded Atmel flash memory... just 2500 bytes or so.

So, now that I've gotten that off my chest, I would like to help you. First question: Which IDE do you use?  If you are using the older 1.0.6 or so version, I can simply give you a replacement pde.jar file that adds a checkbox to preferences allowing you to turn it on or off as desired (and the setting is saved in your home/preferences.txt file as are all the other options).

If you have the newer 1.6.5 or so, I can tell you how to edit one text file to add floating point support (although you will have to edit it back and forth by hand to turn it on or off as desired).

Let me know which and I'll fix you up.

Gentlemen may prefer Blondes, but Real Men prefer Redheads!

RayLivingston

On the Due, full printf, including %f, can be enabled by simply putting "#undef printf" at the top of the .ino file, and, perhaps making a one-line change to a library file.  I forget exactly what I had to do, but it was simple.  Perhaps the same is true for AVR-based libraries?

Regards,
Ray L.

oqibidipo

#3
Aug 26, 2015, 09:34 pm Last Edit: Aug 26, 2015, 09:36 pm by oqibidipo
Yes, quite easy, stdio.h tells what to do:

hardware/tools/avr/avr/include/stdio.h

  Since the full implementation of all the mentioned features becomes
  fairly large, three different flavours of vfprintf() can be
  selected using linker options.  The default vfprintf() implements
  all the mentioned functionality except floating point conversions.
  A minimized version of vfprintf() is available that only implements
  the very basic integer and string conversion facilities, but only
  the \c # additional option can be specified using conversion
  flags (these flags are parsed correctly from the format
  specification, but then simply ignored).  This version can be
  requested using the following \ref gcc_minusW "compiler options":

  \code
  -Wl,-u,vfprintf -lprintf_min
  \endcode

  If the full functionality including the floating point conversions
  is required, the following options should be used:


  \code
  -Wl,-u,vfprintf -lprintf_flt -lm
  \endcode



I modified hardware/arduino/avr/platform.txt like this:

Code: [Select]

## Combine gc-sections, archives, and objects
# -- standard setting with stripped-down printf
# recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} -mmcu={build.mcu} {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" {object_files} "{build.path}/{archive_file}" "-L{build.path}" -lm
# -- printf with floating point support
recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} -mmcu={build.mcu} {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" {object_files} "{build.path}/{archive_file}" "-L{build.path}" -Wl,-u,vfprintf -lprintf_flt -lm



Test sketch:

Code: [Select]
void setup() {
  Serial.begin(115200);
  Serial.print(F("Sketch:   " __FILE__ "\n"
                 "Compiled: " __DATE__ " " __TIME__ "\n\n"));

  char buf[80];

  snprintf(buf, sizeof(buf), "%3s  %10s  %10s  %12s", "i", "x", "sin(x)", "exp(x)");
  Serial.println(buf);

  for (int i = 0; i < 200; i++) {
    double x = i * 0.1234;
    snprintf(buf, sizeof(buf), "%3d  %10.3f  %+10.3f  %12.5g", i, x, sin(x), exp(x));
    Serial.println(buf);
  }
}

void loop() { }


Output:

Code: [Select]
Sketch:   test_printf_float.ino
Compiled: Aug 26 2015 22:21:08

  i           x      sin(x)        exp(x)
  0       0.000      +0.000             1
  1       0.123      +0.123        1.1313
  2       0.247      +0.244        1.2799
  3       0.370      +0.362         1.448
  4       0.494      +0.474        1.6382
  5       0.617      +0.579        1.8534
  6       0.740      +0.675        2.0968
  7       0.864      +0.760        2.3722
  8       0.987      +0.834        2.6837
  9       1.111      +0.896        3.0362
 10       1.234      +0.944        3.4349
 11       1.357      +0.977        3.8861
 12       1.481      +0.996        4.3965
 13       1.604      +0.999        4.9739
 14       1.728      +0.988        5.6271
 15       1.851      +0.961        6.3662
 16       1.974      +0.920        7.2023
 17       2.098      +0.864        8.1482
 18       2.221      +0.796        9.2184
 19       2.345      +0.715        10.429
 20       2.468      +0.624        11.799
 21       2.591      +0.523        13.348
 22       2.715      +0.414        15.102
 23       2.838      +0.299        17.085
 24       2.962      +0.179        19.329
 25       3.085      +0.057        21.867
 26       3.208      -0.067        24.739
 27       3.332      -0.189        27.989
 28       3.455      -0.308        31.665
 29       3.579      -0.423        35.823
 
(truncated to stay under 9000 characters)

192      23.693      -0.991    1.9483e+10
193      23.816      -0.968    2.2042e+10
194      23.940      -0.930    2.4937e+10
195      24.063      -0.877    2.8212e+10
196      24.186      -0.811    3.1917e+10
197      24.310      -0.733    3.6109e+10
198      24.433      -0.644    4.0851e+10
199      24.557      -0.545    4.6216e+10

econjack

Good sleuthing, oqibidipo. I was unaware of this. Thank you!

oqibidipo

#5
Aug 28, 2015, 12:13 pm Last Edit: Aug 28, 2015, 12:14 pm by oqibidipo
It gets better...
Leave platform.txt alone and add these lines to boards.txt instead.

Code: [Select]
menu.printf=AVR printf Version

mega.menu.printf.default=Default printf
mega.menu.printf.default.compiler.c.elf.extra_flags=
mega.menu.printf.full=Full printf
mega.menu.printf.full.compiler.c.elf.extra_flags=-Wl,-u,vfprintf -lprintf_flt
mega.menu.printf.minimal=Minimal printf
mega.menu.printf.minimal.compiler.c.elf.extra_flags=-Wl,-u,vfprintf -lprintf_min

Caveat: has to be duplicated for each board.


Go Up