StreamLib Very much like sprintf

Hi,
I've tried to get C like printf capability use in arduino. I've added printf to AVR as per arduinoplayground instructions to get sprintf capabilities using Serial.printf() . This is good but floats and strings (%f,%s)
are a problem (as with sprintf).
I copied the StreamLib files from GitHub - JAndrassy/StreamLib: Arduino library with Stream helper classes. BufferedPrint stream for efficient networking. ChunkedPrint for HTTP chunked encoding. ChunkedStreamReader for HTTP chunked decoding. CStringBulder builds a c-string with Print class methods. StringReadStream to wrap string as Stream. And printf() function with formatting string from F macro. to realize similar printf limitations as sprintf except %s is allowed, and %d int's rollover above 2^16 (like mod math) VS going negative.

So to do something like myprintf"PI.6~%8.6f\n",PI; PI.6~3.141593

New C++ code needs to be written to introduce a new library class. Not sure I've stated this correctly I'm in the process of learning C++ . The plan would include the rest of C's printf capabilities.
thanks,
Keith

Hi,
I'm trying to avoid doing anything new or creative. did you try your first suggestion ?

I've not used dtostrf and like it. But it is same as Serial.println(PI,6);  Can use up to (PI,7); we do get more sig figs using dtostrf or String(PI,7)  than sprintf, however; sprintf does not allow %s
There isn't %E capability above either. Nor is it compact like myprt("PI.7~",%9.7f);
[code[/*
testing sprintf %f
*/

void setup(){
Serial.begin(9600);
char myArray[9];
char buf[80]={'\0'};
sprintf (myArray, "%.6f", PI);
Serial.println(myArray);
Serial.println(dtostrf(PI,  8, 6, myArray));

Serial.println(dtostrf(PI,10,7,buf));
Serial.println(dtostrf(PI,10,8,buf));
Serial.println(PI,7);
Serial.println(PI,8);
Serial.println("");
Serial.print(String("PI.7~"+String(PI,7)));

            }
void loop() {
            }
// PI~3.14159265359
// OUTPUT:
//?
//3.141593
//3.1415927
//3.14159270
//3.1415927
//3.14159274
//
//PI.7~3.1415927

Hi,
I have not moved the goal posts. The first sentence of my initial post:
I've tried to get C like printf capability use in arduino.

The unseen myprt("PI.7~",%9.7f); is C
myprt was used because printf is also part of arduino.
//PI is not defined in c
float pi=3.14159265359;
printf("PI.7~%9.7f",pi);
//will print->PI.7~3.1415927

I meant %s
I've tried to use %s in sprintf w/o success

String mys=" STRING";
sprintf(buf,"The string is %s\n",mys);

to get error:

:\Arduino\format_print\test\test.ino: In function 'void setup()':

test:20: error: cannot pass objects of non-trivially-copyable type 'class String' through '...'

 sprintf(buf,"The string is %s\n",mys);

                                     ^

exit status 1
cannot pass objects of non-trivially-copyable type 'class String' through '...'

You claim %f can be used in sprintf but has been removed for memory space reasons.
What needs to be done to utilize your first suggestion: sprintf (myArray, "%.6f", PI); ?
I would like to realize this memory impact.

StreamLib's ForrmattedPrint uses the same underlying printf implementation for AVR like you added to Print

btw: do you know what is Library Manager? saves time with library installation

Delta_G:
Only in Arduino-land would someone think that, "Copy this folder into that folder" would need to be automated to "save time".

copy? navigate to github page, download zip, open it, navigate to libraries folder, copy from zip to libraries, rename the folder

myprt DNE ; myprt is the C printf mimic I'd like to use in arduino.
myprt was used so it would not be confused with arduino printf.

printf in arduino is accepted (printf("PI.7~9.7f",PI):wink: where does the output go?
can io redirection be used with, printf("PI.7~%9.7f",PI); , to print to the serial monitor?
printf("PI.7~%.7e",PI); also OK
If it is re-directed to the serial monitor will it print "?" ?

klong84:
myprt DNE ; myprt is the C printf mimic I'd like to use in arduino.
myprt was used so it would not be confused with arduino printf.

printf in arduino is accepted (printf("PI.7~9.7f",PI):wink: where does the output go?
can io redirection be used with, printf("PI.7~%9.7f",PI); , to print to the serial monitor?
printf("PI.7~%.7e",PI); also OK
If it is re-directed to the serial monitor will it print "?" ?

https://www.nongnu.org/avr-libc/user-manual/group__avr__stdio.html

The first stream opened with write intent using fdevopen() will be assigned to both, stdin, and stderr.

What needs to be done to utilize your first suggestion: sprintf (myArray, "%.6f", PI); ?

You change the linker commands to NOT include the standard printf library (vfprintf) and instead include the printf library that has floating point support (vfprintf_flt)
There are a bunch of different ways to do this, which vary in how much trouble they are, how much impact they have on other platforms, how easy it is to select them, how likely they are to "disappear" when you do updates, and how well they keep up with updates, and which versions of the IDE they work with.
There's some discussion here: How to safely and reasonably convert a float or double to string or char array? - #31 by krupski - Programming Questions - Arduino Forum
Krupski has modified the IDE to include new options (which requires the ability to edit and compile the IDE sourcecode), and/or suggests that you simply overwrite the vprintf library with a copy of vprintf_flt instead (which is sort of heavy-handed - it'll affect many avrs at the same time.)

With recent versions of the IDE, the "proper" way probably involves creating a new "platform" (it probably SHOULD only require a new board type, but it looks like currently there is no way to have board-dependent linker options.)

You CAN modify the existing platform.txt and boards.txt for the avr, assuming that you can find them and have a reasonable editor. But this will disappear next time you update the avr board version...

Attached is a .diff file for changes that seem to work (tested, but not extensively.)

And a test program (also demoing an easy way to make printf() go to Serial:

#include <stdio.h>
int fput(char c, FILE* f) {
  Serial.write(c);
  return 0;
}

void setup() {
  Serial.begin(9600);
  while (!Serial)
    ;
  Serial.println("\ntesting testing testing");
  delay (5000);
  stdout = fdevopen(fput, NULL);
}

void loop ()
{
  Serial.println();
  long y = 1 << 31;
  int x = 1023;
  Serial.println ("TestStart\n");
  printf( "This is a test of something  %d  %ld\n", x, y);
  printf("This is a test of something float %f\n", PI);

  Serial.println("TestEnd\n");
  delay(10000);
}

Edit: Hmmph. .diffs files are not attachable. Here it is, inline.

*** platform.txt~	Mon Feb 19 03:27:22 2018
--- platform.txt	Wed Jun  6 00:29:25 2018
***************
*** 37,42 ****
--- 37,43 ----
  
  # This can be overridden in boards.txt
  build.extra_flags=
+ build.elf.extra_flags=
  
  # These can be overridden in platform.local.txt
  compiler.c.extra_flags=
***************
*** 65,71 ****
  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
  
  ## 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"
--- 66,72 ----
  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}" {build.elf.extra_flags} -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"
*** boards.txt~	Mon Feb 19 03:03:55 2018
--- boards.txt	Wed Jun  6 00:44:08 2018
***************
*** 46,51 ****
--- 46,84 ----
  
  ##############################################################
  
+ unoflt.name= Uno w float-printf
+ 
+ unoflt.vid.0=0x2341
+ unoflt.pid.0=0x0043
+ unoflt.vid.1=0x2341
+ unoflt.pid.1=0x0001
+ unoflt.vid.2=0x2A03
+ unoflt.pid.2=0x0043
+ unoflt.vid.3=0x2341
+ unoflt.pid.3=0x0243
+ 
+ unoflt.upload.tool=avrdude
+ unoflt.upload.protocol=arduino
+ unoflt.upload.maximum_size=32256
+ unoflt.upload.maximum_data_size=2048
+ unoflt.upload.speed=115200
+ 
+ unoflt.bootloader.tool=avrdude
+ unoflt.bootloader.low_fuses=0xFF
+ unoflt.bootloader.high_fuses=0xDE
+ unoflt.bootloader.extended_fuses=0xFD
+ unoflt.bootloader.unlock_bits=0x3F
+ unoflt.bootloader.lock_bits=0x0F
+ unoflt.bootloader.file=optiboot/optiboot_atmega328.hex
+ 
+ unoflt.build.mcu=atmega328p
+ unoflt.build.f_cpu=16000000L
+ unoflt.build.board=AVR_UNOFLT
+ unoflt.build.core=arduino
+ unoflt.build.variant=standard
+ unoflt.build.elf.extra_flags="-Wl,-u,vfprintf,-lprintf_flt "
+ 
+ 
  uno.name=Arduino/Genuino Uno
  
  uno.vid.0=0x2341
***************
*** 315,320 ****
--- 348,390 ----
  leonardo.build.core=arduino
  leonardo.build.variant=leonardo
  leonardo.build.extra_flags={build.usb_flags}
+ lenflt.name=Leonardo with float printf
+ lenflt.vid.0=0x2341
+ lenflt.pid.0=0x0036
+ lenflt.vid.1=0x2341
+ lenflt.pid.1=0x8036
+ lenflt.vid.2=0x2A03
+ lenflt.pid.2=0x0036
+ lenflt.vid.3=0x2A03
+ lenflt.pid.3=0x8036
+ 
+ lenflt.upload.tool=avrdude
+ lenflt.upload.protocol=avr109
+ lenflt.upload.maximum_size=28672
+ lenflt.upload.maximum_data_size=2560
+ lenflt.upload.speed=57600
+ lenflt.upload.disable_flushing=true
+ lenflt.upload.use_1200bps_touch=true
+ lenflt.upload.wait_for_upload_port=true
+ 
+ lenflt.bootloader.tool=avrdude
+ lenflt.bootloader.low_fuses=0xff
+ lenflt.bootloader.high_fuses=0xd8
+ lenflt.bootloader.extended_fuses=0xcb
+ lenflt.bootloader.file=caterina/Caterina-Leonardo.hex
+ lenflt.bootloader.unlock_bits=0x3F
+ lenflt.bootloader.lock_bits=0x2F
+ 
+ lenflt.build.mcu=atmega32u4
+ lenflt.build.f_cpu=16000000L
+ lenflt.build.vid=0x2341
+ lenflt.build.pid=0x8036
+ lenflt.build.usb_product="Arduino Leonardo"
+ lenflt.build.board=AVR_LENONARDO
+ lenflt.build.core=arduino
+ lenflt.build.variant=leonardo
+ lenflt.build.extra_flags={build.usb_flags}
+ lenflt.build.elf.extra_flags="-Wl,-u,vfprintf,-lprintf_flt "
  
  ##############################################################

klong84:
I've tried to use %s in sprintf w/o success

String mys=" STRING";

sprintf(buf,"The string is %s\n",mys);

So a C function does not know anything about a C++ object. No surprise there.

Let's give it something it understands, i.e. the address of the buffer used by the object:

sprintf(buf,"The string is %s\n",mys.c_str());

Muuuch better.

klong84:
myprt DNE ; myprt is the C printf mimic I'd like to use in arduino.
myprt was used so it would not be confused with arduino printf.

printf in arduino is accepted (printf("PI.7~9.7f",PI):wink: where does the output go?
can io redirection be used with, printf("PI.7~%9.7f",PI); , to print to the serial monitor?
printf("PI.7~%.7e",PI); also OK
If it is re-directed to the serial monitor will it print "?" ?

If you don't first use fdevopen to setup your io streams, printf goes to NULL and getc reads from NULL.

Well, what if code like this:

int main (void)
{
    init();
    Serial.begin (115200);
    STDIO.open (Serial);

    char buf [64];
    const char *str = "Hello there %s, how are you?\n";
    const char *name = "Arduino";
    const char *temperature = "%5.1f degrees C is %5.1f degrees F\n";

    double celcius;
    double fahrenheit;

    sprintf (buf, str, name);
    fprintf (stdout, "%s", buf);

    celcius = 37.0;
    fahrenheit = ((celcius * 1.8) + 32.0);

    sprintf (buf, temperature, celcius, fahrenheit);
    fprintf (stdout, "%s", buf);

    fprintf (stdout, "But it's easier to just printf.. as such: Deg F = %5.1f\n", fahrenheit);

    while (1);

}

...produced output like this:

[b]Hello there Arduino, how are you?
 37.0 degrees C is  98.6 degrees F
But it's easier to just printf.. as such: Deg F =  98.6
[/b]

...and that magic line [b]STDIO.open (Serial);[/b] could be used for ANY device (LCD, Serial, Ethernet server/client... anything)?

...and each stream (stdin, stdout and stderr) could all be set to different devices (for example, stdin and stdout for the main program, and stderr to an LCD or different serial port for debug diagnostics?

...and of course, all on an Arduino!

You could, of course, save a whopping 1572 bytes and live with results like this:

[b]Hello there Arduino, how are you?
    ? degrees C is     ? degrees F
But it's easier to just printf.. as such: Deg F =     ?
[/b]

Or worse, stumble around with dtostrf like everyone else tells you you MUST do, not to mention the absurdity of building up a single line of text with 5, 6 or more "Serial.print" statements (none of which will give you scientific notation NOR will it allow you to line up digits such as:

[b]   1.0
  10.0
 100.0[/b]

...without doing all kinds of BS like counting string lengths and adding the proper number of leading zeros (or spaces).

What do you think?

Yes, it can be done. Very simply. Very easily.

westfw:
There's some discussion here: How to safely and reasonably convert a float or double to string or char array? - #31 by krupski - Programming Questions - Arduino Forum
Krupski has modified the IDE to include new options (which requires the ability to edit and compile the IDE sourcecode), and/or suggests that you simply overwrite the vprintf library with a copy of vprintf_flt instead (which is sort of heavy-handed - it'll affect many avrs at the same time.)

My "heavy handed" method was meant to allow a person to do a "quick and dirty" test to see how the floating point code actually performed and was not meant as "the solution" to the problem.

For the newer IDE, all that's required is to edit one of the "recipe" files to use the float versions of the printf library.

Also note that there are TWO files involved... one that supports printf and one that supports scanf.

Almost nobody (as far as I know) needs or uses scanf, so if ONLY the printf float code is linked, you get all the printf functionality with only about 1.5K of extra load.

Getting back to editing the recipe file, that does work, but (at least as far as I'm concerned), there should be a quick and easy user preference checkbox to enable or disable the float code as desired.

When I'm working on a sketch and don't need float, all I do is "click it off" and I get my 1.5K back. If I need it, click it on. To have to edit a file each time I wanted to make the switch is (again IMHO) absurd.

This is my Preferences window (growing all the time! (click for full size):

opts.jpg

Concerning printf itself, using fdevopen is simple, but tricky. To get the results desired (for example, separate stdout and stderr), the fdevopen calls need to be made in the correct order. Also, to prevent memory leaks, streams and file pointers need to be both closed and NULL'd... again in the proper order.

I've written a tiny library which does this. It provides a pre-instantiated object (STDIO) and supports .open, .close and a few other useful but not often used functions. The pre-instantiated is OK because of course you need only one (and indeed can't use more than one!).

In fact, the nicest way to use it is to add the two files (.h and .cpp) to the main Arduino directory (that has wiring*, hardwareserial*, etc..) and then just #include it in Arduino.h.

Then it's always available and uses ZERO memory if it's not used. I even have it pre-load into Hardwareserial so that serial prints automatically work. All that's required is this:

// in .begin (at the very end of the function)
    STDIO.open (*this); // connect stdin/out/err to current serial stream

// in .end (at the very end of the function)
    STDIO.close(); // close standard streams

Using "*this" automatically connects it to the proper serial port. If you use "Serial3.begin", then printf is automatically connected to port #3.

To make it REALLY perfect, a slightly edited Print.cpp and Print.h needs to be used. This library does a few things such as PROPERLY handling the "\n" character so that you don't have to use "\r\n" every time. It also provides print_P (for progmem strings), print_E (for EEPROM strings) and properly handles and prints uint64_t and int64_t numbers and doesn't use a fixed buffer to do so.

The "printfloat" code is 100% backward compatible with the original, but it also supports an optional parameter to allow specifying the number string length (like printf does - enabling lining up the number columns properly).

The handling of "\r\n" is done in the (char) section of print - others such as the bare write() are not affected.

The printing from PROGMEM has been improved to handle printing strings that happen to lie past the 64K boundary (whereas before Arduino would just crash):

size_t Print::print_P (const void *str)
{
    size_t n = 0;
    char c;

#if defined (pgm_read_byte_far)
    while ((c = pgm_read_byte_far (str + n))) {
#else
    while ((c = pgm_read_byte_near (str + n))) {
#endif
        print ((char) c);
        n++;
    }

    return n;
}

Simple change, but it works.

It's kinda discouraging when these simple solutions are available, yet virtually every day I read some of the "knowledgeable" Arduino users telling n00bs "it can't be done" or "it takes gigabytes of extra flash".

Oh well, as they say "you can lead a horse to water - but you can't make him drink".

:frowning:

Haven't tried it, but ...

Pieter

Hi,
The forum was not available for sometime.
Yes I would like to use printf capabilities and hope to see the memory impact. There is no substitute for it that I've been made aware of.
I like what you've done krupski, and would like to duplicate same.
W/O making any other mods I tried the code you listed most recently. It failed but I thought I missed something so I went back to your post to alter "libprintf_flt.a" -> "libprintf_min.a" and use sprintf. This did compile and run but I got "?" in the output. I do see that libprintf_flt.a is twice the size of libprintf_min.a and indeed in the installdir:
C:/'Program Files (x86)'/Arduino/hardware/tools/avr/avr/lib/libprintf_min.a ==
C:/'Program Files (x86)'/Arduino/hardware/tools/avr/avr/lib/libprintf_flt.a
I must have missed something. I would like to be at the point of your last post, able to select whether floating point is desired or not (preferences). Code giving "?"

void setup (void) {
char buf [64];double value = 123.45678;
Serial.begin (9600);
sprintf(buf, "You should see a number here --> %7.3f\r\n", value);
Serial.print(buf);
sprintf(buf, "You should see a number here --> %.3e\r\n", value);
Serial.print(buf);}
void loop() {
            }
//Sketch uses 3382 bytes (1%) of program storage space. Maximum is 253952 bytes.
//Global variables use 266 bytes (3%) of dynamic memory, leaving 7926 bytes for local variables. Maximum is 8192 bytes.
//
// "libprintf_flt.a" -> "libprintf_min.a"
//Sketch uses 3406 bytes (1%) of program storage space. Maximum is 253952 bytes.
// Global variables use 266 bytes (3%) of dynamic memory, leaving 7926 bytes for local variables. Maximum is 8192 bytes.

// OUTPUT:
// You should see a number here -->       ?
// You should see a number here --> ?

klong84:
Hi,
The forum was not available for sometime.
Yes I would like to use printf capabilities and hope to see the memory impact. There is no substitute for it that I've been made aware of.
I like what you've done krupski, and would like to duplicate same.
W/O making any other mods

Not quite sure how you expected anything to work without "making any other mods" but here's something you can try. Not sure if it will work for you (can't test it here since I don't use the 1.8.5 IDE) but try this:

Locate the file "arduino-x.x.x/hardware/arduino/avr/platform.txt". In that file, at or near line #35, find a line that reads "compiler.ldflags=". Add this to that line: "-Wl,-u,vfprintf,-lprintf_flt' so that the final line looks like this:

[b]compiler.ldflags=-Wl,-u,vfprintf,-lprintf_flt

[/b]

Enter it EXACTLY as shown, save the file, then quit and restart your IDE. Now, using "sprintf" with the floating point formatting (i.e. %f) should work... at the expense of about 1.5K larger sketch.

Note that there is little to no correlation between the size of the library code and the size of your final Arduino code.

Your statement

I do see that libprintf_flt.a is twice the size of libprintf_min.a

...is irellevant.

Don't bother trying to use "printf" unless you install my "Stdinout" Arduino library... 'cause it won't work.

Hi krupski,
Thanks for responding. I do want C like printf capability use in arduino. What you have done is just that. And more, enabling floating point print via preferences should be arduino's default.

The size statement I made concerning libprintf_min.a and libprintf_flt.a in last post was just that observation. The hope was that should arduino see libprintf_min.a (the cp of libprintf_flt.a) I would get floating point capability.

The cp of libprintf_flt.a to libprintf_min.a is in place for the platform.txt modification:

ok> diff 'C:/Program Files (x86)/Arduino/hardware/arduino/avr/platform.txt' 'C:/Program Files (x86)/Arduino/hardware/arduino/avr/platform_org.txt'
35,36c35
< # change-krupski>compiler.ldflags=
< compiler.ldflags=-Wl,-u,vfprintf,-lprintf_flt
---
> compiler.ldflags=

I the previous code posted compiles and loads but unfortunately the same "?" print occurs.

I don't know that it matters so much but I'm using arduino ide 1.8.4

To use the print capability you've posted:
fprintf (stdout, "But it's easier to just printf.. as such: Deg F = %5.1f\n", fahrenheit);
is the goal.

in the IDE installation folder is the AVR package installed with IDE, but if you update the hw package, then it is installed into C:\Users<login>\AppData\Local\Arduino15\packages and used from there

Hi,
OK, looking in C:/Users/klong/AppData/Local/Arduino15 are files:
library_index.json package_index.json.sig preferences.txt
package_index.json package_index.json.tmp

I' not sure how they got there but all the edits I've made have been in: /'c:/Program Files (x86)'/Arduino

The changes made to libprintf_min.a :
cp libprintf_min.a libprintf_min_org.a
cp libprintf_flt.a libprintf_min.a
was performed in:
/'c:/Program Files (x86)'/Arduino/hardware/tools/avr/avr/lib

There are several places where this could be done:

ok> ff libprintf_min
'c:/Program Files (x86)'/Arduino/hardware/tools/avr/avr/lib/avr25/libprintf_min.a
'c:/Program Files (x86)'/Arduino/hardware/tools/avr/avr/lib/avr25/tiny-stack/libprintf_min.a
'c:/Program Files (x86)'/Arduino/hardware/tools/avr/avr/lib/avr3/libprintf_min.a
'c:/Program Files (x86)'/Arduino/hardware/tools/avr/avr/lib/avr31/libprintf_min.a
'c:/Program Files (x86)'/Arduino/hardware/tools/avr/avr/lib/avr35/libprintf_min.a
'c:/Program Files (x86)'/Arduino/hardware/tools/avr/avr/lib/avr4/libprintf_min.a
'c:/Program Files (x86)'/Arduino/hardware/tools/avr/avr/lib/avr5/libprintf_min.a
'c:/Program Files (x86)'/Arduino/hardware/tools/avr/avr/lib/avr51/libprintf_min.a
'c:/Program Files (x86)'/Arduino/hardware/tools/avr/avr/lib/avr6/libprintf_min.a
'c:/Program Files (x86)'/Arduino/hardware/tools/avr/avr/lib/avrtiny/libprintf_min.a
'c:/Program Files (x86)'/Arduino/hardware/tools/avr/avr/lib/avrxmega2/libprintf_min.a
'c:/Program Files (x86)'/Arduino/hardware/tools/avr/avr/lib/avrxmega4/libprintf_min.a
'c:/Program Files (x86)'/Arduino/hardware/tools/avr/avr/lib/avrxmega5/libprintf_min.a
'c:/Program Files (x86)'/Arduino/hardware/tools/avr/avr/lib/avrxmega6/libprintf_min.a
'c:/Program Files (x86)'/Arduino/hardware/tools/avr/avr/lib/avrxmega7/libprintf_min.a
'c:/Program Files (x86)'/Arduino/hardware/tools/avr/avr/lib/libprintf_min.a
'c:/Program Files (x86)'/Arduino/hardware/tools/avr/avr/lib/libprintf_min_org.a
'c:/Program Files (x86)'/Arduino/hardware/tools/avr/avr/lib/tiny-stack/libprintf_min.a

I'm usinf arduino mega 2560 rev3, should I have made this edit to one of the other places list
ed above (like one of the avrxmega[7:2] dirs) ?

klong84:
Hi,
OK, looking in C:/Users/klong/AppData/Local/Arduino15 are files:
library_index.json package_index.json.sig preferences.txt
package_index.json package_index.json.tmp

I' not sure how they got there but all the edits I've made have been in: /'c:/Program Files (x86)'/Arduino

The changes made to libprintf_min.a :
cp libprintf_min.a libprintf_min_org.a
cp libprintf_flt.a libprintf_min.a
was performed in:
/'c:/Program Files (x86)'/Arduino/hardware/tools/avr/avr/lib

There are several places where this could be done:

ok> ff libprintf_min

'c:/Program Files (x86)'/Arduino/hardware/tools/avr/avr/lib/avr25/libprintf_min.a
'c:/Program Files (x86)'/Arduino/hardware/tools/avr/avr/lib/avr25/tiny-stack/libprintf_min.a
'c:/Program Files (x86)'/Arduino/hardware/tools/avr/avr/lib/avr3/libprintf_min.a
'c:/Program Files (x86)'/Arduino/hardware/tools/avr/avr/lib/avr31/libprintf_min.a
'c:/Program Files (x86)'/Arduino/hardware/tools/avr/avr/lib/avr35/libprintf_min.a
'c:/Program Files (x86)'/Arduino/hardware/tools/avr/avr/lib/avr4/libprintf_min.a
'c:/Program Files (x86)'/Arduino/hardware/tools/avr/avr/lib/avr5/libprintf_min.a
'c:/Program Files (x86)'/Arduino/hardware/tools/avr/avr/lib/avr51/libprintf_min.a
'c:/Program Files (x86)'/Arduino/hardware/tools/avr/avr/lib/avr6/libprintf_min.a
'c:/Program Files (x86)'/Arduino/hardware/tools/avr/avr/lib/avrtiny/libprintf_min.a
'c:/Program Files (x86)'/Arduino/hardware/tools/avr/avr/lib/avrxmega2/libprintf_min.a
'c:/Program Files (x86)'/Arduino/hardware/tools/avr/avr/lib/avrxmega4/libprintf_min.a
'c:/Program Files (x86)'/Arduino/hardware/tools/avr/avr/lib/avrxmega5/libprintf_min.a
'c:/Program Files (x86)'/Arduino/hardware/tools/avr/avr/lib/avrxmega6/libprintf_min.a
'c:/Program Files (x86)'/Arduino/hardware/tools/avr/avr/lib/avrxmega7/libprintf_min.a
'c:/Program Files (x86)'/Arduino/hardware/tools/avr/avr/lib/libprintf_min.a
'c:/Program Files (x86)'/Arduino/hardware/tools/avr/avr/lib/libprintf_min_org.a
'c:/Program Files (x86)'/Arduino/hardware/tools/avr/avr/lib/tiny-stack/libprintf_min.a




I'm usinf arduino mega 2560 rev3, should I have made this edit to one of the other places list
ed above (like one of the avrxmega[7:2] dirs) ?

You don't need to copy any files over in the Arduino directory. You need to edit the "recipe" to use the floating point library. As I said, I don't use 1.8.5, so I don't know exactly where to place the edit.

Why in hell the Arduino devs won't make it a Preferences item is totally beyond me.

When I (rarely) use the IDE, I use 1.0.5 which I added options to. Indeed, all I use it for is the "compile" and "upload" feature - I don't write or edit source with it.

Anyway, all that needs to be done in ANY version of the IDE is simply to add a JAVA checkbox to Preferences and then add a few lines to the compiler JAVA file. Look how simple it is:

    ///////////////// this provides the floating point option /////////////////

    if (Preferences.getBoolean ("build.printf_floating_point")) {
        baseCommandLinker.add ("-Wl,-u,vfprintf,-lprintf_flt");
    }

    if (Preferences.getBoolean ("build.scanf_floating_point")) {
        baseCommandLinker.add ("-Wl,-u,vfscanf,-lscanf_flt");
    }

    ///////////////// this provides the floating point option /////////////////

Notice that there are separate options for "printf" and "scanf" since the "scanf" code is rarely used and uses up more program space.

Edit to add: Copying the float library over the top of the min library will do nothing since the min library is never linked into the code. You have to add it to the recipe file (not sure where... SOMEONE here surely knows?)

Check out this post: StreamLib Very much like sprintf - #23 by Juraj - Programming Questions - Arduino Forum

Windows puts stuff in strange places. Maybe you have to edit the recipe file in your own "users\name" directory. I don't use Windows, so I have no clue about that. In Linux, it's more straightforward.

klong84:
To use the print capability you've posted:
fprintf (stdout, "But it's easier to just printf.. as such: Deg F = %5.1f\n", fahrenheit);
is the goal.

Then use these two libraries:

Note that these need to be installed manually.

For the Print code, REPLACE your existing Print.cpp and Print.h with the new ones.

Hi,
OK I've re-set IDE files to their original, and proceeded to repeat the alterations this time to include replacing Print.h & Print.cpp with GitHub - krupski/Print: Improved Print functionality for Arduino (including stream support, print_P and related). and #included GitHub - krupski/Stdinout: Standard input/output/error support for Arduino to a sketch you've posted here.

/*
getting printf to work (krupski)
*/
#include <stdio.h>
#include <Stdinout.h>

int main (void) {
init();
Serial.begin (9600);
STDIO.open (Serial);

char buf [64];
const char *str = "Hello there %s, how are you?\n";
const char *name = "Arduino";
const char *temperature = "%5.1f degrees C is %5.1f degrees F\n";

double celcius;
double fahrenheit;

sprintf (buf, str, name);
fprintf (stdout, "%s", buf);

celcius = 37.0;
fahrenheit = ((celcius * 1.8) + 32.0);

sprintf (buf, temperature, celcius, fahrenheit);
fprintf (stdout, "%s", buf);

fprintf (stdout, "But it's easier to just printf.. as such: Deg F = %5.1f\n", fahrenheit);

while (1);

                }

OUTPUT:

Hello there Arduino, how are you?
    ? degrees C is     ? degrees F
But it's easier to just printf.. as such: Deg F =     ?

Script used to alter IDE, I visited each change to see that the "DO" did:

# listing of changes to comment in/out as desired
#       *            **           ***            **             *

# krupski printf must use #include Stdinout.h
# involves overwritting Print.h with krupski's modified Print.h
# involves overwritting Print.cpp with krupski's modified Print.cpp

###do
##cp C:/'Program Files (x86)'/Arduino/hardware/arduino/avr/cores/arduino/Print.h C:/'Program Files (x86)'/Arduino/hardware/arduino/avr/cores/arduino/Print_org.h
## above done in doit before
#ls -ls C:/'Program Files (x86)'/Arduino/hardware/arduino/avr/cores/arduino/Print*
#cp c:/Arduino/mylib/Print_krp.h C:/'Program Files (x86)'/Arduino/hardware/arduino/avr/cores/arduino/Print.h
#cp c:/Arduino/mylib/Print_krp.cpp C:/'Program Files (x86)'/Arduino/hardware/arduino/avr/cores/arduino/Print.cpp
#ls -ls C:/'Program Files (x86)'/Arduino/hardware/arduino/avr/cores/arduino/Print*
###undo
#ls -ls C:/'Program Files (x86)'/Arduino/hardware/arduino/avr/cores/arduino/Print*
#cp C:/Arduino/mylib/Print_org.h C:/'Program Files (x86)'/Arduino/hardware/arduino/avr/cores/arduino/Print.h
#cp C:/Arduino/mylib/Print_org.cpp C:/'Program Files (x86)'/Arduino/hardware/arduino/avr/cores/arduino/Print.cpp
#ls -ls C:/'Program Files (x86)'/Arduino/hardware/arduino/avr/cores/arduino/Print*
### WELL ? NOT!!!

#       *            **           ***            **             *
# Adding floatint point to sprintf
# looks like arduino has removed same for memory savings sake. Will overwrite
#  the mininal libprint with floating point libprint

###do
#ls -ls C:/'Program Files (x86)'/Arduino/hardware/tools/avr/avr/lib/libprintf_min*.a
#ls -ls C:/'Program Files (x86)'/Arduino/hardware/tools/avr/avr/lib/libprintf_flt*.a
#cp C:/'Program Files (x86)'/Arduino/hardware/tools/avr/avr/lib/libprintf_min.a C:/Arduino/mylib/libprintf_min_org.a
#cp C:/'Program Files (x86)'/Arduino/hardware/tools/avr/avr/lib/libprintf_flt.a C:/'Program Files (x86)'/Arduino/hardware/tools/avr/avr/lib/libprintf_min.a
#ls -ls C:/'Program Files (x86)'/Arduino/hardware/tools/avr/avr/lib/libprintf_min*.a
#ls -ls C:/'Program Files (x86)'/Arduino/hardware/tools/avr/avr/lib/libprintf_flt*.a

###undo
#ls -ls C:/'Program Files (x86)'/Arduino/hardware/tools/avr/avr/lib/libprintf_min*.a
#ls -ls C:/'Program Files (x86)'/Arduino/hardware/tools/avr/avr/lib/libprintf_flt*.a
#cp C:/Arduino/mylib/libprintf_min_org.a C:/'Program Files (x86)'/Arduino/hardware/tools/avr/avr/lib/libprintf_min.a
###Not working may have modified wrong libprintf file ...

#  Locate the file "arduino-x.x.x/hardware/arduino/avr/platform.txt".  In that file, at or near line #35, find a line that reads "compiler.ldflags=".  Add this to that line: "-Wl,-u,vfprintf,-lprintf_flt' so that the final line looks like this:
#compiler.ldflags=-Wl,-u,vfprintf,-lprintf_flt

###do
#ls  C:/'Program Files (x86)'/Arduino/hardware/arduino/avr/platform*.txt
#cp  C:/'Program Files (x86)'/Arduino/hardware/arduino/avr/platform.txt C:/Arduino/mylib/platform_org.txt
## edit  platform*.txt, replace line "compiler.ldflags= " with
## compiler.ldflags=-Wl,-u,vfprintf,-lprintf_flt
## write out to: C:/Arduino/mylib/platform_mod.txt
#cp  C:/Arduino/mylib/platform_mod.txt C:/'Program Files (x86)'/Arduino/hardware/arduino/avr/platform.txt
#diff C:/'Program Files (x86)'/Arduino/hardware/arduino/avr/platform.txt C:/Arduino/mylib/platform_org.txt

###undo
#cp  C:/Arduino/mylib/platform_org.txt C:/'Program Files (x86)'/Arduino/hardware/arduino/avr/platform.txt
# diff C:/'Program Files (x86)'/Arduino/hardware/arduino/avr/platform.txt C:/Arduino/mylib/platform_mod.txt

OK you reference this "recipe" . What is it?
There must more ingredients than those I've implemented.