i2c master multi slave system

Dear All,
I've been searching the web for over two weeks now and tried a lot to create a arduino network over i2c. My goal is to have a lot of arduino's(for now asume, 10 arduino's) working as a slave. And one as a master.

For now I used the Wire library which is pretty easy to use, although it's not really well documented. But because it's out there for quite some time now, I was able to find a lot of info. One of the most interesting examples of a master-slave system I found was this one by Wyatt Olson (The Digital Cave - Arduino I2C Sketches)

It handles a multi master system as well. Which to me looks like exactly what I want. Works like a charm with 2 arduino's but above 3 arduino's it crashes. I've been searching why, and somewhere I read that if the Wire library sends data it becomes a master and creates its own clock on the clock line. Except when a master request data with requestFrom().

So knowing this, I build my own little system with 1 master requesting data from 2 slaves. That works. After that I created a master slave system where a master sends data to 2 slaves, works as well. But it seems I cannot make it work together.

My question to all of you is(before I put my code here), is there a way or example that I didn't find which handles this kind of master slave system?

Thank you very much in advance,
Rob

Basically what you have to do with a multi-master system is to ensure that no two devices are trying to send at the same time. This is a lot more difficult than it sounds.

You are much better off having a single master that asks the other slaves if they have data for it. That is called polling a slave and is much simpler to implement and 99% of the time all you need.

Thanks GM,

I was guessing that the 'not at the same time' was the problem. The single master asking for data is requestFrom in the wire library I assume? Do you maybe have an example of a script what does this and where the slaves are also capable to receive normal commands(this is what I cannot make to work)?

I'm definitely within the 99%! What you describe is exactly what I'm looking for.

Thank you.
Rob

Anyone? Can I provide more info? Please ask so I can put it up here.

and where the slaves are also capable to receive normal commands

Not sure what you mean by this? I haven't done slave I2C on an arduino myself. I am assuming you are following:-
http://www.arduino.cc/playground/Learning/I2C

and the linking page:-

Hello Mike and others,

First of all, Mike, thank you for your help.

It appears that I made a mistake. As told I could make sending from a master work, also I could make receiving from a slave work, but couldn't combine them in one script. I thought I did something wrong. But I got it working.

I'll post my master and slave script here so it will be findable for anyone in the future. It's not the best code ever and there are a few weird jumps but that's because I'm implenting stuff later on. Still, I think it can be very usefull.

The master script has basically two parts. One part to send data to the slaves. Now consisting of just two functions(which can easily be only one) that turns a led on the slave on or off. The other part receives data from a slave on request. Now there's two way communication between the master and a slave.

On the slave side the code consists of two parts as well. One parts to answer to the master asking for data, and one part to recieve. I've built in a case switch already, although it's not of great use at the moment in the script.

If someone is working on this in the future and has as many problems to get it working as me. Feel free to PM me or contact me via my website www.robhebing.nl

Mastercode:

#include <Wire.h>

void setup()
{
  Wire.begin();        // join i2c bus
}

void loop()

{   
  //get data of a analogIn from a slave
  requestFromSlave(4);
  
  //turn led 13 on at the master and the slave
  digitalWrite(13,HIGH);
  slavePinOn(4,13);
  delay(500);
  
  //turn led 13 off at the master and the slave
  digitalWrite(13,LOW);
  slavePinOff(4,13);
  delay(500);
}

void requestFromSlave(int slave){
   Wire.requestFrom(slave, 2);   //request 2 bytes.

    while(Wire.available()>1)    
  { 
    int pin = Wire.receive();    //in this example the master will receive a pin and a value for an analogWrite
    int value = Wire.receive(); 
    analogWrite(pin,value);
  } 
}

void slavePinOn(int slaveID, int pin){ 
    Wire.beginTransmission(slaveID);
    Wire.send('a');
    Wire.send(pin);
    Wire.send(1);
    Wire.endTransmission();
    delayMicroseconds(10);
}

void slavePinOff(int slaveID, int pin){
    Wire.beginTransmission(slaveID);
    Wire.send('b');
    Wire.send(pin);
    Wire.send(0);
    Wire.endTransmission();
    delayMicroseconds(10);
}

Slavecode:

#include <Wire.h>

byte analogValue=0;


void setup()
{
  Wire.begin(4);                // join i2c bus with address #4
  Wire.onRequest(requestEvent); // register event
  Wire.onReceive(receiveEvent); 
  for(int i=2; i<=13; i++){     //set some pins as output
    pinMode(i,OUTPUT);
  }
}

void loop()
{
  //prepare a analog value
  int tempValue = analogRead(0);
  analogValue = map(tempValue, 0, 1023, 0, 255);

}



  void receiveEvent(int howMany)
{
  while(Wire.available() < 2);                              // Wait for 2 bytes to become available
  char caseState = Wire.receive();
  
  switch (caseState){
    case 'a':{
      
      int pin = Wire.receive();                      
      int ledValue =Wire.receive();
      pinOn(pin);
  }
    break;
    case 'b':{
      int pin = Wire.receive();                        
      int ledValue =Wire.receive();                    
      pinOff(pin);
    }
    break;
  
  }
}  

void requestEvent()//When data is requested by the master send a bytearray back.
{ 
  byte data[2];
  data[0] = 11;//the pin on the master
  data[1] = analogValue;//the value 

  Wire.send(data,2); 
}


void pinOn(int pin){//function to turn pin on
      digitalWrite(pin,HIGH);
}
void pinOff(int pin){//function to turn pin off
      digitalWrite(pin,LOW);
}