Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
49 views

How I2C Communication Works and How To Use It With Arduino

The document discusses Inter-Integrated Circuit (I2C) communication, how it works, and an example of using it with an Arduino board. I2C allows communication between multiple devices over just two wires and each device has a unique address. It transmits data in 8-bit sequences with an acknowledgement bit following each sequence. The document provides an example using an Arduino to read acceleration data from sensors over I2C by writing/reading the sensors' internal registers.

Uploaded by

Souvik Paul
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
49 views

How I2C Communication Works and How To Use It With Arduino

The document discusses Inter-Integrated Circuit (I2C) communication, how it works, and an example of using it with an Arduino board. I2C allows communication between multiple devices over just two wires and each device has a unique address. It transmits data in 8-bit sequences with an acknowledgement bit following each sequence. The document provides an example using an Arduino to read acceleration data from sensors over I2C by writing/reading the sensors' internal registers.

Uploaded by

Souvik Paul
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 7

Inter-Integrated Circuit (I2C or I2C or Two wire interface)

How I2C Communication Works and How to Use It with Arduino


Here we will learn how the I2C communication protocol works and also we will make a practical
example of it with the Arduino Board and a sensor which uses this protocol. You can watch the
following video or read the written tutorial below.

Overview

The I2C communication bus is very popular and broadly used by many electronic devices
because it can be easily implemented in many electronic designs which require communication
between a master and multiple slave devices or even multiple master devices. The easy
implementations comes with the fact that only two wires are required for communication
between up to almost 128 (112) devices when using 7 bits addressing and up to almost 1024
(1008) devices when using 10 bits addressing.

How It Works

How is it possible, a communication between so many devices with just to wires? Well each
device has a preset ID or a unique device address so the master can choose with which devices
will be communicating.

The two wires, or lines are called Serial Clock (or SCL) and Serial Data (or SDA). The SCL line
is the clock signal which synchronizes the data transfer between the devices on the I2C bus and
it’s generated by the master device. The other line is the SDA line which carries the data.
The two lines are “open-drain” which means that pull up resistors needs to be attached to them
so that the lines are high because the devices on the I2C bus are active low. Commonly used
values for the resistors are from 2K for higher speeds at about 400 kbps, to 10K for lower speed
at about 100 kbps.

I2C Protocol

The data signal is transferred in sequences of 8 bits. So after a special start condition occurs
comes the first 8 bits sequence which indicates the address of the slave to which the data is being
sent. After each 8 bits sequence follows a bit called Acknowledge. After the first Acknowledge
bit in most cases comes another addressing sequence but this time for the internal registers of the
slave device. Right after the addressing sequences follows the data sequences as many until the
data is completely sent and it ends with a special stop condition.

Let’s take even closer look at these events. The start condition occurs when data line drops low
while the clock line is still high. After this the clock starts and each data bit is transferred during
each clock pulse.
The device addressing sequence stars with the most significant bit (MSB) first and ends with the
least significant bit (LSB) and it’s actually composed of 7 bits because the 8 th bit is used for
indicating whether the master will write to the slave (logic low) or read from it (logic high).

The next bit AKC/ NACK is used by the slave device to indicate whether it has successfully
received the previous sequence of bits. So at this time the master device hands the control of the
SDA line over to the slave device and if the slave device has successfully received the previous
sequence it will pull the SDA line down to the condition called Acknowledge. If the slave does
not pull the SDA line down, the condition is called Not Acknowledge, and means that it didn’t
successfully received the previous sequence which can be caused by several reasons. For
example, the slave might be busy, might not understand the received data or command, cannot
receive any more data and so on. In such a case the master device decides how it will proceed.

Next is the internal registers addressing. The internal registers are locations in the slave’s
memory containing various information or data. For example the ADX345 Accelerometer has a
unique device address and addition internal registers addresses for the X, Y and Z axis. So if we
want to read the data of the X-axis, first we need to send the device address and then the
particular internal register address for the X-axis. These addresses can be found from datasheet
of the sensor.

After the addressing, the data transfer sequences begin either from the master or the slave
depending of the selected mode at the R/W bit. After the data is completely sent, the transfer will
end with a stop condition which occurs when the SDA line goes from low to high while the SCL
line is high.
Arduino I2C Example

As an example I will use the GY-80 breakout board which consists of 5 different sensors and the
GY-521 breakout board which consists of 3 different sensors. So we can get data from 8
different sensors with just two wires with the I2C bus.

