union and struct to make byte array

I’m trying to use a union with a typdef struct to convert some data into a byte array, then send over I2C, then convert back, but the values I get when I convert back are incorrect.
Attached are the I2C Slave and Master sketches.

Here’s my approach:

Define my structure and union:

#define PACKET_SIZE 11
typedef struct sensorData_t{
  byte stat;
  byte sensorId;
  byte sensortype;
  byte isWet;
  uint16_t temp;
  float volts;
  byte signal;
};

typedef union I2C_Packet_t{
 sensorData_t sensor;
 byte I2CPacket[sizeof(sensorData_t)];
};
I2C_Packet_t leakinfo;

Populate with my data:

  leakinfo.sensor.stat = 0; 
  leakinfo.sensor.sensorId = 22; 
  leakinfo.sensor.sensortype = 0; 
  leakinfo.sensor.isWet = 0; 
  leakinfo.sensor.temp = 75; 
  leakinfo.sensor.volts = 3141 / 1000.0; 
  leakinfo.sensor.signal = 88;

Send out over I2C:

  Wire.write(leakinfo.I2CPacket, PACKET_SIZE);

Then in the Master, I’m trying to put it back in the structure.

  byte byteArray[PACKET_SIZE];
  int readstatus = I2c.read(addrSlaveI2C, PACKET_SIZE, byteArray ); //request data and store directly to i2CData array

  for (int k=0; k < PACKET_SIZE; k++)
  {  leakinfo.I2CPacket[k] = byteArray[k]; }

I verified the master is properly receiving the byte array

Byte         0   1      2       3        4      5        6      7       8       9       10
From Master: 0	22	0	0	75	0	37	6	73	64	88	
From Slave:  0	22	0	0	75	0	37	6	73	64	88

But it’s not getting converted into the proper values. Below is a sample of what I’m getting. What i get also varies, it’s not always the same.

                          Expecting   Actual
leakinfo.sensor.stat          0        231
leakinfo.sensor.sensorId     22          0
leakinfo.sensor.sensortype    0          1
leakinfo.sensor.isWet         0          0 
leakinfo.sensor.temp         75      25344
leakinfo.sensor.volts      3.14          0
leakinfo.sensor.signal       88        155

Is this approach even viable? If so, what am i doing wrong?

I2C_Master_DSS_struct.ino (2.15 KB)

I2C_Slave_struct.ino (2.69 KB)

In master…

void loop()
{
  // I2C_Packet_t leakinfo; // <-- REMOVE THIS LINE

That did it. It's working now, thank you!!

One potential problem with your code is the hardcoded size for the struct. Depending on platform and order of objects in the struct, there may be padding added to make addressing easier.

You should let the compiler compute the size, so that if padding is added, the correct amount of data will still be sent.

PaulS: One potential problem with your code is the hardcoded size for the struct. Depending on platform and order of objects in the struct, there may be padding added to make addressing easier.

You should let the compiler compute the size, so that if padding is added, the correct amount of data will still be sent.

Do you mean I should get rid of #define PACKET_SIZE 11 and use sizeof() instead?

Do you mean I should get rid of #define PACKET_SIZE 11 and use sizeof() instead?

Yes. Or, move the #define to after the structure definition, and replace the 11 with sizeof(sensorData_t).

Thanks for the tip, I'll do that.