0
Offline
Newbie
Karma: 0
Posts: 37
Arduino rocks
|
 |
« on: March 08, 2008, 11:53:18 pm » |
Hi. If anyone has use for a float to string conversion function that runs standalone, I uploaded one to the playground here http://www.arduino.cc/playground/Main/FloatToStringsave that file to a floatToString.h in your project directory and go to town. (On my mac, I have to restart Arduino before I can import the file in a pde). There is example/test code in the comments field at the bottom of the file. With this function, I have it require a char * buffer be passed in that it writes to. If I wanted to create a new string inside that function, and return that instead, I assume that woud require malloc? Anyways, I figured passing in a buffer from the location of your choice would be preferable anyway. Hope it comes in handy, and please let me know if you find any bugs! thanks, Tim
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Full Member
Karma: 0
Posts: 221
|
 |
« Reply #1 on: January 05, 2009, 02:44:05 pm » |
Hi, This is a useful function, but there appears to be a bug of not terminating the string properly when the output is "0". Try running this code: int K; float M; byte stepSize = 2; char test[20];
void setup() { Serial.begin(9600); Serial.println("Starting"); }
void loop() { for (K = 10; K >= -10; K--){ M = K/10.0; Serial.print(floatToString(test,M,0,7,true)); Serial.print(' '); Serial.print(floatToString(test,M,1,7,true)); Serial.print(' '); Serial.println(K, DEC); delay(100); } }
This is the correct output: Starting 1 1.0 10 1 0.9 9 1 0.8 8 1 0.7 7 1 0.6 6 1 0.5 5 0 0.4 4 0 0.3 3 0 0.2 2 0 0.1 1 0 0.0 0 -0 -0.1 -1 -0 -0.2 -2 -0 -0.3 -3 -0 -0.4 -4 -1 -0.5 -5 -1 -0.6 -6 -1 -0.7 -7
This is what you get instead Starting 1 1.0 10 1 0.9 9 1 0.8 8 1 0.7 7 1 0.6 6 1 0.5 5 05 0.4 4 04 0.3 3 03 0.2 2 02 0.1 1 01 0.0 0 -00 -0.1 -1 -01 -0.2 -2 -02 -0.3 -3 -03 -0.4 -4 -1 -0.5 -5 -1 -0.6 -6 -1 -0.7 -7
|
|
|
|
« Last Edit: January 05, 2009, 02:45:56 pm by zitron »
|
Logged
|
|
|
|
|
London
Offline
Faraday Member
Karma: 6
Posts: 6226
Have fun!
|
 |
« Reply #2 on: January 05, 2009, 03:25:17 pm » |
Its worth noting that Don Kinzer published a routine for creating strings from floating point values here: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1207226548/11#11Don's code is smaller although it does not have the minwidth and rightjustify arguments. I have seen this before and am curious, I notice that your code uses [glow]and[/glow] instead of [glow]&&[/glow] . [glow]not[/glow] instead of [glow]![/glow] , I was wondering why this syntax is used?
|
|
|
|
« Last Edit: January 05, 2009, 03:26:47 pm by mem »
|
Logged
|
|
|
|
|
0
Offline
Full Member
Karma: 0
Posts: 221
|
 |
« Reply #3 on: January 05, 2009, 04:07:59 pm » |
I notice that your code uses and instead of && . not instead of ! , I was wondering why this syntax is used? Heh I see you've highlighted the keywords, I had to read that sentence three times to correctly parse it ;D. I didn't even know you could use the keywords [glow]and[/glow] and [glow]not[/glow] in C! mem I think your code is probably better, but I really need the right justify function for my OSD, since it makes changing numbers much easier to read. I think I'll try to combine both codes to get what I want... Cheers, -Z-
|
|
|
|
|
Logged
|
|
|
|
|
Austin, TX USA
Offline
God Member
Karma: 3
Posts: 992
Arduino rocks
|
 |
