Arduino I2C Tutorial: Communication Between Two Arduino Boards

In our previous tutorial learned about SPI communication in Arduino. Today we will learn about another Serial Communication Protocol: I2C (Inter Integrated Circuits). Comparing I2C with SPI, I2C has only two wires while SPI uses four, and I2C can have Multiple masters and slaves, while SPI can have only one master and multiple slaves. So there are more than one microcontrollers in a project that need to be masters, then I2C is used. I2C communication is generally used to communicate with Gyroscope, accelerometer, barometric pressure sensors, LED displays, etc.

In this Arduino I2C tutorial, we will use I2C communication between two Arduino boards and send (0 to 127) values to each other by using a potentiometer. Values will be displayed on the 16x2 LCD connected to each of the Arduinos. Here, one Arduino will act as the Master and another one will act as the Slave. So let’s start with the introduction of communication between two Arduino using I2C.

Table of Contents

  • What is the I2C Communication Protocol?
  • How does I2C Communication Between Two Arduino Boards Work?
  • Where to use I2C Communication Between Arduinos?
  • I2C in Arduino: Pin Configuration and Setup
  • Components Required For Arduino I2C Tutorial
  • Circuit Diagram
  • Working Explanation of Communication between two Arduino using I2C
  • I2C Programming in Arduino
  • Master Arduino Programming Explanation
  • Slave Arduino Programming Explanation
  • Technical Summary and GitHub Repository
  • Frequently Asked Questions
  • Projects Related to Arduino-to-Arduino Communication

What is the I2C Communication Protocol?

The term IIC stands for “Inter Integrated Circuits”. It is normally denoted as I2C or I squared C or even as 2-wire interface protocol (TWI) at some places, but it all means the same. I2C is a synchronous communication protocol, meaning, both the devices that share the information must share a common clock signal. It has only two wires to share information out of which one is used for the cock signal and the other is used for sending and receiving data.

How does I2C Communication Between Two Arduino Boards Work?

I2C communication was first introduced by Philips. As said earlier, it has two wires, these two wires will be connected across two devices. Here, one device is called a master, and the other device is called a slave. Communication should and will always occur between two a Master and a Slave. The advantage of I2C communication is that more than one slave can be connected to a Master.

I2C Communication Working

The complete communication takes place through these two wires, namely, Serial Clock (SCL) and Serial Data (SDA).

Serial Clock (SCL): Shares the clock signal generated by the master with the slave

Serial Data (SDA): Sends the data to and from between the Master and slave.

At any given time, only the master will be able to initiate the communication. Since there is more than one slave in the bus, the master has to refer to each slave using a different address. When addressed, only the slave with that particular address will reply back with the information, while the others quit. This way, we can use the same bus to communicate with I2C between Arduinos.

The voltage levels of I2C are not predefined. I2C communication is flexible, which means the device that is powered by 5V, can use 5V for I2C, and the 3.3V devices can use 3v for I2C communication. But what if two devices that are running on different voltages, need to communicate using I2C? A 5V I2C bus can’t be connected to a 3.3V device. In this case , voltage shifters are used to match the voltage levels between two I2C buses.

There is a set of conditions that frame a transaction. Initialization of transmission begins with a falling edge of SDA, which is defined as ‘START’ condition in the diagram below, where the master leaves SCL high while setting SDA low.

I2C Start Stop Condition

As shown in the diagram above below,

The falling edge of SDA is the hardware trigger for the START condition. After this, all devices on the same bus go into listening mode.

In the same manner, the rising edge of SDA stops the transmission, which is shown as ‘STOP’ condition in the above diagram, where the master leaves SCL high and also releases SDA to go HIGH. So the rising edge of SDA stops the transmission.

I2C First Byte

R/W bit indicates the direction of transmission of the following bytes, if it is HIGH means the slave will transmit, and if it is low means the master will transmit.

Each bit is transmitted on each clock cycle, so it takes 8 clock cycles to transmit a byte. After each byte either sent or received, the ninth clock cycle is held for the ACK/NACK (acknowledged/not acknowledged). This ACK bit is generated by either the slave or the master, depending on the situation. For the ACK bit, SDA is set to low by the master or slave at the 9th clock cycle. So it is low, it is considered as an ACK otherwise NACK.

Introduction to I2C Message

Where to use I2C Communication Between Arduinos?

I2C communication is used only for short-distance communication. It is certainly reliable to an extent since it has a synchronised clock pulse to make it smart. This protocol is mainly used to communicate with sensor or other devices which has to send information to a master. It is very handy when a microcontroller has to communicate with many other slave modules using a minimum of only wires. If you are looking for a long-range communication, you should try RS232, and if you are looking for more reliable communication, you should try the SPI protocol.

I2C in Arduino: Pin Configuration and Setup

The image below shows the I2C pins present in Arduino UNO.

I2C in Arduino

I2C Line

Pin in Arduino

SDA

A4

SCL

A5

Before we get started into programming I2C using two Arduinos. We need to learn about the Wire library used in Arduino IDE.

The library <Wire.h> is included in the program to use the following functions for I2C communication.

1. Wire.begin(address):

Use: This library is used for making communication with I2C devices. This Initiate the Wire library and join the I2C bus as a master or slave.

Address: The 7-bit slave address is optional, and if the address is not specified, it joins the bus as a master like this [Wire.begin()].

2. Wire.read():

Use: This function is used to read a byte that was received from a master or slave device, either that was transmitted from a slave device to a master device after a call to requestFrom() or was transmitted from a master to a slave.

3. Wire.write():

Use: This function is used to write data to a slave or master device.

Slave to Master: Slave writes data to a master when the Wire.RequestFrom() is used in the master.

Master to Slave: For transmission from a master to a slave device, Wire.write() is used in-between calls to Wire.beginTransmission() and Wire.endTransmission().

Wire.write() can be written as:

  • Wire.write(value)

value: a value to send as a single byte.

  • Wire.write(string) :

string: a string to send as a series of bytes.

  • Wire.write(data, length):

data: an array of data to send as bytes

length: the number of bytes to transmit.

4. Wire.beginTransmission(address):

Use: This function is used to begin a transmission to the I2C device with the given slave address. Subsequently, build a queue of bytes for transmission with the write() function and then transmit them by calling the endTransmission() function. The 7-bit address of the device is transmitted.

5. Wire.endTransmission();

Use: This function is used to end a transmission to a slave device that was begun by beginTransmission() and transmits the bytes that were queued by Wire.write().

6. Wire.onRequest();

Use: This function gets called when a master requests data using Wire.requestFrom() from the slave device. Here we can include Wire.write() function to send data to the master.

7. Wire.onReceive();

Use: This function gets called when a slave device receives a data from a master. Here we can include Wire.read(); function to read the data sent from the master.

8. Wire.requestFrom(address,quantity);

Use: This function is used in the master to request bytes from a slave device. The function Wire.read() is used to read the data sent from the slave device.

address: the 7-bit address of the device to request bytes from

quantity: the number of bytes to request

Components Required For Arduino I2C Tutorial

  • Arduino Uno (2-Nos)
  • 16X2 LCD display module
  • 10K Potentiometer (4-Nos)
  • Breadboard
  • Connecting Wires

Tag » Arduino I2c Master Slave Library