When formatting serial output is a concern, it's worthwhile to download and use the Streaming.h
contributed library that adds some “syntactic sugar” to Arduino C. That is, at compile time it converts C++-like <<
Serial stream operators to Serial.print
statements, without increasing code size. If you don't have Streaming.h
installed, you can get Streaming5.zip
from arduiniana.org.
At present, Streaming.h
doesn't support setw()
and setfill()
, which in ordinary C++ set a field width and a fill character.
However, it does support four base-conversion specifiers, _HEX, _DEC, _OCT, and _BIN; a _FLOAT function with number of decimal places specified; and endl
.
Thus, to print “Your coordinates are -23.123456, 135.123456” one would write:
Serial << "Your coordinates are " << _FLOAT(latitude,6) << ", " << _FLOAT(longitude,6) << endl;
Note that unlike the String
class, use of Streaming.h
does not entail any dynamic memory management – everything it does happens at compile time – and it does not increase code size – it translates stream-style operations into ordinary .print()
and .println()
calls. It should result in somewhat smaller, faster, and more-robust code, by avoidance of String
. Use of dynamic memory on small-memory embedded systems can be problematic, and this avoids those problems.
Edit 1a: As Chris Stratton points out, Arduino floats don't support 9-digit precision. I think Arduino floating-point arithmetic is intended to comply with IEEE 754, which sets out standards to be used on modern computers that support floating-point arithmetic.
In the binary32 format used to implement IEEE 754 single-precision binary floating-point, significand precision is 24 bits. That equates to about 7.22 decimal digits (ie, 24*log₁₀(2)), so for simple calculations, 7-digit accuracy is realistic, more than that is not.
[Part of] Edit 1b: In the larger scheme of things perhaps there's no need to create and save a formatted string like that. It is not useful for computing – the float values are better for that. It is not needed for communication – another streaming write can be done.
Edit 2 [replaces most of 1b]: Streaming.h doesn't build any strings, but just delivers the text of its <<
-arguments character-by-character to a stream. However, a PString class at arduiniana can build strings from stream inputs, as in the following example code.
#include <Streaming.h>
#include <PString.h>
char buffer[28];
PString pstr(buffer, sizeof(buffer));
void setup() {
Serial.begin(115200);
pstr.begin(); // Empty the buffer
}
void loop() {
int first=50, second=100;
pstr.begin(); // Empty the buffer
pstr << 'X' << first << 'Y' << second << 'T';
pstr += " hihi ";
pstr << millis() << endl;
Serial << pstr;
delay(1000);
}
Here's what some of its output to Serial looks like:
X50Y100T hihi 263198
X50Y100T hihi 264199
X50Y100T hihi 265199
X50Y100T hihi 266201
X50Y100T hihi 267201
X50Y100T hihi 268201
What the sample of code does is first initialize a string buffer, then build part of a character string using streaming operator <<
, then part of it using concatenation, then some more with <<
, then print the string. Note that the strings involved here are in fixed buffers, rather than dynamically allocated buffers like the String class uses.
float
s? Most output text on a serial port; if you do not need to do numeric operations on the values, perhaps you should just treat them as text all the way through. Note that if you do usefloat
s, their precision is limited, which may well be the cause of what you are seeing with your fake test data.;
float
can incur a rounding error as large as half an ulp, or about 85 cm.message.c_str()
arduino.cc/en/Reference/CStr