Here’s how we will connect the boards. The Serial Clock pin of the Arduino Board will be
connected to the Serial Clock pins of the two breakout boards, the same goes for the Serial Data
pins and we will power the boards with the Gnd and the 5V pin from the Arduino Board. Note
here we are not using pull-up resistors because the breakout boards already have.
Now in order to communicate with these chips or sensors we need to know their unique
addresses. We can find them from the datasheets of the sensors. For the GY-80 breakout board
we have the following 4 addresses: a hexadecimal 0x53 for the 3 Axis Accelerometer sensor, a
hexadecimal 0x69 for the 3 Axis Gyro, a hexadecimal 0x1E for the 3 Axis Magnetometer and a
hexadecimal 0x77 for the Barometer and Thermometer sensor.

For the GY-521 breakout board we have only one address and that’s a hexadecimal 0x68. We
can also get or check the addresses using the Arduino I2C Scanner sketch which can be found
from the Arduino official website. So here if we upload and run that sketch, we will get the
addresses of the connected devices on the I2C bus.

Sensor Part Number I2C Address

3 Axis Accelerometer Analog Devices ADXL345 0x53

3 Axis GyroST Microelectronics L3G4200D 0x69

3 Axis Magnetometer Honeywell MC5883L 0x1E

Barometer + Thermometer Bosch BMP085 0x77


After we have found the addresses of the devices we also need to find the addresses of their
internal registers in order to read the data from them. For example if we want to read the data for
the X axis from the 3 Axis Accelerometer sensor of the GY-80 breakout board, we need to find
the internal register address where the data of the X axis is stored. From the datasheet of the
sensor, we can see that data for the X axis is actually stored in two registers, DATAX0 with a
hexadecimal address 0x32 and DATAX1 with a hexadecimal address 0x33.

Arduino I2C Code

Now let’s make the code that will get the data for the X axis. So we will use the Arduino Wire
Library which has to be including in the sketch. Here first we have to define the sensor address
and the two internal registers addresses that we previously found. The Wire.begin() function will
initiate the Wire library and also we need to initiate the serial communication because we will
use the Serial Monitor to show the data from the sensor.

In the loop() we will start with the Wire.beginTransmission() function which will begin the
transmission to the particular sensor, the 3 Axis Accelerometer in our case. Then with the
Wire.write() function we will ask for the particular data from the two registers of the X axis. The
Wire.endTransmission() will end the transmission and transmit the data from the registers. Now
with the Wire.requestFrom() function we will request the transmitted data or the two bytes from
the two registers.

The Wire.available() function will return the number of bytes available for retrieval and if that
number match with our requested bytes, in our case 2 bytes, using the Wire.read() function we
will read the bytes from the two registers of the X axis. At the end we will print the data into the
serial monitor. Here’s that data but keep in mind that this is raw data and some math is needed to
be done in order to get the right values of the X axis. You can find more details for that in my
next tutorial for using accelerometers with the Arduino Board because I don’t want to overload
this tutorial because its main goal was to explain how the Arduino I2C communication works.

How I2C Communication Protocol Works - Arduino I2C Tutorial


#include <Wire.h>
int ADXLAddress = 0x53;

// Device address in which is also included the 8th bit for selecting the mode, read in this case.

#define X_Axis_Register_DATAX0 0x32 // Hexadecimal address for the DATAX0 internal register.

#define X_Axis_Register_DATAX1 0x33 // Hexadecimal address for the DATAX1 internal register.

#define Power_Register 0x2D // Power Control Register

int X0,X1,X_out;

void setup() {
Wire.begin(); // Initiate the Wire library

Serial.begin(9600);

delay(100); // Enable measurement

Wire.beginTransmission(ADXLAddress);

Wire.write(Power_Register); // Bit D3 High for measuring enable (0000 1000)

Wire.write(8);

Wire.endTransmission();

void loop() {

Wire.beginTransmission(ADXLAddress); // Begin transmission to the Sensor

//Ask the particular registers for data

Wire.write(X_Axis_Register_DATAX0);

Wire.write(X_Axis_Register_DATAX1);

Wire.endTransmission(); // Ends the transmission and transmits the data from the two registers

Wire.requestFrom(ADXLAddress,2); // Request the transmitted two bytes from the two registers

if(Wire.available()<=2) {

X0 = Wire.read(); // Reads the data from the register

X1 = Wire.read();

Serial.print("X0= ");

Serial.print(X0);

Serial.print(" X1= ");

Serial.println(X1);

You might also like