Ok...did some testing....here we go.
First...this will be a long post (I guess as I have to write it) read it if you want, skip it if you don't want.
Now, first some environment setup 'painting':
As I2C sender a ESP8266 as master (as it can not do slave).
As I2C receiver a Nano on address 9
It's been discussed that you should not do this, all kind of limitations on either ESP or Nano side and/or different voltages/architectures etc. We'll skip that for the moment as:
I2C communication between these 2 modules IS working.
When sending a standard transmission with a byte it all works fine.
When incrementing the sended byte value (byte++) the receiving side shows it perfectly. So: although not perfect for all kind of reasons: communication is there and working flawlessly.
The problem arises when sending Structures and especially when....(cliffhanger...will come back to that later
)
Working Structure send/receive:
Followed the instructions from you all above and made a volatile flag (in case I2C receive is an interrupt driven function. If not it wouldn't harm to do so).
OK: working code for the ESP8266 as sender.
Very basic, no bells/whistles just to do the basic test.
/*
I2C comm tussen Nano (master) en een Wemos (slave)
Nano: A4=SDA A5=SCL
Wemos: D2=SDA D1=SCL
*/
#define Slave_Addr 9 //I2C adres van de ontvanger (nano)
#define loop_delay 1000
#include <Wire.h>
//struct I2cTxStruct { //NOT working
struct __attribute__((__packed__)) I2cTxStruct { //this structure works
char textA[16];
int16_t valA;
uint32_t valB;
byte padding[10];
}; //end struct
I2cTxStruct txData = {"xxx", 236, 15};
void setup() {
Serial.begin (9600);
Wire.begin(); //open comm as Master
Serial.print("sizeof(I2cTxStruct) = ");
Serial.println(sizeof(struct I2cTxStruct));
} //end setup
void loop() {
transmitData(); // this function sends the data if one is ready to be sent
delay (loop_delay);
} //end loop
void transmitData() {
Wire.beginTransmission(Slave_Addr);
Wire.write((byte*) &txData, sizeof(txData));
Wire.endTransmission(); // this is what actually sends the data
}
The receiver code for the Nano:
/*
I2C comm tussen Nano (master) en een Wemos (slave)
Nano: A4=SDA A5=SCL
Wemos: D2=SDA D1=SCL
*/
# define loop_delay 1000
# define Slave_Addr 9 //I2C adres van de Wemos
#include <Wire.h>
//struct I2cRxStruct { //this works size of struct = 32 bytes
struct __attribute__((__packed__)) I2cRxStruct { //this also works
char textA[16];
int16_t valA;
uint32_t valB;
byte padding[10];
}; //end struct
I2cRxStruct rxData;
volatile bool was_in_RXloop = false;
void setup() {
Serial.begin(9600);
Wire.begin(Slave_Addr);
Wire.onReceive(receiveEvent);
Serial.print("sizeof(I2cRxStruct) = ");
Serial.println(sizeof(I2cRxStruct));
delay (3000);
} //end setup
void loop() {
//
if (was_in_RXloop==1) {
Serial.println ("We did get into the receive loop!");
was_in_RXloop=0;
}
//else Serial.println ("No");
} //end loop
void receiveEvent(int numBytesReceived) {
was_in_RXloop = 1;
Wire.readBytes( (byte*) &rxData, numBytesReceived);
} //end receiveEvent
And the outcome when I run this:
17:33:04.698 -> sizeof(I2cRxStruct) = 32
17:33:07.712 -> We did get into the receive loop!
17:33:08.300 -> We did get into the receive loop!
17:33:09.296 -> We did get into the receive loop!
17:33:10.285 -> We did get into the receive loop!
17:33:11.294 -> We did get into the receive loop!
17:33:12.298 -> We did get into the receive loop!
As you can see: appr. every second (that's the delay in the send sketch) we are into the receive event as expected.
Not in this code but I'm also able to read all the sended variables so all ok.
Now the interesting part:
There are 2 variables, on both the sender and receiver so that gives 4 possibilities.
It's all in the definition of the Structure:
A) //struct I2cRxStruct {
B) struct __attribute__((__packed__)) I2cRxStruct {
When running these structures on the Nano with the given definition the outcome for both is 32bytes (the absolute length is not important, it's 32 bytes for this test).
No difference for both declaration.
However.....
On the ESP8266 it's different.
The A) structure is 36 bytes where the B) structure is the same as the Nano: 32 bytes.
When running the program: When the sender is using structure B) I can change the structure definition in the Nano to either A or B, both work (as the both generate a struct of the same size).
But when I use the B) structure on the 8266 non of the A or B structures on the Nano will make it work....but
Also: when the sender is sending a structure of 36 bytes the receiveEvent will NOT get triggered.
Not once, not multiple times...just not.
And this I think is strange were as the receiver doesn't know upfront that there are more bytes being send then should.
My thought whould be that at the first byte it would trigger the Event and finally I don't know what would happen because there are more bytes being send then would fit in the structure but the event is not being called at all.
Now...
That's my contribution / outcome of the experiment and although I do not understand it I think the reason behind it is somewhere in the deep dungeons of the 8266 and better leave it there as it is as using the --packed-- structure does work fine.