Passing a float variable between 2 devices using I2C

A quick share of a solution and maybe a chip in from someone with a better way of doing it?

The problem was to send a float type variable from another MCU (Atmega 328P) to a Photon using I2C.

The sender encodes the float like this following receipt of the request from the Photon:

    uint8_t sendbytes[sizeof(float)] = {0};

        *(float*) (sendbytes) = batteryVoltage;
        Wire.write(sendbytes[0]);
        Wire.write(sendbytes[1]);
        Wire.write(sendbytes[2]);
        Wire.write(sendbytes[3]);

and the Photon (as central) receives like this:

    float result = 0.0;
    uint8_t result_byte[4]; 
    uint8_t byte_count = 0;

    requestBatteryVoltage();

    Wire.requestFrom(9,4);                          //request 4 bytes from peripheral device address 9

    while(Wire.available() && byte_count < 4)
    {
        result_byte[byte_count] = Wire.read();
        byte_count++;
    }

    if (byte_count > 0)                             //Wire request returned 4 bytes - typecast to float
    {
        result = *(float *) (result_byte);
    }
    return result;

Have you tried sending your float like this?

  float f = 123.4;
  Wire.write((uint8_t*)&f, sizeof(f));

and read back as

  float f;
  Wire.readBytes((char*)&f, sizeof(f));

Alternatively you could use a union type like this

typedef union transfer_t {
  float   f;
  char    c[sizeof(f)];
  uint8_t u[sizeof(f)];
} transfer_t;

With that all three variables are placed at the same location in memory - sort of “ontop” eachother.

  transfer_t t;
  t.f = 123.4;
  Wire.write(t.u, sizeof(t.u));
  Wire.readBytes(t.c, sizeof(t.c));
2 Likes

@ScruffR Thanks - the union approach I had considered but selected the typecast initially. The first approach you show with the typecast and dereferencing is an interesting idea and quite a bit ‘neater’ for sure.

The “annoying” thing about both approaches is the fact that the two functions (write() and readBytes()) insist in using “incompatible” datatypes.
I’d much prefer if readBytes() would also accept uint8_t* and/or write() also accepted char*. This way one would only need to remember one type of cast.

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