conversion from float to formatted character array on Arduino nano 33 IoT

Hi everybody

I recently moved on from the Arduino Nano to the Nano 33 IoT, which has a 32 bit microprocessor and is much faster than the good old Nano.
Soon after, I realised that the 'dtostrf()' and 'dtostre()' functions, converting floats to formatted strings (allowing you to specify scientific notation, number of decimals etc.) are not available any more for this processor.
Looked everywhere to find a suitable replacement, but ... found none.
Given the fact that the sprintf() '%f' and '%e' specifiers (doing the same thing) are not implemented either, my question is:
how to convert a float to a formatted string on the nano 33 IoT ?
This seems so basic, and I need it to print values either in scientific notation, with a minimal number of decimals or with decimal points aligned.
Hope I just overlooked something ... Any help is much appreciated

could you use something like

char *
dtoa (
    char  *s,
    float  f )
{
    sprintf (s, "%d.%03d", (int)f, (int)(f * 1000) % 1000);
    return s;
}

It might be worth looking at the code .print() uses – it does a brute force division/remainder approach. A better option is the dtostrf() function that converts a double float to ASCII representation.

https://nongnu.org/avr-libc/user-manual/group__avr__stdlib.html#ga060c998e77fb5fc0d3168b3ce8771d42

#include <stdlib.h>
float f = 123.456;
char buf[10];
dtostrf(f, 9, 3, buf);

Serial.println(buf);

dtostrf() is not available on the nano 33 iot ...
that was the reason for my question ...

I think on ARM targets you have gcvtf() in stdlib.h.

https://sourceware.org/newlib/libc.html#gvcvt

I haven't tried, but sprintf("%f") is worth a go.

Both sprintf and dtostrf work with the Nano 33 IIOT - see below!

#include <avr/dtostrf.h>

float valPI = PI;
char buffer[32];

void setup() {

	Serial.begin(38400);
	while(!Serial) delay(10);
	Serial.println("Print float values");

  //Serial.printf("PI=%.3f\n",valPI); //==== No printf present!
  dtostrf(valPI,6,5,buffer);
  Serial.print("With dtostrf: PI=");
  Serial.println(buffer);

  sprintf(buffer,"With sprintf: PI=%.5f",valPI);
  Serial.println(buffer);
}

void loop() { }

First, about dtostrf(): you’re right, it still works with the Nano 33 IoT. Yesterday, the #include <avr/dtostrf.h> statement produced an error, but I guess I’m the culprit here - only thing I can think of is, I forgot to select the Nano 33 IoT as a board. Now, dtostrf() is working. Good !

But I notice strange behaviour related to sprintf() with %f specifier:

Check the program below:

#include <avr/dtostrf.h>

float valPI = PI;
char buffer1 [ 32 ] { "" };
char buffer2 [ 32 ] { "" };

void setup() {

    Serial.begin( 38400 );
    delay( 10000 );

    Serial.println( "Print float values" );
    sprintf( buffer1, "With sprintf: PI=%.5f", valPI );
    Serial.println( buffer1 );

    dtostrf( 1.0, 4, 1, buffer2 );
}

void loop() {
    // put your main code here, to run repeatedly:
}

It produces the correct result. Serial monitor output:
Print float values
With sprintf: PI=3.14159

Now, comment out the dtostrf(…) line. This line is unrelated to what is printed, uses other variables and comes even after the sprintf() line.

 // dtostrf( 1.0, 4, 1, buffer2 );

Run the program again:

The result is not correct now. Serial monitor output:
Print float values
With sprintf: PI=

This is why yesterday I (correctly) believed sprintf() was not working. At least in this sample program, it will work if you add a call to dtostrf() - which is a mystery.

I believe this is a bug, or at least an undocumented behaviour.
Can anybody challenge that and maybe confirm that, before I report this as such ?

Thanks !

Hello,

I don't know if it will help but to enable floats with sprintf you can add at the top of the sketch

asm(".global _printf_float");

The command "asm (...)" does not help, the Nano 33 IOT does not recognize Serial.printf!
Error message: "error: 'class Serial_' has no member named 'printf'; did you mean 'print'?"

And the curious behaviour with sprintf + dtostrf looks like an error too.

The nano variants should be made of one piece! But the differences between Classic, Every, 33 IOT and Ble Sense are unfortunately uncomfortably serious. I wouldn't have expected that with "print [f].

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.