Hello, Dejan Nedelkovski here from HowToMechatronics.com. In this tutorial 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. 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 amaster and multiples slave
devices or even multiple master devices. The easy implementation comes with the fact
that only two wires are required for
communication between up to almost
128 (112) devices when using 7-bit addressing and up to almost
1024 (1008) devices when
using 10 - bit addressing. How is that
possible?
Well each device has a preset ID or a unique
device address so the master can choose
with which device will be communicating.
The two wires or lines are called
Serial Clock (SCL) and Serial Data (SDA). The SCL line is the clock signal which
synchronize data transfer between the
devices on the I2C bus and it's
generated by the master device. The other
line is 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
a higher speeds at about 400 kbps
second, up to
10 K for lower speeds at about
100 kbps.
Okay now let's see the data protocol of the
I2C bus. The data signal is transferred
in sequences of 8 bits. So
after 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
of slave device. After the addressing
sequences follows the data sequences as
many until the data is completely and it
ends with a speacial stop condition.
Okay let's take even closer look at
these events. The start condition occurs when
the 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 starts with the most
significant bit first and end with
the least significant bit and it's actually
composed of 7bits because the 8th
bit is used for indicating whether the
master will write to the slave (logic low)
or read from it (logic high).
The next bit Acknowledge is
used by the slave device to indicate
whether it has successfully received the
previous sequence of bits. So 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
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
ADXL345 accelerometer has a unique device
address and additional internal
registers addresses for the X, Y and Z axes.
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. This
addresses can be found from the
datasheet of the sensor. After the addressing the data transfers sequences begin
either from the master or the slave
depending on the selected mode at the
Read / Write 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. That's how the  I2C communication
protocol works and now let'a make an
example and demonstrate it using the Arduino Board and some sensors. So as an example
I will use the GY - 80 breakout board
which consists five differences sensors and the
GY - 521 breakout board which consists three
different sensors. So we can get data from
eaight 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 and the same goes for the
Serial Data pins and also we will power
the boards with the Ground and 5V
pins from the Arduino board. Note
here that 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 four addresses: a hexadecimal 0x53
for the three-axis accelerometer,  a hexadecimal 0x69
for 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 the hexadecimal 0x68. We can also
get or check the addresses using
I2C Scanner sketch which can be
found from the Arduino official website.
So if we upload and run that sketch we will
get the addresses of the connected
devices on the I2C bus. Ok so 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 the data for the X Axis is actually
stored in two registers, DATAX0 with a hexadecimal address 0x32 and DATAX1 a hexadecimal address 0x33.
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 included in the
sketch. Here first we have to define the
sensor address
and the two internal register addresses that
we previously found. The Wire.begin()
function will initiate the Wire library
and we also 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() function will end
transmission and transmit the data from
the registers. Now with the Wire.requestFrom() function we will requires
the transmitted data or the two bytes from
the registers.
Wire.available() function will return the
number of bytes available for retrieval
and if that number match with our requested bytes, in our case two bytes,
using the Wire.read() function we will
read the bytes from the registers of the
X axis. At the end we will print the data
in the serial monitor. Here's that data
but keep in mind that these 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 the I2C communication
works.
