FtoA another way to implement it

Go To Last Post
9 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello,
i need to output to the UART of a tiny2313 two float numbers with 2 chars precision...

i use codevision and i i perfome ftoa with the cvavr routine it fulls my memory 1260words instead of 1024 i have....
it takes me around 20% of avr's flash...

is there any other way to output to the uart those two numbers i want?

i am stack with 2313 because pcb is ready

thank you and hope there is another way...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

what is the standard

JChristoff
Illinois

Last Edited: Fri. Jan 7, 2011 - 04:47 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

1) try to use printf (maybe it's smaller... hmmm I doubt it);
2) try to write your own function (use integers or long integers instead... decimal point will be virtual - of course);
Something like:

myInteger = myFloat * 100;

Then, send: (myInteger / 100) and "." and finally (myInteger%100).
It should work fine...
3) try also to compile the program with "optimize for size".
HTH,

Real men don't use backups, they post their stuff on a public ftp server and let the rest of the world make copies.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ftoa in CVAVR takes 20% of an ATtiny2313's flash?

That sounds pretty good!

dtostrf (the most compact library function to have the same effect in avr-libc for avr-gcc) appears to be much larger than that... The following trivial program requires 1784 bytes of Flash (892 of the available 1024 words):

#include 
#include 
#include 
int main(void)
{
	char text[20];
	float x = 2.5;
	dtostrf(x, 0, 2, text);
	while(1);
}

main() requires 32 bytes according to the map file...
That means that dtostrf() itself takes up the better part of 1700 bytes... about 83% of an ATtiny2313's total flash space.

If you can possibly get away with it, I'd say you'd be better off using integer mathematics to fake your floats using fixed-point numbers. The integer-to-ASCII conversion routines will be more compact.

If you absolutely must use floats, then (I really hate to say this...) you may be better off sending the raw binary floats, and leaving conversion to a human-readable format up to the receiving entity.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Finally, I strongly believe that in this particular case the AVR will decently handle the situation, just by using the integer operations. This technique has at least two major advantages:
1) no special software on PC side to do the conversion(s) to human readable format;
2) easy to debug when it comes to spy the serial communication line.

Real men don't use backups, they post their stuff on a public ftp server and let the rest of the world make copies.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Where are the numbers coming from?

JChristoff
Illinois

Last Edited: Fri. Jan 7, 2011 - 04:46 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

int temperature;
char *uart_buffer;

temperature = temp_val.f * 100;
// ftoa(temp_val.f,2,uart_buffer);

itoa(temperature,uart_buffer);
puts(uart_buffer);

what is wrong with the above code?

i tried to do it "the integer way" but i get other numbers than expected...

its a sensor , i calculate the value in avr which is float... lets say 28,40

so i multiply it with 100 ..... expected valu 2840
but in my uart comes something like this ;4000<\f>

any clue?

thanks!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

KostasTheGreat wrote:
its a sensor , i calculate the value in avr which is float...

But why use float in the first place. I'm guessing the sensor starts by outputting a binary value (0..255, 0..65535, ?) and you are then using floats to convert this to degF or degC scale value to a couple of decimal places? But why not convert it to 1/100ths of a degF or 1/100ths of a degC and keep the value integer all the way.

Floats are very rarely a necessity in an embedded control application.

Cliff

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You've allocated a pointer but, where is the storage space allocated to hold the ASCII data?

instead of:

char *uart_buffer; 

where, the compiler has no reference as to where to put the converted string so, it's probably getting trashed.

Maybe something like:

char uart_buffer[20]:

The following code worked using ICCAVR 6.xx.

2840 was multiplied by 100, equalling 284000 and it displayed correctly using HyperTerminal.

long int temperature; 
long int temp_val = 2840;
  
char uart_buff[20]; 
 
temperature = temp_val * 100; 

// Convert the long integer to ASCII format in the base 10 radix.
ltoa(uart_buff, temperature, 10); 
puts(uart_buff);

You can avoid reality, for a while.  But you can't avoid the consequences of reality! - C.W. Livingston