I2C and Secondary Device Request from another Secondary Device

I have one Nano that is set as the primary/master (top) that needs to request data from a secondary/slave Nano (bottom), but I also have an ATtiny85 secondary/slave that needs to request different data from the secondary/slave Nano. How can I check which device is requesting data from the secondary/slave Nano so it can reply back with the correct info?

I've used I2C previously and have working code but this is the first time where I need one secondary/slave device to respond to both the primary/master and another secondary/slave with different data.

I don't think your architecture is going to work. I don't think that a slave can request from another slave on the bus.

I think the master Nano will need to periodically ask the ATTiny85 slave2 "Do you want data from slave1, and if so what." Then the master will request that data from slave1, receive it, and send it to the ATTiny slave 2.

Alternatively, there could be another signal wire between the ATTiny and the Master Nano which is used by slave2 to tell the master that I want data from slave1.

I don't know if it's possible. But I think you have to wire all the devices to notify each-other when they are communicating with each other.

When one of them is having communication then it raises, or lowers a pin. That pin is connected to the others. So if some device wants to access someone else first it checks if the others are already have access via the pin that is connected to each other.

You don't need to. There is only one master device on the bus, so it must be the one sending the request.

A secondary/slave device cannot request data, so there's no chance any request can come from it.

1 Like

But I have been able to request data from the secondary/slave Nano from the ATtiny85 - this code works:

ATtiny85

void setup() 
{
  Wire.begin(10); // join i2c bus with address #10 (each secondary needs a unique address - numbers 1-7 should be avoided)

  // Get delay timing from other device
  getDelay();
}

/*
    Purpose:    function that executes in setup() to get delay before showing NeoPixels
    Parameters: none
    Returns:    nothing
*/
void getDelay() {
  Wire.requestFrom(8, 2);         // request 2 bytes from blinky/stepper motor controller (numbers 1-7 should be avoided)

  byte highbyte = Wire.read();    // highbyte holds upper byte of received delayBeforeExitAdjustmentsMS
  byte lowbyte  = Wire.read();    // lowbyte holds lower byte of received delayBeforeExitAdjustmentsMS

  delayBeforeShowNeoPixelsMS = (highbyte<<8)+lowbyte; //make those bytes back into an int (parenthesize everything 
                                                      //when doing bitwise operators, the order of operations is counter-intuitive)

  if (delayBeforeShowNeoPixelsMS == -1) {
    delayBeforeShowNeoPixelsMS = 6000;
    return;                       // Cannot connect to secondary device, so exit
  }
}

Secondary/Slave Nano

void setup() {

  Wire.begin(8);                // join i2c bus with address #8 (each secondary needs a unique address - numbers 1-7 should be avoided)
  Wire.onRequest(requestEvent); // register event
  Wire.onReceive(receiveEvent); // register event
}

/*
    Purpose:    function that executes whenever data is requested by nother microcontroller
                [this function is registered as an event, see setup()]
    Parameters: none
    Returns:    nothing
*/
void requestEvent() {
#ifdef DEBUG_MODE
  Serial.println("requestEvent() called - send total time to wait before NeoPixels light up...");
#endif

  byte highbyte = (AMBER_LED_WAIT_START_TIME + AMBER_LED_FADE_UP_TIME)>>8;     // shift right 8 bits, leaving only the 8 high bits. 
  byte lowbyte  = (AMBER_LED_WAIT_START_TIME + AMBER_LED_FADE_UP_TIME)&0xFF;   // bitwise AND with 0xFF

  Wire.write(highbyte);                         // I2C is byte oriented; write(pause time);
  Wire.write(lowbyte);
}

Any MCU making a request is a master, not a slave.

The Arduino Wire library doesn't support multiple masters, as far as I know. That may be why you are having difficulties.

Can you redesign your circuit so that there only needs to be one master?

PS. please post complete code, not snippets.

I hadn't considered this, but it shouldn't be impossible. You need to set up a protocol to determine which is the primary master and which is the secondary master to prevent bus contention.

A single line connecting the masters should be able to prevent bus contention.