CSE, EEE, Engineering School, Notes, Notes

I2C BUS Communication and Address Finding

What and how I2C

I2C communication is interaction between two or more than two devices. For example, this communication can be between two arduino uno or an arduino uno and a nano or two arduino nano. Communication can be done between various devices.

This communication can be done by enrolling role to the devices. We have basically two roles to define here. One is the master and another is the slave. Constant back and forth between master and slave ensures communication and brings dynamic function to our project.

Now the question can be asked, what makes the I2C communication happen? Well in simple words I2C interface between the devices makes this dynamic communication to take place and gives us the ability to do various things.

Now, to describe the I2C interface or I2C BUS, it has 4 things.

  1. SDA or Serial Data Line
  2. SCL or Serial Clock Line
  3. 2 External Pull up resistance
Basic I2C interface structure

This SDA and SCL are the main two things of this interface, this 2 establishes the connection between devices. The more devices you want to connect you have to make a parallel connection between this two. Now we have A4 and A5 pins which are now I2C BUS pins. These two analog pins now act as a communication medium or communication pin between two or more devices. Regardless of arduino uno or nano, these two analog pins A4 and A5 will do the job of I2C BUS pins.Here one thing needs to said that, SDA here transmits data bidirectionally an SCL communicates between master and slave. It takes data to slave or it takes data from slave to the master. Also there is an I2C FIFO buffer which is also part of the I2C interface. This FIFO buffer is 32 Bit long and it helps to store the I2C communication information to make use of it later.

Master, slave and address

Initially we touched upon the two roles of master and slave. These roles playes pivotal part in communication. The term master and slave are quite self explanatory. Master acts as a main device or head device of the I2C interface and the connected other devices are the slave. This slave devices does the work and sends information to the master device. The thing we have to clear here is that there can be more than one master and more than one slave. Multiple master and slave can communicate and do jobs easily or breaks a huge works into pieces and makes parallel computing to do the jobs.

Now to differentiate between slaves we need to assign slave addresses to mark them. Because there will be multiple communication going on and if there isn’t a specific name or address given to the slaves then the data may not go to the proper device or it may not understand where to go in first place. So, the slaves are give 7 bit address ranging from 0 to 2^7-1 (127) or in hex 0x00 to 0x7E.

Simulation and operation

Now we simply have discussed the theoretical part here, but the question is will these things happen automatically? The answer is no. Arduino uno or nano won’t do these automatically. We have to tell arduino uno,nano mega to do those thing and to do those things we have to tell them through codes.

Now we will analyze a basic code for to illustrate I2C communication.

We here will use arduino uno as the master and arduino nano as the slave side.

Code for master side:


#include <Wire.h>
void setup() {
  Serial.begin(9600);
  Wire.begin();
}
 
void loop() {
  for (byte i = 0x00; i <= 0x3F; i++) {
    Wire.beginTransmission(i);
    if (Wire.endTransmission() == 0) {
      Serial.println(“Slave address: 0x” + String(i, HEX));
      delay(1000);
    }
  }
  exit(0);
}
 

Master Part

Here we will elaborate the code. There are two main functions one is setup and another is loop. Setup function is mainly used for initialization and the things we want to see at a single time. We see Serial.begin(9600) and Wire.begin(). Here Serial.begin initializes the serial monitor with 9600 baud rate and I2C communication or I2C interface is being initialized by Wire.begin. Now in loop function there is a for loop which goes from 0x00 to 0x3F and asks the I2C interface if there are any established declared devices connected.If there is then when the transmission will end it will return a zero value. So wire.beginTransmission sees if there are any connection, if there is then endTransmission returns 0 and it prints in slave address in HEX at the 11th line. If the codes find all the device then it exit itself.

Now in the slave side we will use arduino nano:


#include<Wire.h>
void setup()
{
  Wire.begin(0x13);
}
 
void loop()
{
 
}
Slave Part

Here will initiate the I2C interface by using Wire.begin and telling the interface that the address of the nano is 0x13 and afterwards if we want to access the the nano we can call it by its address and fetch data from it.

Now we will see a small simulation of it in proteus.

Proteus Simulation

Multiple slaves

Here we have selected arduino uno r3 and simulino nano from the library of proteus and we also included a serial monitor to observe the outcome.we can see that A4 and A5 pins are being shorted and in the code from both sides we have used wire.begin to trigger the I2C interface to start a communication when these two devices have been powered on. We double tapped arduino uno and nano and uploaded the hex file from arduino ide into the circuit.

From the above code we have seen that we have coded to name the nano 0x13. From the arduino uno serial monitor we see that the slave address is 0x13 which is our desired output.

Now we will observe multiple slaves with a master which will give us a more wide thought.

I2C Bus communication between mutiple devices

Here we see that we have two I2C one with PCF8574 and PCF8574A, one arduino nano and one simulino variant of arduino uno all these are slave and on the left there is the master arduino uno.

Code for master arduino uno:


#include <Wire.h>
void setup() {
Serial.begin(9600);
Wire.begin();
}
void loop() {
for (byte i = 0x00; i <= 0x3F; i++) {
Wire.beginTransmission(i);
if (Wire.endTransmission() == 0) {
Serial.println(“Slave address: 0x” + String(i, HEX));
delay(1000);
}
}
exit(0);
}
Master Uno

Code for slave 1


#include<Wire.h>
void setup()
{
Wire.begin(0x13);
}
void loop()
{
}
Slave Nano

Code for slave 2

#include<Wire.h>
void setup()
{
Wire.begin(0x15);
}
void loop()
{
}
Slave Uno

The rest two I2C device PCF8574 and PCF8574A address are set by setting their internal A0,A1 & A2 as ground which results there address to be 0x20 and 0x38.

As from the previous observation we ran the finding slave code in the master and we found our all four device I2C address.

Advance implementation

We only touched the surface level of I2C communication we can do many more things. Such as we can sense temperature from LM35 with arduino nano and we can see that result in arduino uno’s I2C display.The limits can only be set by you.