Sending floating point numbers

I want to grab each byte of a float and send it using LoRa. C++ is overprotective of its variable types and gets real irritated when you (that is, me) try to disassemble, send them, and then reconstruct numbers (ints, floats, doubles). Is there a function (like highByte()) that can pluck the 3rd or 4th byte out of a float?

I'm working with is the MPU6050, which has in its library support for:
x = RAD_TO_DEG * (atan2(-yAng, -zAng)+PI);
where the variables are all integers. Obviously, "x" isn't an integer, it's declared as a double in the example code, but this code forces it to be a float.

I've considered making "x" an integer by doing something like this:
x = init() (RAD_TO_DEG * (atan2(-yAng, -zAng)+PI) * 100) ;
then converting back to a float at the receiver with a simple:
x = x / 100.0 ;

My second question is, will the function init() force "x" to be an integer variable representing hundredths of degrees?

If you have questions about code, please post ALL the code, using code tags.

But for your first question, using most of the common radio libraries, there is no need to disassemble a float to send it. Something like this works with RadioHead, for example

radio.send((uint8_t *)&floatval, 4); //send four consecutive bytes

Since sensor data is almost always integer valued, send integers. To send an integer representing a float in 1/100 degree use

int x = 100.0*floatval:

Make sure that x does not exceed 32676 on an AVR based Arduino.

You can use an union like this

/*
  floating point union
*/
union FU
{
  float f;
  uint8_t b[sizeof(float)];
};

Declare a variable, and set the f element

FU fu;
fu.f = 3.1415;

You can now iterate over the bytes and send them.

Does that compile?

Without knowing what init() is, I guess it's hard to say.

thanks for the radio.send() function, that looks like it's what I was looking for.

However, you raise another question when you post

int x = 100.0*floatval ;

if you had posted

int x = 100*floatval ;

would that have truncated floatval to an integer prior to the multiplication?

As far as integer size, I'm only working with +/- 90 degrees, so hundredths would be within +/- 9,000.

No. Both expressions are evaluated as floats. I just like to put the decimal into floating point constants in order to make the intent clear.

1 Like

Thanks, I have struggled with unions before, I guess I should spend some time on the concept.

As far as the init() function, all I can say is I've seen some code that implied there was a function that would convert the number to the right into a different type, eg, float to integer or vice versa. Maybe what I had seen was

x = (init) floatval ;

What jremington posted above looks straightforward (int x = 100.0 * floatval ;). I'm going to give that a try.

Using a union to convert data types is called type punning and is not legal in C++. See this recent discussion, Problem with the use of union

Also see this page: Don't use unions or pointer casts for type punning

1 Like

You are probably thinking of "int" as in

int x = (int) floatval;

But you can leave out the "(int)".

There are excellent C/C++ references on line; always a good idea to check, especially when it comes to operator precedence, which can be very confusing.

https://en.cppreference.com/w/

1 Like

what Lora board are you using?
put your floats and other data in a structure and transmit the complete structure
for example have a look at decimals-strings-and-lora

Thanks. memcpy it is.

can you use serial write to send the raw bytes comprising the float/double

void
setup ()
{
    Serial.begin (9600);

    double  x = 3.14;
    byte   *p = (byte *)&x;

    Serial.println ("ready");
    Serial.write (p, sizeof(x));
    Serial.println ();
}

void loop () { }

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.