hello,
I just received my new M0 Board (a Adafruit ItsyBitsy M0), and could not make sprintf and/or dtostrf work (SAMD Boards installed correctly).
Then I found this piece of code which I c+p'ed into my Sketch - and now surprisingly both sprintf and dtostrf work fine. But I am curious about 2 things:
how does that snippet make both functions work, especially sprintf for fp?
do I always have to c+p it or is there also a way by a #include <....> ?
linking dtostrf.c enables float support in printf with asm(".global _printf_float"). linking sprintf doesn't enable it. using String with float uses dtostrf so enables it too.
the lines you copy-pasted are in avr/dtostrf.h. #include <avr/dtostrf.h> would do
Juraj:
linking dtostrf.c enables float support in printf with asm(".global _printf_float")
Put that in some suitable function like setup() or whichever function happens to use floats with sprintf(). Just make sure that the function is actually used.
Arduinos traditionally support C printf() but the cut-down version without f-p.
They expect you to use the C++ print() from Print.h
The overloaded print(float, prec=2) has a default precision of 2. So you can just say print(float)
If you want a different number of decimal places, use the full signature.
If you want to control width and precision, use dtostrf().
Some ARM cores use the full-fat version of printf(). After all, you have got plenty of Flash.
Most Arduinos can find dtostrf() by themselves. The M0 and Zero require you to specifically include the header. But the M0 and Zero come with full-fat printf() anyway.
STM32 ST Core has a cut-down printf() for compatibility.
STM32 stm32duino Core has full-fat printf()
ESP8266 and ESP32 have full-fat printf()
Thank you very much, David, now I see - and now it works for my Itsybitsy M0 (i.e., of course outcommented #ifdef for that core)!
sprintf actually is far better for floats than dtostrf, e.g. for left/right text justify, filling chars, adding + signum for positive values, or adding text and multiple variants and formattings.
I'm very glad it's working now, again, thanks a lot!
No. dtostrf() can format just as well as printf() i.e. width and precision.
However printf() makes life a lot easier than Serial.print() when you have multiple items.
The whole operation is done in one statement. Ok, two if you count sprintf(buf, ...) + Serial.print(buf)
It is wise to write code that will work on ALL Arduino targets. Most do not have full-fat printf(). All Arduinos have dtostrf().
You can either use dtostrf() in a Serial.print() or as an %s argument in printf().
In an ideal world, you would not need the specific include. Especially an include path that will fail on some cores. Most Arduinos include all relevant headers via "Arduino.h" (that is prepended to every INO file)
sprintf(buf, "d=%+6.1f r=%+4d p=%+4d", anglef, roll, pitch); // right justified, with explicit extra "+" for positive values
or, e.g., for better structered readability on TFTs:
sprintf(buf, "d=%-6.1f r=%-4d p=%-4d", anglef, roll, pitch); // left justified
but that was only 1 example of lots, mostly I need multiples of floats in either line.
dostrf is far less powerful IMO for such combined chart tables having to show different formatted floats, and extremely cumbersome to daisy chain them up then with extra string constants.
I'm glad sprintf works for ARMs and ESPs, and for some AVR - in case - I'll switch to dtostrf then, unavoidably.
Yes. Both your examples would be painful to do in Print.h methods.
Fairly painful to do in dtostrf() too. You would need separate char buffers for each argument. And conditionals for the + sign.
God did an excellent job when she invented printf().
The previous post by oqibidipo is very straighforward and simple, however, 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:
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: