Communicating between two Arduino boards using I2C bus
There are many different forms of digital communication protocols and they differ based on application. I2C and SPI protocol are commonly recognized as ‘small protocol’ relative to such Ethernet, USB, SATA, PCI-E protocol bus and etc that their transmission rate is up to hundreds or thousands Mbits/s. However, we couldn’t forget the purpose of these kinds of protocols bus. ‘Big protocol’ is employed as communication between systems, ‘small protocols’ is used as communication between IC within systems. There is no evidence that ‘small protocols’ is replaced necessarily by these ‘big protocols’. Existence and flexibility of SPI and I2C reflect the idea of ‘Enough is enough’.
I2C (pronounced I-squared-C) created by Philips Semiconductors(now NXP) and commonly written as “I2C” stands for Inter Integrated Circuit and allows communication of data between micro-controller and peripheral unit over two wires. In this master-host communication mode, multiple I2C devices can be connected to I2C bus, which is identified by assigned unique address.
I2C is serial bus which is constituted of data line(SDA- Serial Data line) and clock line(SCL- serial clock line) ,with which microcontroller and controlled IC, IC and IC are able to communicate bidirectional at the data transmission rate up to 100kb/s. Varieties of controlled IC is connected to this bus in parallel, just like telephone is connected up when its number is dialed up, each IC connected to I2C bus has a unique address. In the procedure of data transmission, IC connected to I2C bus can be either master(slave) or transmitter(receiver) at the same time which depends on the function it performs. It is obvious that two or more masters are not allowed.
Here we do a simple I2C experiment in which I2C bidirectional communication is completely demonstrated. Character string “light is” and byte x which is 0 or 1 is sent from master device to slave device repeatingly. When slave device receive the data, it is displayed on the serial monitor as below. Then the byte x is transmitted to master and assigned to variable c when slave is requested data by master. Master judge whether variable c is 1 or 0, master light up a led when c is 1.
Wire library is used to communicate with I2C devices. On most Arduino board, Arduino UNO or compatible, SDA is on analog input 4 pin. SCL is on analog input 5 pin. On Arduino mega , SDA is on digital pin 20 and SCL is on digital pin 21.Please note sending function in old Arduino IDE v22 I use now is send(),receiving function is receive(). Up-to-date Arduino IDE V1.0 sending is write(), receiving is read().
SCL, SDA and GND on two Arduino board are connected together using jumper wires, VCC should connected for sharing one source if two Arduino power are not supplied individually. SDA is on analog input 4 pin. SCL is on analog input 5 pin.If only using one I2C device, the pull-up resistors are (normally) not required, as the ATmega328 microcontroller in our Arduino has them built-in. However if you are running a string of devices, use two 10 kilo ohm resistors.
Arduino Master Program
/* Character string “light is” and byte x which is 0 or 1 is sent from master device to slave device repeatingly. When slave device receive the data, slave is requested data by master, byte x is transfered to master and assigned to variable c. Master program judge whether c is 1 or 0, master light up a led when c is 1, or it is off.*/
#include < Wire.h > //declare I2C library function
#define LED 13
byte x = 0; //variable x determine whether led on master is on or off
Wire.begin(); // join the I2C bus as master
pinMode(LED,OUTPUT); // initialize the digital pin 13 as output
Wire.beginTransmission(4); //begin a transmission to slave device 4
Wire.send(“light is “); // send character string “light is ”
Wire.send(x); // send one byte data to slave
Wire.endTransmission(); // end a transmission to slave
x++; //variable x plus one
if(x==2) //if variable x value is 2, assign 0 to variable x
delay(1000); //delay one second
Wire.requestFrom(4, 1); //request one byte from slave 4
while(Wire.available()>0) // when data is received from slave to master
byte c = Wire.receive(); //receive one byte from slave and assign to variable c
//if c is 1, light up led
Arduino Slave Program
/*Display the data packet from master on serial monitor and transfer last byte of it to master*/
#include <Wire.h> //declare I2C library function
int x; //variable x determine whether led on master is on or off//
Wire.begin(4); //join I2Cbus as slave with identified address
Wire.onReceive(receiveEvent); //register a function to be called when slave receive a transmission from master//
Wire.onRequest(requestEvent); //register a function when master request data from this slave device//
Serial.begin(9600); //set serial baud rate
//when slave receive string from master, trigger this event.
void receiveEvent(int howMany)
while( Wire.available()>1) // execute repeatedly until last byte left in the data packet from master//
char c = Wire.receive(); // receive data from master and assign it to char c
Serial.print(c); // display char c on serial monitor
//receive last byte of data packet from master
x = Wire.receive(); // receive last data from master and assign it to int x
Serial.println(x); // display int x on serial monitor
//trigger this event when master request data from slave,
//transfer last byte of data packet receiving from master to master