[SOLVED] Why can't I print a "float" value with sprintf ?

  float fl = (glove[1] / 22.8) - 0.85;
  char minStr[100];//cnt    min sec   temp  skinHi skinLO  beat   move
  print"fl = ";
  println(fl,2);
  sprintf(minStr,"%1.2f  ,%02d:%02d  ,%03d  ,%03d  ,%03d  ,%03d  ,%03d",
    fl,hour,minute,oneMin.temperature,oneMin.highSkin,oneMin.lowSkin,oneMin.heartBeats,oneMin.maxMove);
  Serial.println(minStr);

Above is a section of my actual sketch. The only part I'm having a problem with is the "%1.2f".

This page explains:

sprintf(aa, "%0.7f", a);
The general syntax "%A.B" means A digits before decimal point & B digits after decimal point :slight_smile:

I've followed this syntax exactly, so how can it not work?

The output I get from the above is:

fl = 7.75
?  ,20:46  ,147  ,000  ,000  ,000  ,255

Since the first line of output shows that fl has the correct floating point value, why does the second line show a "?" for it instead?

The "?" comes from the fact that floating point is by default not supported for sprintf in Arduino. The means to add that support is posted in many places on the forum and elsewhere.

sprintf(aa, "%0.7f", a);
The general syntax "%A.B" means A digits before decimal point

Not correct. A is the minimum width of the entire field. If the number takes up less than A spaces, the remaining space is blank filled.

Thank you. That explains everything.

After seeing some of those solutions, I molded them into my own solution for two decimal places. It now works perfectly for me.

  float fl = (glove[1] / 22.8) - 0.85;
  char str[10];
  int newFl = round(fl*100);
  sprintf(str,"%03d",newFl);
  str[4] = 0;
  str[3] = str[2];
  str[2] = str[1];
  str[1] = '.';
  char minStrA[50];
  char minStrB[50];
  strcpy(minStrA,str);
  Serial.print("newFl:");
  Serial.println(newFl);
  sprintf(minStrB,"  ,%02d:%02d  ,%03d  ,%03d  ,%03d  ,%03d  ,%03d",
 hour,minute,oneMin.temperature,oneMin.highSkin,oneMin.lowSkin,oneMin.heartBeats,oneMin.maxMove);
  strcat(minStrA,minStrB);
  Serial.println(minStrA);

The output of 7.75 now matching on both lines:

fl = 7.75
7.75  ,20:46  ,147  ,000  ,000  ,000  ,255

If you are going to use an array to hold the float converted to a string BY ITSELF anyway, dtostrf() will save you the trouble of converting the float to an int and then inserting a decimal point. Your conversion makes some assumptions that are not, in general, true for floats. They may be for your specific float.

For those using an AVR board that want to know more about customizing the Arduino IDE and allowing the extra overhead of the full printf related tools, read on:

A solution can be found by reading the AVR documentation for the printf family of functions that will lead you to vfprintf… at the bottom there it describes compiler flags needed for properly linking in the full functionality (see following link):
https://www.nongnu.org/avr-libc/user-manual/group__avr__stdio.html#gaa3b98c0d17b35642c0f3e4649092b9f1

The problem is that knowing where to put the compiler flags can be difficult. Compiler options are found in a file called “platform.txt” and in this case we want to add to “compiler.c.elf.extra_flags”. If you want to add your own flags without messing up the default Arduino files then use “platform.local.txt” (you will have to create this file). Assuming Windows, for standard Arduino boards, the path to these files is similar to:
*C:\Program Files (x86)\Arduino\hardware\arduino\avr*

If you have a non-standard board, you will need to modify folder options to show hidden folders, and the path is similar to:
_C:\Users*\AppData\Local\Arduino15\packages*\hardware\avr**_

I would recommend simply adding the file “platform.local.txt” and in that file adding the following line:

compiler.c.elf.extra_flags=-Wl,-u,vfprintf -lprintf_flt -lm

That should do it. Floats will now be printed instead of “?”. :slight_smile:

NOTE: When enabling the full vfprintf library, my code memory footprint (flash) increased by 1472 bytes.

1 Like