Usin I2C where Slave indicates to master that data are ready to be transfered

Hi All,

Thank you for reading my post,

I have tied 2 Arduinos together with I2C and having a small problem.

Masters the one who will be running just the code (very fast <50ms per loop) and Slave will have some Temperature sensors and other stuff which will be relatively slow (about 1.2s per loop).
The main problem is that as soon as Master requests data from Slave, slave drops everything that is doing (the temperature measurement for instance).

What I would like is that Slave would do the measurement, indicate to a Master that data is ready to transfer and then Master requests and gets data. With that, I would avoid extra delay on the Master.

Is there a way or function that would help me with that problem (i am aware that it might not be possible)?

I have put together a test code where Slave on request sends 8 random numbers to a Master. Before sending they get translated to bytes and on the other end back to int.

Thanks,

MASTER:

#include <Wire.h>
#define SLAVE_ADDRESS 4
#define ANSWER_SIZE 16

int i = 0;
int sensors[8] = {0};
byte array_received[16];
 
void setup() 
{
  Wire.begin();
  Serial.begin(9600);
}
 
void loop() 
{
  delay(500);
  
  Wire.requestFrom(SLAVE_ADDRESS,ANSWER_SIZE);
  for(i = 0; i < 16; i++)
  {
    array_received[i] = Wire.read();
  }
  for(i = 0; i < 8; i++)
  {
    sensors[i] = array_received[i*2];
    sensors[i] = (sensors[i] << 8) | array_received[(i*2)+1];
    Serial.print(sensors[i]);
    Serial.print("  ");
  }
  Serial.println("");
}

SLAVE:

#include <Wire.h>
#define SLAVE_ADDRESS 4

int i = 0;
int sensors[8] = {2560, 2570, 1006, 2206, 310, 320, 2006, 2016};
byte array_send[16];
 
void setup() 
{
  Wire.begin(SLAVE_ADDRESS);
  Wire.onRequest(requestEvent); 
  Serial.begin(9600);
}

void loop() 
{
 delay(50);
}

void requestEvent() 
{
  for(i = 0; i < 8; i++)
  {
    array_send[i*2] = (sensors[i] >> 8) &0xFF;
    array_send[(i*2)+1] = sensors[i] & 0xFF;
  }
  for(i = 0; i < 16; i++)
  {
    Wire.write(array_send[i]);
  }
}

Where is this temperature measurement that you say the slave is doing? There is nothing in the example slave code except the random numbers, so how do you know it "drops everything that is doing "?

On an I2C bus any device can become a master. If devices A and B have their own I2C addresses, A can send data or notifications to B, and B can send data and notifications to A. Or A and B can broadcast whatsoever to every device on the bus.

Thank you for your reply,

@aarg
This is just a sample code. I didn't put it in the code cause that was not a problem. I was hoping there is a way for Slave to finish one loop and then indicate to a master that is ready for data transfer.

@DrDiettrich
Sorry, I should have mentioned that my I2C knowledge was limited but I get what you are saying. If I have it in Master-Master configuration if one sends a notification to another, would the receiver finish the loop before receiving it? Cause one Arduino would be running a sensitive code that needs to finish first?

Incoming master to slave transmissions are handled in interrupts and the onReceive() callback function. You implement that function according to your needs.