UNO Q: Println() float or double results in "ovf"

Monitor.println(f) and Monitor.println(d) both show "ovf" for overflow. snprintf works fine. Whenever Uno Q offers an update, I accept so the Uno Q is up to date.

#include <Arduino_RouterBridge.h>

void setup() {
  Bridge.begin();
  Monitor.begin();
}

void loop() {
  float f = 39.3;
  double d = 55.9;
  int i = 3141;
  char print_buf[128];

  Monitor.print("float f = ");
  Monitor.println(f);   /* ovf */
  if (snprintf(print_buf, sizeof(print_buf), "float f = %f using snprintf", f) >
    Monitor.println(print_buf);
  }

  Monitor.print("double d = ");
  Monitor.println(d);   /* ovf */
  if (snprintf(print_buf, sizeof(print_buf), "double d = %f using snprintf", d) 
    Monitor.println(print_buf);
  }

  Monitor.print("int i = ");
  Monitor.println(i);

  delay(1000);
}

I don't know why you're getting the 'ovf', but you can use a String constructor if you like, e.g.:

Monitor.println("double d = " + String(d));
Monitor.print("int i = " + String(i));

@customcontroller

Your sketch of post #1 is nt compiled under IDE 2.3.8 and UNO Q. This is the error message:

E:\ArduinoUNOQ\floatNumber\floatNumber.ino: In function 'void loop()':
E:\ArduinoUNOQ\floatNumber\floatNumber.ino:18:1: error: expected primary-expression before '}' token
   18 | }
      | ^
E:\ArduinoUNOQ\floatNumber\floatNumber.ino:17:32: error: expected ')' before '}' token
   17 |     Monitor.println(print_buf);
      |                                ^
      |                                )
   18 | }
      | ~                               
E:\ArduinoUNOQ\floatNumber\floatNumber.ino:16:6: note: to match this '('
   16 |   if (snprintf(print_buf, sizeof(print_buf), "float f = %f using snprintf", f) >
      |      ^
E:\ArduinoUNOQ\floatNumber\floatNumber.ino:18:1: error: expected primary-expression before '}' token
   18 | }
      | ^
E:\ArduinoUNOQ\floatNumber\floatNumber.ino: At global scope:
E:\ArduinoUNOQ\floatNumber\floatNumber.ino:20:1: error: 'Monitor' does not name a type
   20 | Monitor.print("double d = ");
      | ^~~~~~~
E:\ArduinoUNOQ\floatNumber\floatNumber.ino:21:1: error: 'Monitor' does not name a type
   21 | Monitor.println(d); /* ovf */
      | ^~~~~~~
E:\ArduinoUNOQ\floatNumber\floatNumber.ino:22:3: error: expected unqualified-id before 'if'
   22 |   if (snprintf(print_buf, sizeof(print_buf), "double d = %f using snprintf", d)
      |   ^~
E:\ArduinoUNOQ\floatNumber\floatNumber.ino:24:3: error: expected declaration before '}' token
   24 |   }
      |   ^
E:\ArduinoUNOQ\floatNumber\floatNumber.ino:26:3: error: 'Monitor' does not name a type
   26 |   Monitor.print("int i = ");
      |   ^~~~~~~
E:\ArduinoUNOQ\floatNumber\floatNumber.ino:27:3: error: 'Monitor' does not name a type
   27 |   Monitor.println(i);
      |   ^~~~~~~
E:\ArduinoUNOQ\floatNumber\floatNumber.ino:29:8: error: expected constructor, destructor, or type conversion before '(' token
   29 |   delay(1000);
      |        ^
E:\ArduinoUNOQ\floatNumber\floatNumber.ino:30:3: error: expected declaration before '}' token
   30 |   }
      |   ^
Multiple libraries were found for "Arduino_RouterBridge.h"
  Used: C:\Users\GolamMostafa\Documents\Arduino\libraries\Arduino_RouterBridge
  Not used: C:\Users\GolamMostafa\AppData\Local\Arduino15\packages\arduino\hardware\zephyr\0.55.0\libraries\stubs
exit status 1

Compilation error: expected primary-expression before '}' token

Please, submit the complete sketch so that I can test it without wasting time.

This is a working sketch:

#include <Arduino_RouterBridge.h>

void setup() {
  Bridge.begin();
  Monitor.begin();
}

