ftoa() ??? Does it work, or...

does it maybe, perhaps, have a tendency to drop the first zero after the decimal point?

I've been blaming my analog sensor circuits for not being accurate.

I've been blaming my math - and proper use of the (float) - for why SOMETIMES I am not receiving the number my meter says I should expect.

My sensor readings should be accurate to AT LEAST one decimal place.
I'm using the Virtual Wire library to send the data. It needs characters.

I'm starting to strongly suspect that the reason a number that should be something like '9.08' is being transmitted as '9.8', is because ftoa() is screwing up. ( I say 'should be' because my data source is always fluctuating - I don't REALLY know what it is.)

Is that possible? Or have I not got enough sleep - again. :wink:

Here's the function. And no, I did not write it. I copied it from a program a friend sent me. I don't think he wrote it. I don't know who to give credit to.

char *ftoa(double f, char *a, int precision) { // Convert float to ascii!
long p[] = {0,10,100,1000,10000,100000,1000000,10000000,100000000};
char *ret = a;
long heiltal = (long)f;
itoa(heiltal, a, 10);
while (*a != '\0') a++;
*a++ = '.';
long desimal = abs((long)((f - heiltal) * p[precision]));
itoa(desimal, a, 10);
return ret;
}

There is one thing I notice right off-the-bat, though...
abs().
I thought I remember reading something about doing math inside abs() being a 'no-no'.
Anyone out there know for sure?

it is an incorrect implementation, it drops all zero's after the decimal point

suppose you have 52.0034 then (&& precission = 4)

long heiltal = (long)f; => ( hieltal = decimal part = 52 ) OK

long desimal = abs((long)((f - heiltal) * p[precision]));
= abs((long)((52.0043 - 52) * 1000))
= abs((long)((0.0034) * 10000)
= abs((long (34))
= 34

itoa(desimal, a, 10);
--> prints 34 iso 0034

why not just use avr-gcc's dtostre and dtostrf? - avr-libc: <stdlib.h>: General utilities

char* dtostre (double __val, char * __s, unsigned char __prec, unsigned char __flags)

Well, well well. I thought some more about what was going on inside that abs() part.
OF COURSE! Integer math doesn't return leading zeros! How the heck did this routine ever 'get out there'?
Anyway...
I got it to work for me - in my particular instance where my desired precision is always two places to the left of the decimal point.
I'm not going to go nuts trying to get it to work for any further down the line - but you can.

Here's how my version looks now...

char *ftoa(double f, char *a, int precision) {
// Convert float to ascii!
long p[] = {0,10,100,1000,10000,100000,1000000,10000000,100000000};
char *ret = a;
long heiltal = (long)f;
itoa(heiltal, a, 10);
while (*a != '\0') a++;
*a++ = '.';
long desimal = abs((long)((f - heiltal) * p[precision]));
if (desimal< p[precision-1]) //are there leading zeros?
{ *a='0'; a++; }
itoa(desimal, a, 10);
return ret;
}

May you others-like-me now have a nicer day!

if you precision is allways 2 why not implement that in your code? makes it smaller and faster.

BTW have you tried negative numbers?

char *ftoa(double f, char *a) 
{
  // Convert float to ascii!
  char *ret = a;
  long heiltal = (long)f;
  itoa(heiltal, a, 10);
  while (*a != '\0') a++;
  *a++ = '.';
  int desimal = abs((int)((f - heiltal) * 100));  // int is enough for 2 digits
  if (desimal< 10)  //are there leading zeros?
    { *a='0'; a++; }
  itoa(desimal, a, 10);
  return ret;
}