I2C device addressing

It's been a while, had to bring up my new website...

But I have made a little progress. Bought a Saleae Logic to help out and then wrote some code.

I first tried the I2C library here http://dsscircuits.com/articles/arduino-i2c-master-library.html and found out that the Slave side of the API isn't there yet: "The new library does not support Slave functions as of yet." This particular application needs both the Master and Slave API, so I had to go with the Wire library. This will cause me some problems later.

To test Wire API, I wrote a single routine that "plays catch" between two Arduinos. Whichever one has the "Ball", lights it's LED.

  • I compile once. Connect the serial port to one Arduino, download. Connect to the other Arduino, download. Get's tedious very quickly.
  • The initial master is gotten from Pin 5. After that the master and slave swap roles.
  • Note that I had to declare the Wire.onReceive(receiveEvent); even though I don't use the interrupt routine. That took a while to figure out.
  • It is just as gratifying watching the LEDs light up on the two Arduino's as it was for the very first LED blinker program :slight_smile:
  • There is a lot of output to the screen so you can follow along as the ball goes back and forth. Note this output for one Arduino (the initial master)
A
B
C
M1: passing the ball
M2: wait for slave...
recv: 1
M3: got it...
M4: and it is an ack; Slave now has the ball.
S1: waiting for ball
recv: 1
S2: got it...
S3: and it is the ball
S4: told master we got the ball
M1: passing the ball
M2: wait for slave...
recv: 1
M3: got it...
M4: and it is an ack; Slave now has the ball.
<and so on>

Next step: try seeding the random number generator on both Arduino's to see if a simple AnalogRead(0) works.

John

// for I2C stuff: http://www.gammon.com.au/forum/?id=10896
// for i2c lib:   http://dsscircuits.com/articles/arduino-i2c-master-library.html
#include "WProgram.h"
#include "Wire.h"

#define CONFIGPIN 5
#define THEBALL 0x88
#define GOTTHEBALL  0x66

static enum
  {
  master = 0,
  slave = 1,
  } state;
int myaddr = 1;
int destaddr = 2;

//===========================
void receiveEvent(int howMany)
  {
  Serial.print("recv: ");
  Serial.println(howMany, DEC);
  }

//===========================
void setup()
  {
  Serial.begin(9600);

  Serial.println("A");

// Pin 13 has an LED connected on most Arduino boards:
  pinMode(13, OUTPUT);
  pinMode(CONFIGPIN, INPUT);

  // the Config pin indicates who starts off as the master
  int v = digitalRead(CONFIGPIN);
  if (v == HIGH)
    {
    state = master;
    myaddr = 1;
    destaddr = 2;
    // the LED indicates who has the ball (the master)
    digitalWrite(13, HIGH);
    }
  else
    {
    state = slave;
    myaddr = 2;
    destaddr = 1;
    // the LED indicates who has the ball
    digitalWrite(13, LOW);
    }
  Serial.println("B");

  //Start the wire session using our own address
  Wire.begin(myaddr);

  //Even though receiveEvent is empty, got to use it in the setup
  Wire.onReceive(receiveEvent);

  // empty the input buffer of any garbage
  while (Wire.available() > 0)
    {
    Wire.receive();
    }

  Serial.println("C");
  }

//===========================
void loop()
  {
  if (state == master)
    {
    // send the ball to the slave
    Serial.println("M1: passing the ball");
    Wire.beginTransmission(destaddr);
    Wire.send(THEBALL);
    Wire.endTransmission();

    // wait for slave to acknowledge it has the ball
    Serial.println("M2: wait for slave...");
    int timeout = 0;
    const int maxtimeout = 500;
    while (timeout < maxtimeout && Wire.available() < 1)
      {
      delay(1);
      timeout++;
      }
    if (timeout >= maxtimeout)
      {
      Serial.println("M3: timeout, trying the send again");
      }
    else
      {
      Serial.println("M3: got it...");

      // check it is a good value (GOTTHEBALL)
      byte c = Wire.receive();
      if (c == GOTTHEBALL)
        {
        Serial.println("M4: and it is an ack; Slave now has the ball.");
        }
      else
        {
        Serial.print("M4: error unexpected byte: ");
        Serial.println(c, HEX);
        }

      // convert to a slave
      state = slave;

      // don't have the ball anymore, so clear the LED
      digitalWrite(13, LOW);
      }
    }
  else // state == slave
    {
    // wait for the incoming ball
    Serial.println("S1: waiting for ball");

    int count = 0;
    while (Wire.available() < 1)
      {
      delay(1);
      count++;
      if (count > 500)
        {
        count = 0;
        Serial.println("S2: still waiting...");
        }
      }
    Serial.println("S2: got it...");

    // consume the byte that was read
    byte c = Wire.receive();
    if (c == THEBALL)
      {
      Serial.println("S3: and it is the ball");
      }
    else
      {
      Serial.print("Sx: error unexpected byte: ");
      Serial.println(c, HEX);
      }

    //  send response to master
    Wire.beginTransmission(destaddr);
    Wire.send(GOTTHEBALL);
    Wire.endTransmission();
    Serial.println("S4: told master we got the ball");

    // convert to the master
    state = master;

    // we have the ball now, so indicate the we have it
    digitalWrite(13, HIGH);

    // wait for a while before passing the ball back...
    delay(500);
    }
  }

//===========================
int main()
  {
  init();
  setup();
  for (;;)
    {
    loop();
    }
  return 0;
  }