Dynamically define communication channel for I2C

Hi!

I am busy trying out the following:

I have a Master Arduino Uno which will have to connect through I2C to 2 or more other Arduino boards. The Wire functionality allows to connect these arduinos using a unique address for each. However, the problem is that I want to define the unique address by the Master Arduino, once a new device is connected to it.

I tried the following: - The Master Arduino listens to a default address (eg. 11). - The new device gets its power from the 5V of the master module. - Once a new device is connected, I push a button. - The master will send a request through the default address. - The new device will return a GUID. - The master will send back the GUID + a unique address. - Both master and slave will now switch to the unique address and continue communications.

This seems to work with only one device connected. However, once you connect more than one on the default address, this will not work anymore.

Is there any way to "dynamically" attach an address (communication channel) for the I2C communication, so I can connect as many devices as I want to this bus (naturally limited to just a few).

Thanks! Steph

You should probably look at the DHCP protocol for the ethernet interface. It is initiated by the client device when it needs an IP, and sends a unique serial number (mac address) to the DHCP server on a common address. This identifies each client device as unique. If you just "shotgun" a request from the master, more than likely all slaves will think that transmission is for it.

Oops,

using DHCP would be a bit overkill, I think… The idea is that in the end I would use Arduino Nano, which would provide sufficient functionality for I2C, but DHCP would be too much. The devices themselves would be quite small…

As I understand, there is no way to send a message to all devices, and let them reply after each other?

Thanks!

Have you decided how to determine which I2C device is which? Or doesn’t it matter which is responding?

Hey!

Indeed, as I wasn't familiar with I2C, I assumed it would be possible to have multiple devices use the same address. However, as each device needs to have a unique address to function, this did not work.

I did manage however to assign a unique channel to each new device using the following method:

  • A new device is attached to the master. This is simulated using a push button. An initialization function is executed. The master sends over the default address (eg 11) an INIT request.
  • A multiplexer will go through all the attached devices and connect the I2C wires from the master to each of the devices individually.
  • The new device will receive the INIT request over the default address. It will send back its own unique ID (GUID).
  • The master received the GUID of the new device and store it in an array. The master will attach a unique address to this GUID and send back this address to the new device.
  • The new device will switch to the unique address and from then on listen only to this addres.

The above procedure actually seems to work quite good. I can attach new devices without problems and in the end communicate over the unique channels.

Sadly, in the practical solution I will not be able to create a multiplexer. As such, I will not be able to receive the GUIDs from each device and create the list of GUIDs.

So, for me it's back to the drawing board :-)

I hope to find the solution soon!

Thanks!

once you connect more than one on the default address, this will not work anymore.

That probably makes sense as AFAIK you can't have multiple slaves talking at the same time.

Why not add a single slave at a time and have it store it's address in EPROM?


Rob

Apple-talk used a imho smart protocol when a new slave was in the network it asked "has anybody address 15?" if no one responds the new device took address 15 if another device responds (yes I'm 15) then the new device tried another (random) number.

robtillaart:
Apple-talk used a imho smart protocol
when a new slave was in the network it asked “has anybody address 15?” if no one responds the new device took address 15
if another device responds (yes I’m 15) then the new device tried another (random) number

Hey!

Thanks for the tip :slight_smile: I was looking at the master initiating, but I didn’t look into the slave actually searching for a channel. It works!! I am now able to attach as many devices as I want to the master (limited by my own stock of arduinos :-))

A very odd thing I came across. I wanted to try the communication by sending a command - after setting the correct address for each device - to each device separately. The command would simply flash the led 13 for 3x 1 sec at a time.

I simply use the following:

void receiveEvent(int howMany)
{
String cmd = "";
  while(1 < Wire.available()) // loop through all but the last
  {
    char c = Wire.read();
    cmd += c;  
  }
  Serial.println(cmd);
  if (cmd == "#CMD FLASH") {
    Serial.println("COMMAND RECEIVED");
    digitalWrite(ledPin, HIGH); 
    delay(1000);  
    digitalWrite(ledPin, LOW); 
    delay(1000);  
    digitalWrite(ledPin, HIGH); 
    delay(1000);  
    digitalWrite(ledPin, LOW); 
  }
  // re-initialize the wire
  Wire.begin(channel);
  Wire.onRequest(requestEvent); 
  Wire.onReceive(receiveEvent); 
}

However, when I send the command, the slave only flashes once very quickly. It is really odd, because when I just try the blink example, all devices work properly… It seems like the receiveEvent is not able to take delays?

Also, after this is executed, I always have to restart the Wire. If I do not do this, the next time I send a command it will not be received by the slave… Seems a bit odd to me ?..

Again thanks for all your help, it helps me a lot trying to solve this!

BTW:

Be careful if you attach another arduino through the 5V to your master. If you have, as in my case, an external power source, and you by accident attach it to your slave arduino, it will blow up your master... That's at least how I lost one of my Arduino Megas :-(

The mistery deepens…

When I try the following code:

void receiveEvent(int howMany)
{
  Serial.println("RECEIVING COMMAND");
  String cmd = "";
  while(1 < Wire.available()) // loop through all but the last
  {
    char c = Wire.read();
    cmd += c;  
  }
  Serial.println(cmd);
  if (cmd == "#CMD FLASH") {
    Serial.println("COMMAND RECEIVED");
    digitalWrite(ledPin, HIGH); 
    delay(1000);  
    digitalWrite(ledPin, LOW); 
    delay(1000);  
    digitalWrite(ledPin, HIGH); 
    delay(1000);  
    digitalWrite(ledPin, LOW);
    // Serial.println("COMMAND EXECUTED"); 
  }
  Wire.begin(channel);
  Wire.onRequest(requestEvent); 
  Wire.onReceive(receiveEvent); 
}

The led flashes once very fast. It does not flash three times slowly. However, when I uncomment the Serial.println after the last digitalWrite(ledPin, LOW), the whole thing blocks. It even blocks my master device!

This seems to me very odd behaviour. Does anybody have a clue why I cannot add digitalWrites to the receiveEvent?

Thanks!