1

I need to interface an ATTiny88 MCU configured as an I2C slave with a Raspberry Pi configured as an I2C master. I may be using the wrong approach, but I have a structure consisting of four different fixed length data types I want to pass back to the Master whenever it requests data.

Source Code:

#include <Wire.h>
struct Response // 7 bytes
 {
 byte Command; // 1 byte
 float Temperature; // 4 bytes
 byte FanValue; // 1 byte
 bool CoolStat; // 1 byte
 };
struct Response Reply;
bool True = 1;
bool False = 0
void setup()
{
 pinMode(ADDR1, INPUT_PULLUP); // Address Offset 0 or 1
 pinMode(ADDR2, INPUT_PULLUP); // Address Offset 0 or 2
 I2C = (2 * digitalRead(ADDR1)) + digitalRead(ADDR1) + 8; // Set I2C address 8 - 11
 Wire.begin(I2C);
 Wire.onRequest(requestEvent); // Call requestEvent when data requested
 Reply.Command = 1;
 Reply.Temperature = 35.62;
 Reply.FanValue = 255
 Reply.CoolStat = True
}
// Function that executes whenever data is requested from master
void requestEvent() {
 Wire.write(Reply); // respond with message as expected by master
 Responded = True;
}

This does not work, of course, because the library does not like the fact I am passing a structure, rather than a simple null terminated string. I am not sure how best to pass the structure to the Wire.write() function. I like the ability to change the variables in the structure to different values of different data types at different points in the code, but would I be better served to take a different approach and manually update the binary values in the string?

asked Jul 17, 2024 at 6:25

1 Answer 1

3

There is an overload of Wire.write that lets you send an arbitrary array of bytes:

virtual size_t write(const uint8_t *, size_t);

In order to use it, you have to cast the address of your structure to a pointer to uint8_t:

Wire.write((uint8_t *) &Reply, sizeof Reply);

Note, however, that this method, although very common, is not really conformant to the C++ standard. I suggest you instead use a union that lets you access the memory of the structure as a simple array of bytes:

union Response {
 struct {
 byte Command; // 1 byte
 float Temperature; // 4 bytes
 byte FanValue; // 1 byte
 bool CoolStat; // 1 byte
 };
 uint8_t bytes[7];
};

This can then be sent with:

Wire.write(Reply.bytes, sizeof Reply);

However: You may have a hard time parsing the structure back on the Pi. Different computing platforms have different data-type sizes and different alignments constraints. The structure you are using may be 7-bytes long on an Arduino Uno, but it will be larger on an ARM-based Arduino, and also on a Raspberry Pi: for alignment reasons, you will have three padding bytes before Temperature. Also, the CoolStat field may be larger than one byte, and add some padding of its own. To make things easier, I recommend you define the structure in a way that its layout is platform-independent: use only fixed-size types, put the larger items first, and manually pad to a multiple of the larger item's size:

union Response {
 struct {
 float Temperature; // 4 bytes
 uint8_t Command; // 1 byte
 uint8_t FanValue; // 1 byte
 uint8_t CoolStat; // 1 byte
 uint8_t padding; // 1 byte
 };
 uint8_t bytes[8];
};

This should have the exact same layout on any Arduino, and also on a Raspberry Pi.

answered Jul 17, 2024 at 8:24
3
  • To avoid alignment, you can use #pragma pack(1) Commented Jul 17, 2024 at 10:28
  • @SBF: This probably works on x86_64. However, I prefer avoid it, as I have used computers where unaligned memory accesses crash the program with SIGBUS (Bus error). Commented Jul 17, 2024 at 14:41
  • Thank you, Sir! Yours is a perfect answer. Commented Jul 22, 2024 at 18:52

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.