Sending floats w/NRF8001

Using Blend Micro (basically Arduino Uno + Nordic nRF8001) to gather and send sensor data via BLE. Can't figure out how to send floats.

Here's a snip of code:

if ((lib_aci_is_pipe_available(&aci_state, PIPE_AIR_QUALITY_SENSOR_TEMPERATURE_MEASUREMENT_TX)) && (lib_aci_is_pipe_available(&aci_state, PIPE_AIR_QUALITY_SENSOR_RELATIVE_HUMIDITY_TX)) && (lib_aci_is_pipe_available(&aci_state, PIPE_AIR_QUALITY_SENSOR_CARBON_MONOXIDE_LEVEL_TX)))
  {

    // Read DHT & MQ7 sensors
    h = dht.readHumidity(); // Read humidity from DHT
    t = dht.readTemperature(); // Read temperature as Celsius from DHT
    f = dht.readTemperature(true); // Read temperature as Fahrenheit from DHT
    int VoutAn = analogRead(MQ7PIN); //Read Vout in analog from MQ7

    // Compute heat index
    hi = dht.computeHeatIndex(f, h);

    // Compute CO in PPM
    float Vout = (5.0/1023)*VoutAn;
    co = 100.468*(pow(((5/Vout)-1),-1.43));

    lib_aci_send_data(PIPE_AIR_QUALITY_SENSOR_TEMPERATURE_MEASUREMENT_TX, &f, sizeof(f));
    lib_aci_send_data(PIPE_AIR_QUALITY_SENSOR_RELATIVE_HUMIDITY_TX, &h, sizeof(h));
    lib_aci_send_data(PIPE_AIR_QUALITY_SENSOR_CARBON_MONOXIDE_LEVEL_TX, &co, sizeof(co));
  }

And here's the compile error:

Arduino: 1.0.6 (Mac OS X), Board: "Blend Micro 3.3V/16MHz (overclock)"

BLE-DHT-MQ7-Test.ino: In function 'void loop()':

BLE-DHT-MQ7-Test.ino:287: error: cannot convert 'float*' to 'uint8_t*' for argument '2' to 'bool lib_aci_send_data(uint8_t, uint8_t*, uint8_t)'

BLE-DHT-MQ7-Test.ino:288: error: cannot convert 'float*' to 'uint8_t*' for argument '2' to 'bool lib_aci_send_data(uint8_t, uint8_t*, uint8_t)'

BLE-DHT-MQ7-Test.ino:289: error: cannot convert 'float*' to 'uint8_t*' for argument '2' to 'bool lib_aci_send_data(uint8_t, uint8_t*, uint8_t)'

My understanding of the aci_send_data function is that argument 2 is a uint8_t variable that points to the data in memory to be sent, and that this data can be in any form. But it only seems to work if the data is in a uint8_t variable - e.g. this compiles if I convert my variables to uint8_t - but I need floats...

So my questions:

Am I understanding the aci_send_data function correctly?

If so, what am I doing wrong?

If not, how can I send floats?

Thanks!

Use a cast, e.g. if "f" is a float:

    lib_aci_send_data(PIPE_AIR_QUALITY_SENSOR_TEMPERATURE_MEASUREMENT_TX, (uint8_t *)&f, sizeof(f));

Thank you jremington. But in reading up on casting, it seems not much different from conversion... will using the function with a cast send the float 'f' or will it convert 'f' into an into integer and send that?

I see these codes all the time. Why in the world would anyone use a float type for temperature? Why lose precision? The largest range of temperatures you could possibly be working with here is a few thousand degrees. That will go into a long with more precision than a float AND all the calculations will be faster and more accurate. AND you don't have all these encoding problems sending them around. Why would anyone not do that?

Yes, Delta_G, probably easier and better to use long... but the issue here is that this ACI function requires a uint8_t pointer.

Here's what I came up with:

if ((lib_aci_is_pipe_available(&aci_state, PIPE_AIR_QUALITY_SENSOR_TEMPERATURE_MEASUREMENT_TX)) && (lib_aci_is_pipe_available(&aci_state, PIPE_AIR_QUALITY_SENSOR_RELATIVE_HUMIDITY_TX)) && (lib_aci_is_pipe_available(&aci_state, PIPE_AIR_QUALITY_SENSOR_CARBON_MONOXIDE_LEVEL_TX)))
  {
    
    typedef union _dataF
    {
      float f;
      uint8_t fInt[4];
    } myDataF;
    
    myDataF F;
    
    typedef union _dataH
    {
      float h;
      uint8_t hInt[4];
    } myDataH;
    
    myDataH H;
    
    typedef union _dataCO
    {
      float co;
      uint8_t coInt[4];
    } myDataCO;
    
    myDataCO CO;
    
    // Read DHT & MQ7 sensors
    h = dht.readHumidity(); // Read humidity from DHT
    t = dht.readTemperature(); // Read temperature as Celsius from DHT
    f = dht.readTemperature(true); // Read temperature as Fahrenheit from DHT
    int VoutAn = analogRead(MQ7PIN); //Read Vout in analog from MQ7
    
    // Compute heat index
    hi = dht.computeHeatIndex(f, h);
    
    // Compute CO in PPM
    float Vout = (5.0/1023)*VoutAn;
    co = 100.468*(pow(((5/Vout)-1),-1.43));
    
    F.f = f;
    H.h = h;
    CO.co = co;
    
    lib_aci_send_data(PIPE_AIR_QUALITY_SENSOR_TEMPERATURE_MEASUREMENT_TX, F.fInt, 4);
    lib_aci_send_data(PIPE_AIR_QUALITY_SENSOR_RELATIVE_HUMIDITY_TX, H.hInt, 4);
    lib_aci_send_data(PIPE_AIR_QUALITY_SENSOR_CARBON_MONOXIDE_LEVEL_TX, CO.coInt, 4);
  }

But in reading up on casting, it seems not much different from conversion... will using the function with a cast send the float 'f'

Casting does not convert. Casting like I proposed tells the compiler to treat "&f" as a pointer to a byte quantity or a byte array. The transmitter function will then send the 4 bytes that make up the float value, where 4 = sizeof(f).

On the receiving end, you need to reconstruct the float from the 4 bytes, and the "union" works great for that. You can also use memcpy(), but it is slower than using a union.

A union could also be used for transmitting, but the cast is easier.