-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
sprintf for floats on Arduino Mega? #293
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
To keep things consistent, this would probably have to be added to the Uno and other small variants. Otherwise code will fail to work correctly between them. This has been discussed before I'm pretty sure, and I think the overhead would be undesirable for the smaller boards. There are already floating point conversions in both the Print class and String class. If both are used, then there is a substantial code size increase. If there is a pragma for this option, you cuold simply add it to your sketch when you need it. If you're interested, I have a library PrintEx in the library manager which has sprintf and a printf for Print objects. It also supports repition, reading from PROGMEM, and EEPROM. Using a GString object you can also use print/printf functions and streaming to write to RAM variables. Which is far more efficient that grabbing in the whole sprintf function (depending on how much of its functionality you use). |
my question was about to be optionally (!!) enabled perhaps by a #include or by a #pragma config. Having to deal currently with the mutilated AVR-sprintf-crippel stuff and those unconscionable ftoa functions is an impertinence, so every programmer should be empowered to decide by his own if he wants the full ANSI C /stdio.h functionality or not (like on the Due, and the Mega is powerful enough for that purpose, too). And finally the original stdio.h-sprintf version is already existing and available, so why not to be simply - optionally - enabled for Sketch? |
Enabling float support for printf is currently only possible by passing some compiler flags to the linker, which is not currently possible from within a sketch. This feature is disabled by default to save space. |
re: "This feature is disabled by default to save space." Of course I know that, and that's already been said. So my post was meant to be a request for a new additional feature. |
now what about making possible that sprintf() can be optionally (!!) enabled perhaps by a #include or by a #pragma config ?? |
I cannot think of any way to do this, without having to make significant changes to gcc and/or avr-libc... |
Perhaps have just two sets of different either by #include <libfloat.h> // switches from lib.c ctandard to libcfloat (extended) or., e.g., set a #define libcfloat // switches the libs for the linker automatically or., e.g., set a #pragma config libcfloat which does the same automatically by preprocessor, compiler and linker. Finally when patching all |
Add this to
(Full version attached.) |
I just need the functionality for sprintf and possibly vsprintf and sscanf,
But your list does not mention sprintf and either string formatting function so I'm curious if it will solve the sprintf issue? (BTW, for the DUE sprintf and vsprintf work fine even for floats, just not for AVRs) |
It covers the whole |
ok, |
Just select Default printf / Default scanf if you don't need floating point support. |
how can I do it in a couple of programs and do the other thing in another couple of programs from inside my code? as I wrote in my TOP:
one time I must be able to exclude the full sprintf functionality optionally because of memory reasons, and the other time I must be able to have this sprintf feat. floats formatting optionally when I need this functionality ! |
@tofrnr Could it done differently, perhaps. It might be possible to have played some games with some weak symbols to affect link ordering to trick the linker to select different libraries by using a dummy symbol in the application code. However, that is now how the AVR libC is implemented and it is very unlikely something that Arduino development team would ever want to take on. So basically there are a hand full of approaches.
None of these will give you control from the application source code. As an alternative you might want to look at the PrintEx library. It is actually a much nicer solution than using the xxprintf() routines and will work consistently across all platforms with a smaller footprint than using the libC xxpprintf() routines, particularly on some of the other (non AVR) platforms. |
re: "You don't seem to be understanding that the way this is controlled is through compiler and linker flags." perhaps by a #pragma config which changes the compiler and linker flags or by doing different magic things, or a Anyway, oqibidipo's proposal sounded as if perhaps he might have found a workaround nevertheless. So my wish is still the same, i.e. to change the current implementation into a more suitable one: "could we finally have sprintf for floats on Arduino Mega? |
@tomFr, I don't know of a way to do what you are asking for without having to modify the gcc tools which is the same comment @matthijskooijman made earlier. Also, consider that using the floating point xxprintf() libraries over the reduced libraries is a cost of about 1.8k of flash space when floating point formatting is not used. I think it is reasonable to request that there be a way to enable xxprintf() floating point support from the IDE. - Perhaps through an option just like the verbose mode. Or perhaps through a free form option text box that can be passed through to the compiler and/or linker. But I believe to ask for the capability for this to be controlled by an individual application source code module is a step too far. Think about what you are asking. You are asking for the ability of an individual source code module to affect the compiler and/or linker options used to compile that module (as well as potentially affecting options used for other modules) and to control the linker options that are used when linking together all the modules and libraries. There are are already multiple pre-built libraries for the xxprintf() support. They come with the avr libC libraries that come from the avr gcc package included in the IDE but is not maintained by the arduino development team. The way the various xxprintf() libraries are selected is through linker flags. Like I said earlier it might be possible to play some games using weak symbols or symbol renaming pragmas to trick the linker into pulling in a specific xxprintf() library. But then you would have to go in and modify the avr libC code for those libraries, rebuild all the libraries to create a new avr libC package to put into a new avr-gcc package and update all the associated documentation. And you would have to convince Atmel or whoever is maintaining the AVR libC libraries and avr-gcc packages to do it since I doubt arduino developers would want to take on that task (assuming it is even possible). If you want to get a flavor of the technical possibility of doing what you are wanting, or to see if there is any other interest in it, I suggest that you venture over to the AVRfreaks site and start a thread over there. That is where the hardcore AVR tool folks and avr-gcc developers hang out. |
well, actually I have no idea HOW it could work, I'm just interested in THAT it does work how I stated: to optionally enable sprintf() for float formatting also on AVRs, as it always works on the Due, and especially just that for the Mega. As sprintf for floats is the standard in C (stdio.h), it would work always that way on either platform when stdio.h once was #included. OTOH, whoever needs a stripped-down, crippled formatting function on AVrs using less memory space, might #include a different stripped-down lib in his program, perhaps one could create a "avrio.h" lib for that purpose. Just in case, one was not enable to automatize that by #defines or #ifdefs or #pragmas or whatever by the wirng libs like
But in doubt, stdio.h is the standard and so sprintf should then work always like the standard, also for AVRs, not other way round. |
But you are asking for more than having float formatting in xxprintf() functions on AVRs optionally work. You are also asking for a capability that is not compatible with the way code is compiled and linked. |
then AVR programmers with a lack of RAM should #include a different lib without sprintf, Just in case no genius invents another more sophisticated method. |
@tofrnr This is not a RAM issue. This is not an issue using a library with or without sprintf() or even a sprintf() issue. Here is a link to the SVN repository so you can look at the xxprint routines for yourself: |
" the overhead would be undesirable for the smaller boards" |
sprintf() is a stdio.h function and must work as the default, i.e. providing floats formatting features. If one wants a crippled version for AVRs to save space, he must be able to use a different function with a minor functionality - either explicitely or automated by flags or #pragmas or #includes or whatever. But if one uses sprintf() he must be able to expect and to have (at least optionally) ALWAYS the full functionality, i.e. like described here:
|
But on AVR-GCC you are using this: http://www.nongnu.org/avr-libc/user-manual/group__avr__stdio.html#gaa3b98c0d17b35642c0f3e4649092b9f1 And all its variants/limitations are listed there. AVR-GCC is a non standard implementation because it does not support/contain many things such as a complete 'C++ standard library' or exceptions. It implies from the beginning that everything inside it might not be to standard, including the expectation for some difference in the things that are provided. |
But like I said earlier the space saved is in flash not ram as you said:
And you don't #include a library. That isn't how libraries and linking works. In terms of how reduced functionality in a function works:
That isn't how reduced functionality works. And the capability to use different versions of the xxprintf() code already exists. Compiler & linker flags are used to control which version of the xxprintf() code you get. There are different pre-compiled versions of the code and you use the compiler & linker flags to select which version you get. It is not possible to select which library object is used from a source module.
So being able to get nearly all the xxprintf() formatting capabilities ALL the time is already possible. You don't seem to like the way it works. The default version of the xxprintf() code selected at link time happens to be a reduced feature set with without floating point formatting because the vast majority of the users of this code have wanted it this way as it saves flash space. If you want to ALWAYS have floating point formatting capabilities go in and modify your build recipes for AVR builds. |
I don't feel like reading your posts as long enough to sink a ship. sprintf() is a standard C command provided by stdio.h, providing well-defined features OTOH: Whoever wants sprintf in Sketches must be able to have it, with full funcionality, even and especially with float formatting support, at any time. Finally this is standard C syntax. If it would be needed to #include stdio.h for that purpose, and no other magic automated way, ok, provide it by an explicite #include < stdio.h > Who might not want sprintf() because of memory reasons is not forced to #include stdio.h, then he can (and must ) do without sprintf and may save RAM. Anyway, sprintf() is expected to always being able to work standard-C-like, without compromising, at any time, for all processors, e.g. also for the MEGA, period. |
I have made an update to my library.
Prints:
This solves the problem using a single |
no, definitely: no extra lib! perhaps #include < stdio.h >, yes! sprintf from stdio.h is perfect, there is no need to change that. But what perhaps might have to be changed is: But don't ever mutilate the original sprintf() from stdio.h !!! (and BTW, I never use the library manager, it always muddles everything up. I just copy libs manually to the Arduino libs folder) |
@tofrnr
For example, if you were not using the Arduino IDE, and using makefiles instead, then changing the compiler and linker flags would be trivial as you could go in and modify the makefile for that sketch. And you keep shifting between what you want.
and
and in other cases you say you want to be able to control the capabilities of what is in the sprintf() code based on flags inside the application module:
and
You can't have it both ways and because of this, it is very difficult to have a technical conversion. The reality is that the way compilers and linkers work and the way the avr-gcc package is put together, it includes different pre-compiled versions of the xxprintf() code and you tell the linker which one you want. The default happens to be a reduced functionality version but that can easily be changed by using compiler & linker flags. The Arduino IDE currently has no way to set those compiler & linker flags from the GUI as a configuration option similar to the way it can set the compiler warning flags through a "verbose" mode option. In the absence of having a IDE configuration option to set these flags from the GUI, And then when @Chris--A offered a simple solution that offered EXACTLY what you asked for in your original post,
to give you full sprintf() support by simply including a header file. You don't like the way things currently work, but you don't seem to want to change anything to get the capabilities you want. Well, the reality is that unless you install a different or additional library or specify some command line options you can't get a different version of sprintf() than the default which is current the reduced capability sprintf() without floating point formatting support. You seem to have some desires to do things in ways that are not supported by the existing tool sets. But I think it would be much simpler and whole lot less work, to simply reconfigure a few small things to get the desired capabilities. If you feel strongly enough about it, then by means go over to AVRfreaks site: |
I didn't read your novel, it's simply too many words - just this: The reaseon why I don't like the idea of printEx which mimics stdio.h is that I am extremely skeptical if it will really objectively mimic all and everything of the stdio.h features then too, additionally, like listed here: But at long last, Arduino simply must not mutilate standard C functions and then keep it in that crippled version. i.e., stdio.h functions must provide all stdio.h functionalities! If Arduino wants to provide mutilated functions, then Arduino must call them differently or build in a compiler switch that one is able to switch between the full and the mutilated version. In that case it means:
|
@tomfmr And now I'm out as this discussion is not advancing and is simply spinning in circles. |
As I mentioned earlier, it would be possible to set the needed compiler/linker options from the GUI just like there is way to set the compiler options to turn on more verbose warnings. It is a small change and should be fairly isolated. The GUI could also be changed to have a text box where the user could optionally type in additional desired command line arguments. Perhaps a couple of different boxes for the different tools (pre-processor, compiler, linker, etc...) This method could be used for other things besides just the selection of which xxprintf() routines to use. |
yes, that sounds promising! |
@tofrnr |
a way to perhaps resolve this issue from out of the GUI / IDE. |
I suggested that earlier in my first response in this issue/thread (a toggle to enable/disable the floating point formatting on AVR processors) but you rejected it because it didn't (couldn't) provide a mechanism to do the selection from the source code modules. |
"How to do the impossible" a.k.a.
|
bperrybap, I am a hobbyist and simply could not imagine to do that configuration/switching from out of the IDE unless then doing it out of the source code. Anyway, I'm gladly looking forward! |
@oqibidipo It seems like a lot of work when there are other alternatives that already work with existing IDE versions that could offer what is needed (possibly not all of what is wanted) at a much lower development and support cost that don't wonk up the IDE code with new Arduino specific pre-processing extensions. I think a better option (and probably the best at the current time) for the majority of users would be to simply include something like the board type menu extensions you proposed earlier in the stock AVR boards.txt file that comes with the IDE. This would give the user build control over which xxprintf() code to use using menus in the IDE GUI when building the sketch on all the AVR based arduino boards that arduino.cc includes in the IDE "out of the box". Using the menu capability in board types requires no changes to any IDE code and offers the user the ability to select the desired xxprintf code to use from a simple GUI selection menu when he selects the target board for the build. In the mean time, users could add it to their boards.txt file themselves. it takes just a minute or so and would be a simple cut and paste operation. Baring that, using the PrintEx library offers and easy way to get better sprintf() or even a printf() method within a device library class on a per sketch basis. |
Just for the record, #PRAGMA is exactly the way you control compiler flags from a source file but it is up to the compiler to support it. HOWEVER, IMHO it is probably best to control it from a build system of some sort not the source file. @oqibidipo Thank you very much for this solution Risto, it appears to work great on Arduino IDE 1.8.2 / Linux Mint / Mate / JDK 8 |
@Sonophoto |
@bperrybap -L -l and -Wl<,linker,options> are gcc compiler flags that control the linker. You did not offer the solution (!?) not sure where you came up with that idea. @oqibidipo offered the correct solution for the Arduino IDE and it was posted a day before you entered the conversation. |
technically "gcc" is really a wrapper not the actual compiler. gcc typically invokes the pre-processor, the compiler and the linker. |
@bperrybap You just have to keep fucking arguing don't you? Giving everyone a hard time, trying to act like you have some unique technical knowledge the rest of us don't have or that the rest of us don't really know what is going on. |
as to me, patching system files are not very much appreciated, because for every IDE update everything had to be patched again. |
@tomFr, I think an easy alternative solution that works quite well with Arduino and the existing Arduino IDEs is to use the PrintEx library as originally suggested quite some time ago. |
it' because I write code which is intended to work both for the Due and for the Mega and for esp8266 (and perhaps in future also for the M0 pro), using float-to-string formatting by sprintf as already provided for the Due. The Due does not require PrintEx, the Mega works faulty for floats, for the esp8266 it's probably not fixed yet and I'm no quite sure about the M0 pro. |
The AVR sprintf() code is not faulty for floats. The avr-gcc AVRlibc supports configuring which xxprintf() code is linked in. By default it links in a smaller reduced functionality version because many of the AVR chips are very code limited and the majority of users wanted it that way. While it is configurable, you can't configure it from the Arduino IDE. We have to keep in mind that avr-gcc is outside the control of Arduino. While we can ask for some kind of support to be added to the Arduino IDE GUI to configure AVR xxprintf() support, that may be a long time coming. Until there is something else, you will have do something to get floating point support.
Given your new stated goal/requirements of always wanting full xxprintf() support, I'd recommend that you go in and patch the AVR platform.txt file to default to the full xxprintf() code and be done with it. |
as already stated, I do not want to patch system files or create board types, that is too cumbersome. |
It seems like this discussion is getting really redundant (and some of it was already gone over years ago in arduino/Arduino#1719). Please keep it productive or I'll need to lock the thread. Saying the same things over and over is just a waste of time. |
@pert234 I totally agree. |
I don't see why it shouldn't be possible to choose the libs I want to use by simple #includes: so if there is low space at a certain cpu (e.g., Uno) it should be possible to have a restricted stdio lib version, and then just If I do that by my gcc for Linux, then I do not even need a linker flag for those standard lib functionalities, I just use But even if a linkerflag was needed additionally like for wiringPi.h in my example above, why couldn't that flag (e.g., -lwiringPi) be added then by the IDE either automatically or by a setting in preferences, depending on the required lib name ? That that would be "WAY outside the scope and control of Arduino" is honestly WAY beyond my scope of understanding. |
@tofrnr includes are not linker flags; if you want a constructive discussion, please keep quiet. diff --git a/platform.txt b/platform.txt
index 16c25b1..729b426 100644
--- a/platform.txt
+++ b/platform.txt
@@ -65,7 +65,7 @@ archive_file_path={build.path}/{archive_file}
recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{archive_file_path}" "{object_file}"
## Combine gc-sections, archives, and objects
-recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} -mmcu={build.mcu} {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" {object_files} "{build.path}/{archive_file}" "-L{build.path}" -lm
+recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.flags} -mmcu={build.mcu} {compiler.c.elf.extra_flags} -o "{build.path}/{build.project_name}.elf" {object_files} "{build.path}/{archive_file}" "-L{build.path}" {compiler.ldflags} -lm
## Create output files (.eep and .hex)
recipe.objcopy.eep.pattern="{compiler.path}{compiler.objcopy.cmd}" {compiler.objcopy.eep.flags} {compiler.objcopy.eep.extra_flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.eep" Unfortunately, the current If you want to push for the patch to enter mainline, test it, report your findings and contribute to the discussion, thanks. |
What?? All I said was that some #includes of libs work without any additional linker flag by gcc/g++ (e.g., stdio.h or iostream) , while some other #includes of libs do need additional linker flags (like for the wiringPi lib example) in order to locate the libs , to link them and "make" the executable. And I said that choosing a arbitrary lib functionality is normally possible by |
It would be good if you could choose this using a If Arduino starts supporting custom, per-sketch compiler options (which it should at some point, but is non-trivial, and not the topic of this issue), enabling float support could be made convenient. Until then, some workarounds have been shown in this issue, feel free to use any of them. As @per1234 indicated, this issue is repeating arguments and not progressing anymore. Since @tofrnr is coninuing to repeat things again, I'll go ahead and lock this issue from further discussion. |
@sandeepmistry, I think this issue should be moved to ArduinoCore-avr. |
could we finally have sprintf for floats on Arduino Mega?
enabled perhaps by a #include or by a #pragma config
The text was updated successfully, but these errors were encountered: