I2C Wire Chat Between Two Arduinos

Someone asked me the other day if it was possible to have a ‘chat’ between Arduinos using the I2C Wire library. I came up with  ‘proof of concept’ code called ‘I2C Wire Chat Between Two Arduinos’. Here is the sketch:

I2C Wire Chat Between Two Arduinos

/* 
 
 I2C wire chat
 From: earl@microcontrollerelectronics.com

 Analog Pin 5 SCL
 Analog Pin 4 SDA
 Common ground

*/

#include <Wire.h>
#define WireDevice 8

String buffer;
int mode;

void setup() { Serial.begin(9600); }

void loop() {
  while (Serial.available()) {
    char c = Serial.read();
    if (c != '\n') {
      if (c == '\r') continue;
      buffer += c;
      continue;
    }
    else {  
      buffer += '\0';
      if (buffer[0] == '#') {
        if (buffer[1] == 'm') {
          if (mode != 'm') {
            mode = 'm';
            master();
            Serial.println("Master mode");
          }
        }
        if (buffer[1] == 's') {
          if (mode != 's') {
            mode = 's';
            slave();
            Serial.println("Slave mode");
          }
        }
        buffer = "";
        continue;
      }
      if (mode == 'm') {
        Wire.beginTransmission(WireDevice); 
        int i = 0;
        while (buffer[i]) { Wire.write(buffer[i]); i +=1; }
        Wire.endTransmission();    
      }
      else Serial.println("Invalid Mode");
      buffer = "";
    } 
  }
}

void master() {
  Wire.begin();
  Serial.println("Master Initialized");
}

void slave() {
  Wire.begin(8);                
  Wire.onReceive(receiveEvent);
  Serial.println("Slave Initialized");
}

void receiveEvent(int howMany) {
  while (1 < Wire.available()) {
    char c = Wire.read();
    Serial.print(c);     
  }
  char c = Wire.read();
  Serial.println(c);     
}

Setup two Arduinos connected by a length of CAT5 cable (you really only need 3 wires). Connect Analog Pins 5 (SCL), 4 (SDA) and Ground as shown in this Fritzing diagram:

I2C Wire Chat Between Two Arduinos

I2C Wire Chat Between Two Arduinos

Make sure each serial port is set to 9600 BAUD and type: #s in one Arduino and #m in the other making sure that ‘New Line’ is sent as the end character. This will put one in slave mode and the other in master mode. Due to the design of the I2C Wire library one has to be master and one slave. Only the master can send data (the slave receives), so it is not simultaneous transmit/receive. Whatever is typed in the master serial console is sent to the slave which displays it on its serial console. To switch back and forth (master <=> slave) just alternate the #s and #m. So you can in essence have a ‘chat’ with the I2C Wire library.

It basically functions the same as a Walkie-talkie radio.

One could even take the sketch further to automatically switch the master to slave and slave to master. For example, when the master is finished it could send a # as the last character which could function as the toggle. I will leave it to the reader to implement this. 😎

Well.. OK.. just so you can see how the code develops, here is the final version with the ‘toggle’ master/slave being the ‘#’ as the last character in the transmission buffer:

I2C Wire Chat Between Two Arduinos  [Final Version]

/* 
 
 I2C wire chat
 From: earl@microcontrollerelectronics.com

 Analog Pin 5 SCL
 Analog Pin 4 SDA
 Common ground

*/

#include <Wire.h>
#define WireDevice 8

String buffer;
int mode;

void setup() { 
  Serial.begin(9600);
  mode = 's';
  toggle_mode();
}

void loop() {
  while (Serial.available()) {
    char c = Serial.read();
    if (c != '\n') {
      if (c == '\r') continue;
      buffer += c;
      continue;
    }
    else {  
      buffer += '\0';
      if (buffer[0] == '#') {
        if (buffer[1] == 'm') {
          if (mode != 'm') toggle_mode();
        }
        if (buffer[1] == 's') {
          if (mode != 's') toggle_mode();
        }
        buffer = "";
        continue;
      }
      if (mode == 'm') {
        Wire.beginTransmission(WireDevice); 
        int i = 0;
        while (buffer[i]) { Wire.write(buffer[i]); i +=1; }
        Wire.endTransmission();    
        i -= 1;
        if (buffer[i] == '#') toggle_mode();
      }
      else Serial.println("Invalid Mode");
      buffer = "";
    } 
  }
}

void toggle_mode() {
  if (mode != 's') {
    mode = 's';
    slave();
    Serial.println("Slave mode");
  }
  else {
    mode = 'm';
    master();
    Serial.println("Master mode");
  }
}

void master() {
  Wire.begin();
  Serial.println("Master Initialized");
}

void slave() {
  Wire.begin(8);                
  Wire.onReceive(receiveEvent);
  Serial.println("Slave Initialized");
}

void receiveEvent(int howMany) {
  while (1 < Wire.available()) {
    char c = Wire.read();
    Serial.print(c);     
  }
  char c = Wire.read();
  if (c == '#') {
    Serial.println();
    toggle_mode();
  }
  else Serial.println(c);     
}

Over and Out!

Leave a Reply

Your email address will not be published.