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);
}
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
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.
*******************************************************
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.
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
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
@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.