The Slaves are not sending data whenever they feel like it, they are responding to the Wire.requestFrom() from the Master. So the Master controls the I2C bus.
The Wire.write() can send a number of bytes. The second parameter is the number of bytes. If the second parameter is omitted, only one byte is send, but just one byte is boring...
I prefer a struct to create a package and transfer that. Both the Master and the Slave must know the struct of course.
This is with a buffer:
byte buffer[10];
buffer[0] = 0x25;
buffer[1] = 0x75;
Wire.write( buffer, 10);
In the Master, the Wire.requestFrom() requests data from the Slave, and waits for it, puts the data into a buffer and returns the number of bytes received.
So you don't need the Wire.available() at all, the Wire.requestFrom() already returns the number of data bytes in the buffer.
byte buf[10];
int n = Wire.requestFrom( 2, 10);
for( int i = 0; i<n; i++)
{
buf[i] = Wire.read();
}
Or use the readBytes()
byte buf[10];
int n = Wire.requestFrom( 2, 10);
Wire.readBytes( buf, n);
if ( n != 10)
Serial.println("Error, didn't receive 10 bytes");
If the Master only need the first 4 bytes, it can do Wire.requestFrom ( 2 , 4 ) ;
It is okay that the Slave still does a Wire.write ( buffer, 10 ) ;
It is part of the protocol that it works, and the Arduino libraries allow it too.
The sizeof() is for the compiler. The compiler fills in the number of bytes of that element. An integer is 2 bytes.
How is my explanation so far ?