i2c three Slaves, no Master. Possible?

Here's my objective: Option 1: 2 Slaves, 1 Master One slave (Slave A) has buttons connected to it, and reads high/low state. It needs to send a message via i2c immediately to the Master. The Master then tells the other slave, Slave B, to turn an LED on or off via i2c. In short, there needs to be bi-directional communication, and ideally it would be immediate.

From what I have read, it sounds like I can have the Master poll Slave A with the wire.request. The slave either responds with nothing back (which seems to respond with ⸮), or it tells them that a button has been pushed. The Master then sends a standard wire.write message to Slave B and it lights the LED.

My first set of questions are:

1) Does it matter how often or quickly the Master polls Slave A? 2) Can you clog up the i2c lines with too many polls? 3) Does it have any detrimental effect on the hardware, by overworking it? Would the arduino's lifespan be shortened as a result of so much i2c communication?

OR Option 2: 3 Slaves It seems like another option is to have 3 slaves, which sounds like no one is a fan of for some reason. The appeal of the multiple slaves and no master is that you can have Slave A immediately send the message to Slave C (the Master in the first scenario), without a Master having to poll the Slave A.

I tested having two Slaves with addresses '8' and '9'. They both sent messages to each other, no problem. Nick Gammon shows this as a possibility in example code also: http://www.gammon.com.au/i2c-summary If you go to the 'Communicating with other devices' section, it shows his 'master' as having an address of 25. From what I understand, this actually makes it is a 'slave.'

Regardless, it does work for me to have two Slaves send messages to each other. The only thing I can guess could be a problem is if either Slave A, B or C decides to send a message at the same time. I have not been able to get this to occur in my tests yet. But out of curiosity:

4) What would happen if two slaves talk at the same time and the i2c trips over itself? 5) Does it only ruin the two messages sent at the same time? Or does it crash the arduino, and require a restart???

I am guessing that the master's primary purpose is to make sure that messages don't get sent at the same time. Is there something else I am missing?

Thanks for the input! :)

The Master is to make sure that messages don't get sent at the same time. It is possible to have two Slaves, when for example always one Slave starts and the other Slave responds.

1) Yes 2) Not the bus, but the Arduino gets clogged up. 3) No, you may keep the I2C communication running. 4,5) Perhaps only wrong data without warning. Perhaps the Wire library might detect it (if you are lucky). Perhaps the software will halt somewhere. Some I2C devices get so confused that they might stop the I2C bus forever. Solar flares. Disturbance in the space time continuum. Aliens attack. That kind of things, you don't want that :smiley_cat:

A common way is to add a "interrupt" signal from each Slave to the Master. Then the Master has to read the digital inputs of all the "interrupt" signals and when activated request data from that Slave.

It is only buttons ? Then polling is no problem. Does Slave A do the debouncing as well ? Perhaps polling that Slave 10 times per second is enough, maybe a little more is better, for example 20 times per second. Polling 100 times per second is possible, but that is not needed for buttons.

In the Master you can use a software timer with millis() at a rate of 20 Hz (50 ms) to poll Slave A.

Hello Koepel,

Thank you for your reply!!! Very helpful stuff.

If by chance you hear of Aliens attacking next week, then you'll know it was cause I used the all Slave method... :)

I think the reason my double Slave method was working was because I was using interrupts between the two and it was impossible to talk over each other.

But I will follow your polling recommendation instead.

Thank you for your thoughts, help and advice! Have a great weekend!

Few definitions/ protocols of TWI Bus (aka I2C Bus) are:

1. Who is a Master?
The device that acquire TWI Bus by bring START and STOP conditions on the bus; it also generates SCL (clock) pulses to shift-in/shift-out data into/from a Slave.

2. What is an Active Slave?
It is a Slave device having capability of becoming a Master if necessary) as described in Step-1. An MCU like UNO can become an active Slave. Sensors/devices like MPU6050/24C512 are passive slaves.

3. Can two passive slaves work together without a Master?
No.

4. Can two active slaves work together with a Master?
Yes! One or both slaves can become a Master.

5. In what sense the Wire.requestFrom(arg1, arg2) is a looping/waiting/polling instruction?
During the execution if this instruction, the Master keeps waiting (stretches the SCL pulse) to receive the ACK signal from the Slave. After receiving the ACK signal, the Master generates as many SCL pulses as needed (determined by arg2) to read data bytes from the queued buffer of the Slave. The Master saves the received data bytes into a 32-byte wide FIFO type buffer. If the Slave has queued 2 bytes data and the arg2=3, the last data byte is meaningless.

In case the Slave fails to generate ACK signal, the Master will enter into endless loop from which only the Watchdog Timer or user defined timeout logic could bring it out.

bool i2cReady(uint8_t adr)
{
   uint32_t timeout = millis();
   bool ready = false;
   while((millis() - timeout < 100) && (!ready)  //100 ms timeout logic
   {
      Wire.beginTransmission(adr);
      byte busStatus = Wire.endTransmission();
      ready = (busStatus == 0x00)? true : false;
    }
    return ready;
}

6. In TWI Bus, it is very unlikely that a bus contention could happen resulting the loss of message. It is because every Master is required to acquire the Bus first and then begin communication. The bus ownership is achieved by making a Roll Call of the desired Slave and then checking the busStatus for 0x00.

do
{
   Wire.beginTransmission(slaveAddress);
   byte busStatus = Wire.endTransmission():
}
while (busStatus != 0x00);
Serial.println(busStatus);