« Reply #4 on: January 05, 2009, 04:53:41 pm » |
Mem, Those "and" and "or" keywords come from iso646.h, which is automatically included, ostensibly to help people with "international" or "non-QWERTY" keyboards. To me it seems more problematic than useful. See http://en.wikipedia.org/wiki/Iso646.h. Mikal
|
|
|
|
« Last Edit: January 05, 2009, 05:54:27 pm by mikalhart »
|
Logged
|
|
|
|
|
0
Offline
Full Member
Karma: 0
Posts: 221
|
 |
« Reply #5 on: January 06, 2009, 10:04:02 am » |
Hi, I've looked around the forum, but couldn't find a FloatToStr function that actually worked with out any bugs. - Tim's code has some problem displaying zero.
- Mem's code does not have proper rounding, does not allow setting text minimum width.
- Don's code also has some issues displaying zero and negative values
So I've combined mem's code with Tim's code, and a little bit from Don. This hopefully should work as a compact sprintf() replacement that has no bugs (famous last words  ). Maybe it can be more efficient, but I think it's pretty good. char * floatToString(char * outstr, double val, byte precision, byte widthp){ char temp[16]; byte i;
// compute the rounding factor and fractional multiplier double roundingFactor = 0.5; unsigned long mult = 1; for (i = 0; i < precision; i++) { roundingFactor /= 10.0; mult *= 10; } temp[0]='\0'; outstr[0]='\0';
if(val < 0.0){ strcpy(outstr,"-\0"); val = -val; }
val += roundingFactor;
strcat(outstr, itoa(int(val),temp,10)); //prints the int part if( precision > 0) { strcat(outstr, ".\0"); // print the decimal point unsigned long frac; unsigned long mult = 1; byte padding = precision -1; while(precision--) mult *=10;
if(val >= 0) frac = (val - int(val)) * mult; else frac = (int(val)- val ) * mult; unsigned long frac1 = frac;
while(frac1 /= 10) padding--;
while(padding--) strcat(outstr,"0\0");
strcat(outstr,itoa(frac,temp,10)); }
// generate space padding if ((widthp != 0)&&(widthp >= strlen(outstr))){ byte J=0; J = widthp - strlen(outstr); for (i=0; i< J; i++) { temp[i] = ' '; }
temp[i++] = '\0'; strcat(temp,outstr); strcpy(outstr,temp); } return outstr; }
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Full Member
Karma: 0
Posts: 221
|
 |
« Reply #6 on: January 06, 2009, 10:07:52 am » |
Usage: floatToString(buffer string, float value, precision, minimum text width) set minimum text width to 0 for no right justify. Example: #include <string.h>
int K; float M; byte stepSize = 2; char test[20];
void setup() { Serial.begin(19200); Serial.println("Starting"); }
void loop() {
for (K = 1000; K >= -1000; K--){ M = K/100.0;
Serial.print(floatToString(test, M, 0, 3)); Serial.print(' ');
Serial.print(floatToString(test, M, 1, 5)); Serial.print(' ');
Serial.print(floatToString(test, M, 2, 6)); Serial.print(' ');
Serial.print(floatToString(test, M, 3, 7)); Serial.print(' '); Serial.println(K, DEC); delay(10); } } Prints: ... 0 0.1 0.07 0.070 7 0 0.1 0.06 0.060 6 0 0.1 0.05 0.050 5 0 0.0 0.04 0.040 4 0 0.0 0.03 0.030 3 0 0.0 0.02 0.020 2 0 0.0 0.01 0.010 1 0 0.0 0.00 0.000 0 -0 -0.0 -0.01 -0.010 -1 -0 -0.0 -0.02 -0.020 -2 ...
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Newbie
Karma: 0
Posts: 5
|
 |
« Reply #7 on: January 25, 2009, 10:51:23 pm » |
hello zitron, I'm having rounding problems with your function. I did try to write my own ftoa function, but also have the same rounding issues as with your function. Check out this: Serial.println(floatToString(str, 32766.6613, 2,  ); Serial.println(floatToString(str, 32766.6613, 4,  ); Serial.println(floatToString(str, 1.6613, 4,  ); Serial.println(floatToString(str, -32766.1234, 2,  ); Serial.println(floatToString(str, -32766.1234, 4,  ); These are the results of your function: 32766.66 // CORRECT 32766.6621 // WRONG 1.6613 // CORRECT -32766.12 // CORRECT -32766.1230 // WRONG Errors are small and probably won't make much difference, but still annoys me for not knowing the cause. Any ideas?
|
|
|
|
|
Logged
|
|
|
|
|
Connecticut, US
Offline
Edison Member
Karma: 1
Posts: 1036
Whatduino
|
 |