void loop() {
  float f = 39.3;
  double d = 55.9;
  int i = 3141;

  Monitor.println("float d = " + String(f));
  Monitor.println("double d = " + String(d));
  Monitor.println("int i = " + String(i));
  Monitor.println("========================");

  delay(1000);
}

Output:

========================
float d = 39.30
double d = 55.90
int i = 3141
========================

I edited his sketch to make it compile... Missing a couple of )s and {s...

#include <Arduino_RouterBridge.h>

void setup() {
  Bridge.begin();
  Monitor.begin();
}

void loop() {
  float f = 39.3;
  double d = 55.9;
  int i = 3141;
  char print_buf[128];

  Monitor.print("float f = ");
  Monitor.println(f); /* ovf */
  if (snprintf(print_buf, sizeof(print_buf), "float f = %f using snprintf", f)) {
    Monitor.println(print_buf);
  }

  Monitor.print("double d = ");
  Monitor.println(d); /* ovf */
  if (snprintf(print_buf, sizeof(print_buf), "double d = %f using snprintf", d)) {
    Monitor.println(print_buf);
  }

  Monitor.print("int i = ");
  Monitor.println(i);

  delay(10000);
}

And the output:

float f = ovf
float f = 39.299999 using snprintf
double d = ovf
double d = 55.900000 using snprintf
int i = 3141
float f = ovf
float f = 39.299999 using snprintf
double d = ovf
double d = 55.900000 using snprintf
int i = 3141

Which confirms the problem:

@customcontroller: If you have a github account, you might want to create an issue up at: Issues · arduino/ArduinoCore-zephyr

If not, I can or better yet @ptillisch

Thank you.

Note: I edited the sketch again, to allow it to build for either the GIGA (zephyr) or UNOQ...

#ifdef ARDUINO_UNO_Q
#include <Arduino_RouterBridge.h>
#endif
void setup() {
#ifdef ARDUINO_UNO_Q
  Bridge.begin();
#endif
  Serial.begin(115200);
}

void loop() {
  float f = 39.3;
  double d = 55.9;
  int i = 3141;
  char print_buf[128];

  Serial.print("float f = ");
  Serial.println(f); /* ovf */
  if (snprintf(print_buf, sizeof(print_buf), "float f = %f using snprintf", f)) {
    Serial.println(print_buf);
  }

  Serial.print("double d = ");
  Serial.println(d); /* ovf */
  if (snprintf(print_buf, sizeof(print_buf), "double d = %f using snprintf", d)) {
    Serial.println(print_buf);
  }

  Serial.print("int i = ");
  Serial.println(i);

  delay(10000);
}

And it appears to work correctly on GIGA?

float f = 39.30
float f = 39.299999 using snprintf
double d = 55.90
double d = 55.900000 using snprintf
int i = 3141

Note I did not fix the sketch for the snprintf warning:

"C:\\Users\\kurte\\AppData\\Local\\Arduino15\\packages\\zephyr\\tools\\arm-zephyr-eabi\\0.16.8/bin/arm-zephyr-eabi-g++" -g -Os -std=gnu++17 -c -D_PICOLIBC_CTYPE_SMALL=1 -Wall -Wextra "-imacrosD:\\Arduino\\hardware\\arduino-git\\zephyr\\variants\\arduino_giga_r1_stm32h747xx_m7/llext-edk/include/zephyr/include/generated/zephyr/autoconf.h" "-imacrosD:\\Arduino\\hardware\\arduino-git\\zephyr\\variants\\arduino_giga_r1_stm32h747xx_m7/llext-edk/include/zephyr/include/zephyr/toolchain/zephyr_stdint.h" "@D:\\Arduino\\hardware\\arduino-git\\zephyr\\variants\\arduino_giga_r1_stm32h747xx_m7/cxxflags.txt" -fno-exceptions -fno-rtti -fno-threadsafe-statics -fno-unwind-tables -fno-use-cxa-atexit -lstdc++ -lsupc++ -lnosys -nostdlib -lstdc++ -lsupc++ -lm -fno-exceptions -fno-rtti -fdata-sections -ffunction-sections -fno-unwind-tables -MMD -mcpu=cortex-m7 -mfloat-abi=softfp -mfpu=fpv5-d16 -DARDUINO=10607 -DARDUINO_GIGA -DARDUINO_ARCH_ZEPHYR -DARDUINO_ARCH_ZEPHYR -DARDUINO_LIBRARY_DISCOVERY_PHASE=0 "-ID:\\Arduino\\hardware\\arduino-git\\zephyr\\cores\\arduino" "-ID:\\Arduino\\hardware\\arduino-git\\zephyr\\variants\\arduino_giga_r1_stm32h747xx_m7" "-ID:\\Arduino\\hardware\\arduino-git\\zephyr\\cores\\arduino/api/deprecated" "-ID:\\Arduino\\hardware\\arduino-git\\zephyr\\cores\\arduino/api/deprecated-avr-comp" "-iprefixD:\\Arduino\\hardware\\arduino-git\\zephyr\\variants\\arduino_giga_r1_stm32h747xx_m7" "@D:\\Arduino\\hardware\\arduino-git\\zephyr\\variants\\arduino_giga_r1_stm32h747xx_m7/includes.txt" "C:\\Users\\kurte\\AppData\\Local\\arduino\\sketches\\55A0E840F13FEAC8EBCC796AEAE53FF0\\sketch\\sketch_may5a.ino.cpp" -o "C:\\Users\\kurte\\AppData\\Local\\arduino\\sketches\\55A0E840F13FEAC8EBCC796AEAE53FF0\\sketch\\sketch_may5a.ino.cpp.o"
D:\temp\.arduinoIDE-unsaved202645-34292-z2dn6x.m1y2\sketch_may5a\sketch_may5a.ino: In function 'void loop()':
D:\temp\.arduinoIDE-unsaved202645-34292-z2dn6x.m1y2\sketch_may5a\sketch_may5a.ino:19:77: warning: implicit conversion from 'float' to 'double' when passing argument to function [-Wdouble-promotion]
   19 |   if (snprintf(print_buf, sizeof(print_buf), "float f = %f using snprintf", f)) {
      |                                                                             ^

I did not try it on other boards.

@jgmdavies

That is an excellent workaround that is much easier than using snprintf.

@KurtE

Thanks for the fixing the sketch. Something truncated long lines when I pasted the code.

That is interesting point that this bug is really a zephyr issue instead of Uno Q or App Lab. I am fine with someone else creating the issue. I probably would have created the issue in the wrong repo.

Unclear - could be different library code or ???
But created issue:
[UNO Q} - Serial.print of a float or double prints ovf · Issue #472 · arduino/ArduinoCore-zephyr

@ptillisch @customcontroller

Note: This issue is not confined to to just Serial.print of float or double,

I was trying to debug some of it yesterday and could reproduce the issue in a different way with simple sketch:

#ifdef ARDUINO_UNO_Q
#include <Arduino_RouterBridge.h>
#endif
void setup() {
#ifdef ARDUINO_UNO_Q
  Bridge.begin();
#endif
  Serial.begin(115200);

  delay(1000);

  float f = 39.3;
  double d = 55.9;

  printk("\n\n*******************************************************\n");
  printk("inline %f > %f? %d\n", f, 4294967040.0, (f > 4294967040.0)? 1 : 0);
  printk("inline %f > %f? %d\n", d, 4294967040.0, (d > 4294967040.0)? 1 : 0);

  print_through_function(f);
  print_through_function(d);
}

void  print_through_function(double val) {
  printk("though function %f > %f? %d\n", val, 4294967040.0, (val > 4294967040.0)? 1 : 0);
  printk("*******************************************************\n");
}

void loop() {
  delay(1000);
}

The output shows:

*******************************************************
inline 39.299999 > 4294967040.000000? 0
inline 55.900000 > 4294967040.000000? 0
though function 39.299999 > 4294967040.000000? 1
*******************************************************
though function 55.900000 > 4294967040.000000? 1
*******************************************************

As I mentioned in the issue #472 linked above, maybe issue of when called directly
within code the compare is done maybe at compile time but through call, it
is maybe done through helper function, and that library helper function is compiled into the zephyr bootloader and we have fixups for.... Wondering if the fixup is not working properly on Q?

The core problem seems to be the print function, so any solution that converts the numbers to a char array or a String will work (within the limits of such function).

@GolamMostafa tested for me the char * sci(double value, uint8_t decimals) from my printHelpers library on the UNO Q as I do not own one. The test results are in line with the statement above. (the output shows rounding errors to be investigated)

#include<Arduino_RouterBridge.h>
#include "printHelpers.h"

void setup()
{
  Bridge.begin();
  Monitor.begin();
}


void loop()
{
  float f = 39.3;
  double d = 55.9;
  int i = 3141;
  Monitor.print("float f = ");
  Monitor.println( sci(f,2) );

  Monitor.print("double d = ");
  Monitor.println( sci(d, 4) );

  delay(1000);
}

which printed the values in scientific format.

float f = 3.92E+01
double d = 5.5899E+01

The sci() function was written long ago to prevent large floats to be printed as OVF on the original UNO. It can also be used to print very small floats without loosing readability.


reread the analysis of @KurtE which is more than interesting.
Unfortunately cannot confirm.

The developers have prepared a fix for the bug:

Some additional actions will need to be completed before that fix reaches the users:

  1. Complete review of the proposed fix.
  2. Merge the pull request.
  3. Make a new release of the "Arduino UNO Q Board platform.

Thanks @ptillisch yep the one fix for not loading some sketches broke this.
Another option might be to downgrade to previous release of the board...

But a side question, is about the tests within printFloat...

size_t Print::printFloat(double number, int digits)
{
  if (digits < 0)
    digits = 2;

  size_t n = 0;

  if (isnan(number)) return print("nan");
  if (isinf(number)) return print("inf");
  if (number > 4294967040.0) return print ("ovf");  // constant determined empirically
  if (number <-4294967040.0) return print ("ovf");  // constant determined empirically

Where do those numbers (4294967040.0) come from?

If I print out the values:
printk("MAX DBL: %lf float:%f\n", DBL_MAX, FLT_MAX);

It shows:

MAX DBL: 179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.000000
float:340282346638528860000000000000000000000.000000

Just wondering...

I recognize these as MAX_UINT32-ish,
In the printFloat of UNO / AVR printFloat it is stated

size_t Print::printFloat(double number, uint8_t digits) 
{ 
  size_t n = 0;
  
  if (isnan(number)) return print("nan");
  if (isinf(number)) return print("inf");
  if (number > 4294967040.0) return print ("ovf");  // constant determined empirically
  if (number <-4294967040.0) return print ("ovf");  // constant determined empirically

MAX UINT32 == 4.294.967.295 which 0xFFFFFFFF
4294967040 == 0xFFFFFF00

As a float is only 23 bit mantissa, the float value compares with the max float value that can be represented with an uint32_t. The rationale is that the printing math in printFloat() is all done with (32 bit) integers.

FYI, exact this (premature) overflow is the reason I wrote the sci() and eng() functions to have scientific / engineering notation for floats / doubles.
(see printHelpers library)


FYI traced the scientific notation back to this post of 13 years ago - 2013-05-12

@customcontroller @ptillisch and all,

Another semi work around for this specific issue, is to edit your Print.cpp file.

On my machine it is located at:
C:\Users\kurte\AppData\Local\Arduino15\packages\arduino\hardware\zephyr\0.55.0\cores\arduino\api\Print.cpp

I just commented out the two tests:

size_t Print::printFloat(double number, int digits)
{
  if (digits < 0)
    digits = 2;

  size_t n = 0;

  if (isnan(number)) return print("nan");
  if (isinf(number)) return print("inf");
  //if (number > 4294967040.0) return print ("ovf");  // constant determined empirically
  //if (number <-4294967040.0) return print ("ovf");  // constant determined empirically

  // Handle negative numbers

And then rebuilt the sketch:

float f = 39.29
float f = 39.299999 using snprintf
double d = 55.89
double d = 55.900000 using snprintf
int i = 3141

Note: it does not fix the underlying issues with the two functions, which now have
improper wrappers around them...

A lot more details about the issue with these wrappers can be found in the issue:
[UNO Q} - Serial.print of a float or double prints ovf · Issue #472 · arduino/ArduinoCore-zephyr

@KurtE
One of the other issues I was having with the XV-11 was that the PID controller I was using (the standard PID v1) uses doubles wasnt working the controller would never adjust or update the pwm values. No errors popped up with using doubles.

I update this morning to the merged changes to fix the double print issue on the chance that it affected more than prints and voila the controller was able to update the RPM of the XV-11 and I was able to start receiving distance data from the XV-11 - but still the issue with Serial1 data persists - will probably post about that as well in the other thread.

I have news on this subject: Version 0.55.2 of the "Arduino UNO Q Board" platform (arduino:zephyr) has now been released, and contains the bug fix.

You should see an update notification the next time you start Arduino App Lab or Arduino IDE.

I updated and confirm the problem is fixed.

I also confirm that the package is updated and the problem of printing decimal number is fixed.