floats to char arrays

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

Hi guys,
Im trying to convert a float (say, pi) to an unsigned char array.
I was trying something like this:

float x;
    unsigned char *c = (unsigned char *)&x;

    x = 1.2345;
//do something with c...

But it doesnt work - I get garbage out, and I remember that I might need to include a .a file or two, and I cant remember where to find them (if thats the case) I think I need to add them as a linker?
Could someone shed some light on this for me?
Thanks

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

You probably want dtostre() or dtostrf().

You do not say what compiler you are using.

For avr-gcc they are in avrlibc and have their prototypes in stdlib.h . Thus, you do not need to do anything with the linking stage.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

Quote:
//do something with c...
Do what with c? If you really want a human readable string, then use the functions that Johan recommended, but you will have to call those functions after assigning a value to x, not before.

Regards,
Steve A.

The Board helps those that help themselves.

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

Thanks guys.
well I actually want to send it wirelessly - I have all of that set up, but currently I can send unsigned chars, floats have been eluding me!

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

The devil is in the details - which you havent shown us. I expect that you realise that a float is 4 bytes, so you need to ensure you code treats it as such. Also, what is receiving these 4 bytes? If it is a different machine, eg PC, then you might have endianess issues.
To debug these problems, i would look at the following:
The byte representation of your float ( use a debugger or simulator)
The bytes that you send
The bytes that you receive
The resultant float value on the receive end

Find out where it goes wrong and you've nearly got the problem solved. You can always read up on ieee754 floating point representation to understand how the float is represented.

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

But do you want to send the float over the radio as 4 bytes of binary for speed, or 8 or 9 bytes of ascii chars with decimal point etc in human readable form so its easy to read on the receiving end? The sort of speed vs readability tradeoffs are the realm of 'system engineering'. You have to decide which parameter is most important.

Imagecraft compiler user

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

Check this out, it's not fast and elegant but it's working. Include stdio.h as I remember correctly.

//	*** Function shtFloatToString(float number) ***
//	Get float temperature or humidity and return string value
char * shtFloatToString(float number) {
	static char text[TERMINAL_BUFFER_SIZE];
	int number_int;
	float difference;
	int rest;
	number_int = (int)number;
	difference = number - (float)number_int;
	rest = (int)(difference * 100.0);
	sprintf(text, "#i.#i", number_int, rest);
	return text;
}

Replace # with % in sprintf

SHT11 C source code for ATmega
www.shtproject.blogspot.com

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

Sht11, you missed to requirements. The OP didn't want float to string, i don't know why you just didnt use sprintf with
f for float. You can also specify precision.

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

Bob thats an interesting point.
I am sending it via rf from mega168 to mega1284, then the 1284 pumps it out to serial. Everything works except when I send floats (ints such as 1 come out as [1])
Currently my code is doing this sort of thing:
[code]float pi = 3.141596;
unsigned char halfpie[10];
snprintf(halfpie, 79, "% f", pi);
while(1){
i = 0;
while (i < sizeof(halfpie)){
//send halfpie[i]
i++;
}
}
That works for characters but not for floats. However I havent tried Johan's suggestion(dtostrf()).
How would you send it as binary, I would be interested to do it for speed, and then convert back at the other end into something human readable...

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

Quote:
That works for characters but not for floats.
And what exactly means "don't work"? Are you getting a '?' followed by some garbage by any chance?

BTW:
Why do you use 79 in the snprintf call while your buffer size is actually only 10?
Why do you send the whole buffer instead of only the meaningful content of it?

Stefan Ernst

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

Quote:
How would you send it as binary

The size of a float (or double) is 4 bytes. You'd simply send those bytes, one by one. But then you'd have to make sure the other end can work with the same representations for floats, and e.g. "endianness".

If you stay with converting the floats to strings on the AVR side, send the strings and then convert back at the other there will be no such issues.

Tell us something about the performance requirements. How much data is to be sent per second?

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

Sorry, that 79 was a typo, I was copying a commented out line rather than the line that was being used.
Anyhow, currently using Johan's method:

float pi = 3.141596;
unsigned char halfpie[5];
dtostrf(pi, sizeof(halfpie), 3, halfpie);
	while(1)
	{		
		i = 0;
		DelayS(1); //delay 1 second between each letter
		while (i < sizeof(halfpie)){
		data[0] = halfpie[i];//c[i]; //set up data to be sent
		i++;
		//send data via RF
		
		ToggleLED(); //toggle the on-board LED as visual indication that the loop has completed
		DelayMS(50);
		
		}
	}

Works.
I get 3.142 out the other end, however I am interested in speed options
Eventually I want to send a string of comma seperated floats - perhaps 6 so say:
1.1111,2.2222,3.3333,4.4444,5.5555,6.6666
And the other end to seperate it out based on the commas
I want it as fast as I can get it but still reliably. The datasheet says:

Quote:

250kbps, 1Mbps and 2Mbps on-air data-rate options

Which sounds really fast considering Im just sending some floats...
I also want to know whether the correct data was received, but obviosuly I dont want to send all the data back again, so I am wondering if there is a standard algorithm for this - i.e add all the numbers together and divide by the number of numbers the send that back or somethign?