« Reply #8 on: January 25, 2009, 10:53:56 pm » |
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Full Member
Karma: 0
Posts: 221
|
 |
« Reply #9 on: January 27, 2009, 12:07:00 am » |
Hi gui, Thanks for pointing out the mistake. I found out that there is a problem in the my function. Because the function itoa is used to convert numbers, and it is a integer (16bit) function, so there is a problem when you specify precision > 4 digits, the function therefore only works for values less than xxxx.xxxx. I have modified it so that it uses ltoa instead, which uses long integers, so that should be plenty of digits. I'm also pretty much rewritten the function, so now it should be smaller and more efficient. char * floatToString(char * outstr, double val, byte precision, byte widthp){ char temp[16]; //increase this if you need more digits than 15 byte i;
temp[0]='\0'; outstr[0]='\0';
if(val < 0.0){ strcpy(outstr,"-\0"); //print "-" sign val *= -1; }
if( precision == 0) { strcat(outstr, ltoa(round(val),temp,10)); //prints the int part } else { unsigned long frac, mult = 1; byte padding = precision-1; while (precision--) mult *= 10;
val += 0.5/(float)mult; // compute rounding factor strcat(outstr, ltoa(floor(val),temp,10)); //prints the integer part without rounding strcat(outstr, ".\0"); // print the decimal point
frac = (val - floor(val)) * mult;
unsigned long frac1 = frac;
while(frac1 /= 10) padding--;
while(padding--) strcat(outstr,"0\0"); // print padding zeros
strcat(outstr,ltoa(frac,temp,10)); // print fraction part }
// generate width space padding if ((widthp != 0)&&(widthp >= strlen(outstr))){ byte J=0; J = widthp - strlen(outstr);
for (i=0; i< J; i++) { temp[i] = ' '; }
temp[i++] = '\0'; strcat(temp,outstr); strcpy(outstr,temp); }
return outstr; }
|
|
|
|
|
Logged
|
|
|
|
|
Orygun
Offline
Full Member
Karma: 0
Posts: 195
Don't let the smoke out!
|
 |
« Reply #10 on: April 14, 2009, 08:41:55 pm » |
Would this be valid documentation for use of this function to add to the top of floatToString.h ? Please correct where needed. /* * floatToString.h * * Usage: floatToString(buffer string, float value, precision, minimum text width) * * Example: * char test[20]; // string buffer * float M; // float variable to be converted * // precision -> number of decimal places * // min text width -> character output width, 0 = no right justify * * Serial.print(floatToString(test, M, 3, 7)); // call for conversion function * */
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
Full Member
Karma: 1
Posts: 137
|
 |
« Reply #11 on: December 10, 2009, 02:39:12 pm » |
capt.tagon Good hint making understanding that stuff easier for a beginner!
|
|
|
|
|
Logged
|
|
|
|
|
0
Offline
God Member
Karma: 0
Posts: 592
|
 |
« Reply #12 on: December 10, 2009, 04:38:07 pm » |
|
|
|
|
|
Logged
|
I'm an electrical engineering student. I designed the USnooBie (V-USB dev kit) which is sold at Seeed Studio 
|
|
|
|
0
Offline
Full Member
Karma: 0
Posts: 221
|
 |
« Reply #13 on: January 19, 2010, 12:10:19 pm » |
Crap frank. :  Didn't know it existed! Seriously, just use: #include<stdlib.h> dtostrf(FLOAT,WIDTH,PRECSISION,BUFFER); It's 20% smaller than my floatToString(), and probably faster as well.
|
|
|
|
|
Logged
|
|
|
|
|
|