To format output you need to use sprintf to put the formatted text in a buffer then use the normal Serial.print commands to output the buffer. You cannot include formatting commands within the Serial.print commands.
You can influence the output of Serial.print a small amount by using parameters after the value to be printed
Serial.print(variable, HEX);
will print the value of the variable in HEX, for instance and you can also include \t, \n and \r in strings to give a tab, newline and carriage return respectively.
Conversion is done in the format "[-]d.ddd". The minimum field width of the output string (including the '.' and the possible sign for negative values) is given in width, and prec determines the number of digits after the decimal sign. width is signed value, negative for left adjustment.
The dtostrf() function returns the pointer to the converted string s.
To save code space the the Arduino version of printf, and hence sprintf, does not include the functionality to output floating point values. Sorry to have got your hopes up.
What you wanting it support for the std C library function printf() to be supported by the Print class.
The Print class is what implements the character output within the Serial object.
The modifications to the code to add it isn't that difficult,
however it requires modifying the Print class code that the Arduino team provides
in their core code.
One of the drawbacks of the xxprintf() routines mentioned by others is the lack of floating point support.
Actually, there is floating point support in the AVR libC library xxprintf() functions, it is just that by default
the xxprintf() routines linked in have floating support removed to save code space.
To enable floating support requires using a different version of the xxprintf() routines which requires
setting a linker option to use a different library. And that is where the problem is, the standard/stock IDE currently
does not provide a way to set the command line options to the linker to specify the floating version of the libraries.
(The IDE has the linker options hardcoded inside the java code)
There is a way to patch your libraries and even some other versions of the IDE floating around that have
been patched to allow setting the linker option from the GUI.
If you search around you can find them.
As an alternative, you can use a wrapper with some clever gcc macros
to provide some simple printf() support for your code.
You will still have to live with the floating point deficiency unless you patch your libraries or
get the IDE that allows setting the linker option.
I have attached example code of how to do this.
This code will create a Printf() function that not only supports printf() capability on the serial port, but also
will automagically move your formating strings to progmem space so it does not eat up precious RAM.
What is the max value of hours and mins? Using multiplication, division and remainder may not be the most elegant solution (and my example below is pretty awful) but should be fast.
float val = 4.5
int ival = int(val * 10.0);
char buf[4];
sprintf(buf, "%d.%d", ival/10, ival%10);
kyrpav:
I am sure that i miss something here any help?
Make yourself these two files and #include them in your sketch:
stdinout.cpp
#if ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
#include <stdio.h>
#include <stdinout.h>
// Function that printf and related will use to print
static int serial_putchar(char c, FILE *f)
{
if(c == '\n') {
serial_putchar('\r', f);
}
return Serial.write(c) == 1 ? 0 : 1;
}
// Function that scanf and related will use to read
static int serial_getchar(FILE *)
{
// Wait until character is avilable
while(Serial.available() <= 0) { ; }
return Serial.read();
}
static FILE serial_stdinout;
static void setup_stdin_stdout()
{
// Set up stdout and stdin
fdev_setup_stream(&serial_stdinout, serial_putchar, serial_getchar, _FDEV_SETUP_RW);
stdout = &serial_stdinout;
stdin = &serial_stdinout;
stderr = &serial_stdinout;
}
// Initialize the static variable to 0
size_t initializeSTDINOUT::initnum = 0;
// Constructor that calls the function to set up stdin and stdout
initializeSTDINOUT::initializeSTDINOUT()
{
if(initnum++ == 0) {
setup_stdin_stdout();
}
}
stdinout.h
#ifndef _STDINOUT_H
#define _STDINOUT_H
// no need to make an instance of this yourself
class initializeSTDINOUT
{
static size_t initnum;
public:
// Constructor
initializeSTDINOUT();
};
// Call the constructor in each compiled file this header is included in
// static means the names won't collide
static initializeSTDINOUT initializeSTDINOUT_obj;
#endif
This gives you stdin, stdout and stderr.
So, now "printf" and "fprintf(stdout, ..." will work, as will getc, putc, gets, puts, etc...
Be aware though that the %f format will not work because the Arduino IDE doesn't include floating point support to save sketch size. If you want to add the ability to enable or disable floating point support (via a checkbox in File / Preferences), grab this file: https://github.com/krupski/arduino-1.0.3/blob/master/app/pde.jar (click on "view raw" to download it), then REPLACE your arduino-1.0.x/lib/pde.jar with the downloaded version. Be sure to make a backup copy of your original pde.jar file, just in case!
Note that enabling floating point support will make your sketch about 1.5K larger, so leave it disabled unless you need it.
Of course you could use something simple like this.
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
float f = 1.1;
Serial.print("report at ");
Serial.print(f,2);
Serial.println(" toaday");
}
I've never understood the atraction to C++ streaming i/o.
I simply fail to see how C++ i/o streaming is simpler than simple xxprintf format strings.
Consider these simple examples:
printf("High Score: %04d", score);
printf("Time: %02d:%02d.%02d", hour, min, sec);
printf("Voltage: %04.2fv", volts); // volts is a float
These types of things are not easy to do with C++ streaming i/o
but are trivial to do with xxprintf() formatting strings.
It does to stdout.
As long as you set up your stdout it will go wherever you want
(A serial port, an lcd, a graphical LCD, etc...)
In my case I didn't actually use printf() because I wanted some additional
functionality.
The printing line outputs things in sequence, it's pretty easy to follow, and to write. You don't need an external buffer to "sprintf" into.
The biggest issue that I have with C++ stream i/o is, that it can't format the text like in the examples I showed
that used xxprintf() formatting.
Things like 0 (zero) filling or space/width padding on numbers or strings are not so easy with stream i/o.
As far as an external buffer goes, when things are setup correctly, you won't need an external buffer because
you won't be using sprintf().
One of the things I really like about the Printf() function/wrapper example I provided earlier is that
it also pushed all the literal strings into AVR progmem automatically without the user having to know
or deal with it.
There are so many macro wrappers that can be done when using xxprintf() routines to
aid in debugging because of the variable argument methodology of the xxprintf() routines.
For example, with a simple single macro change, you can have all your debug output now include the
file name and line number within your code or make all the debug output completely disappear
or like in the example I provided, even automatically push all the formatting strings into AVR progmem.
This kind of stuff is difficult if not impossible with stream i/o.
bperrybap:
One of the things I really like about the Printf() function/wrapper example I provided earlier is that
it also pushed all the literal strings into AVR progmem automatically without the user having to know
or deal with it.
...
This kind of stuff is difficult if not impossible with stream i/o.
You can keep the literals in program memory:
#include <Streaming.h>
int hour = 5, min = 23, sec = 14;
void setup ()
{
Serial.begin (115200);
Serial << F("Time: ") << hour << F(":") << min << F(":") << sec << endl;
} // end of setup
void loop () { }