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.