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.
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);
}
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.