While stdio and hence printf() isn't built into the Arduino environment, there are several
ways to get xxprintf() type output support in the Arduino environment.
Each way has its pluses and minuses.
The alternatives include:
See the printf man page for details on how to build format strings.
While xxprintf() routines are very convenient for formatting output, it comes with a cost of added code size.
Also note that by default the Arduino IDE does not set the AVR linker options to support floating point in the xxprintf() routines. So while that saves quite a bit of code space on the AVR builds, it means that printf() functions cannot be used for floating point output on the AVR. Floating support is included by default for the other processors.
The advantage of adding printf() to the Print class is that once added,
it will transparently add printf() to all the device classes for any CPU archtecture that use the Print class.
i.e. once it is done, nothing else has to be done on any device that uses the Print class. This allows it to be easily used on lcds, HardwareSerial, SoftSerial, etc... with no modification to any other files. The sketch code can use it by simply referencing the device class object directly:
lcd.printf("Hello World"); Serial.printf("Hello World\n"); SoftSerial.printf("Hello World\n"); Serial.printf("Value is:%3d\n"), value);
It can also transparently support using the F() macro to put the printf() formatting strings into flash.
Serial.printf(F("Hello World\n")); Serial.printf(F("Value is:%3d\n"), value);
The disadvantage is that it requires modifying each of the Arduino system Print class header files, which exists in each CPU architecture core directory and also requires using a hidden temporary buffer.
Note that the addtional code space for the printf() code is not used unless the printf() function is used.
Similar to adding printf() support to the Print class Creating a wrapper function for each device has the advantage of working on any CPU architecture but has the disadvantages of requiring a seperate wrapper for each device class.
Hooking into the libC embedded stdio support has the advantage
of actually making the printf() function work.
The disadvantage is that the sketch usually has to be involved with setting up the stdio linkage with custom code for each device class to make it work, and the code to make it work will be different for each cpu architecture toolset. So for example using Arduino AVR with serial vs USB will be different, vs Teensy AVR serial/USB, vs DUE ARM, vs Teensy3 ARM, vs chipkit etc...
To add printf() support to the Print class you must modify the Print class header file. Because of the way the Arduino code is built, each core has its own Print.h header file, so you will have to modify the Print.h header file for each architecture that you want to add printf() support into the Print class. Here is the location of where the Print.h header files can be found:
Insert the following code into the Print.h header file. The code must be inserted into the Print class definition. Just copy and past this code into the bottom of the public section.
Once this is inserted into the Print class header, sketches can
use printf() functionality by simply referencing the function in the device object.
This function emulates the stdio.h printf() functionality in C and will send the output to the Serial connection using Serial.print(). The resulting string sent over serial is limited to 128 chars.
See the sprintf man page or the examples herein for details on how to build format strings.
If anyone has a better version please feel free to remove or edit this version.
You can also avoid using Serial.print() altogether and redirect STDIN and STDOUT to UART.
The avr-gcc C library, avr-libc, provides the printf() family of functions. You can use them in Arduino sketches after some preparation. General details are in the avr-libc documentation for file stdio.h. These notes are specific to the Arduino development environment.
printf() makes your executable object ~1000 bytes larger, so you may not want to use it if size is a problem.
If you can define a character-based output function and reference it in a FILE structure, you can use fprintf() as well. An example for an LCD shield follows below.
Using Flash Memory for string storage
Version 1.0 of the Arduino IDE introduced the F() syntax for storing strings in flash memory rather than RAM. e.g.
The same result can be achieved with printf by using the _P versions of printf, fprintf, etc and wrapping your string in the PSTR() macro. You'll need to #include <avr/pgmspace.h>, e.g.
Using flash memory this way only works for the format string. If you include a string (%s) in your format you'll need to pass a regular string, e.g.
Tweaked version of the above example using printf_P:
I've tweaked the previous example to use regular integers rather than floating point values. My environment (Ubuntu Linux 10.04, Arduino IDE 1.0) doesn't include support for floating points (%f) by default when compiling printf support. According to notes in stdio.h it's possible to change this behaviour by passing gcc extra parameters. I'm not sure if this limitation applies to Windows and OSX environments.