What is I2C?
I2C or I2C is short for Inter-Integrated Circuit, a synchronous serial communication protocol developed by Phillips for communication between a fast Microcontroller and relatively slow peripherals (like Memory or Sensors) using just two wires. Hence, it is sometimes also known as TWI (Two Wire Interface). Using I2C, you can transmit data at rates 100 kbit/s (clock 100 kHz – Standard Mode), 400 kbit/s (clock 400 kHz – Fast Mode), 1 Mbit/s (clock 1 MHz – Fast Mode Plus) and 3.4 Mbit/s (clock 3.4 MHz – High Speed Mode). This may not seem much but it is sufficient for interfacing sensors, memories and displays at small distances.
I2C Bus
The I2C Bus consists of two wires called the Serial Data (SDA) and the Serial Clock (SCL). Data is transmitted through the SDA line while the SCL line is used to synchronize the devices with the clock signal. Both these bus lines are open-drain drivers and hence you have to use pull-up resistors to keep them HIGH.
There are two types of devices that connect to the I2C Bus: Master and Slave. Bus Masters are responsible for sending and receiving data to and from the slave devices. The clock signal is also supplied by the master. I2C network supports multiple masters and multiple slaves (but we usually see single master and multiple slaves). Each slave device connected to the I2C bus has a unique 7-bit address. Using this address, master selects a particular slave for data transmission (send or receive) and the selected slave responds according to request. I made an extensive tutorial on basics of I2C Communication. For more information on that, visit “Basics of I2C Communication”.
I2C in Arduino
Arduino supports I2C Communication. If you take a look at the pinout of Arduino UNO from the tutorial “ARDUINO UNO PINOUT”, Analog Input pins A4 and A5 have an alternative function of I2C. The A4 pin acts as SDA while the A5 pin acts as SCL. In R3 of original Arduino UNO, there are two more pins near Digital IO Pin 13 (near the USB socket), dedicated to SDA and SCL. If you are using any other board then the following table will be useful to you as it describes the I2C pins on all the popular Arduino boards. ATmega328P Microcontroller used in Arduino UNO and Nano supports I2C Data Transfer speeds up to 400 kHz.
How to use Arduino I2C Interface?
To demonstrate the working of I2C in Arduino, let us build a small circuit. In this demo, I connected two Arduino UNO boards to communicate over I2C Bus. To make things interesting and actually see the communication, I added a couple of LEDs and Potentiometers (one set for each UNO Board). The potentiometers are connected to respective Analog Input pins (A0) and the LEDs are connected to a Digital IO Pin with PWM (Pin 9). One UNO board is configured as I2C Bus Master and the other UNO is configured as a Slave device.
When I adjust the potentiometer connected to the Master Arduino UNO, it captures the analog reading from the POT, converts it into a digital value (in the range of 0 – 1023), maps it to a proper PWM value (in the range of 0 – 255) and transmits this value to the Slave Arduino over I2C Bus. The Slave Arduino, upon receiving the PWM Value, adjusts the brightness of its LED. Also, the Slave Arduino Sends its own potentiometer value converted to PWM number to the Master Arduino (up on request from the Master). Master Arduino then reads the PWM value from the Slave Arduino and adjusts the brightness of its LED according to that value. This communication continues and repeats seamlessly over the I2C Bus.
This is a simple circuit just to understand the Arduino I2C Communication. You can modify the circuit to make a complex I2C Bus Network with different Slave Devices like I2C LCD, EEPROM IC, BMP180 Barometric Pressure Sensor etc. (a weather station with data logging).
Components Required
Arduino UNO x 2 10 kΩ Potentiometer x 2 5mm LED x 2 330Ω Resistor x 2 Breadboard Connecting Wires Breadboard Power Supply (optional)
Circuit Diagram
The following image shows the circuit diagram for Arduino I2C demonstration between two Arduino UNO boards.
Code
In order to program the I2C peripheral in Arduino, you need to understand the Wire library. This is the main library that allows you to communicate with I2C or TWI Devices over the I2C Bus (SDA and SCL lines).
Wire Library
It comes with Arduino IDE and you don’t have to download anything extra. All you have to do is include the Wire library to work with I2C in Arduino. #include <Wire.h> The Wire library provides you with 10 functions for developing I2C related applications. They are:
Wire.begin() Wire.requestFrom() Wire.beginTransmission() Wire.endTransmission() Wire.write() Wire.available() Wire.read() Wire.SetClock() Wire.onReceive() Wire.onRequest()
Let us see in detail about some of the important Wire Library functions now.
Wire Library Functions
Wire.begin() Use this function to initiate the I2C Communication. If you pass the 7-bit device address as an argument to this function, then the device will join the I2C bus as Slave else it will join as Master.
Wire.begin() – Master Wire.begin(address) – Slave
Wire.beginTransmission(address) Use this function to begin data transmission to a slave device with the specified address. Wire.write() Once you begin the transmission using above function you can now start sending the actual data using the Wire.write() function. You can also use this function to write data from Slave to Master when master uses Wire.RequestFrom() function.
Wire.write(value) – Send a single Byte value Wire.write(string) – Send a series of Bytes in the form of string Wire.write(data, length) – Send an array of data of specified length
Wire.endTransmission() To end the I2C data transmission, use Wire.endTransmission() function. Wire.read() Use this function to read a byte of data that was transmitted from Master to Slave or from Slave to Master when Master makes a call to Wire.requestFrom() function. Wire.requestFrom() Master I2C Device uses this function to request bytes of data from a slave device. Use the Wire.read() function to retrieve the data.
Wire.requestFrom(address, quantity) – Request a number of bytes of data mentioned by quantity from a slave device with address specified in address field.
Wire.onReceive() This is a handler function used to define a function which is called when Slave receives data from Master. Wire.onRequest() This is a handler function used to define a function which is called when Master requests data from slave.
Master Code
Using the above-mentioned functions, I wrote a simple code for Master Arduino to send the PWM value and also request a byte of data from the Slave.
Slave Code
In the Slave Arduino code, I defined the Slave address as 0x14. It can be any value less than 128. An important point to note about ArduinoI2C Wire Library I that it uses 7-bit I2C Address without the Read / Write bit. So, if you have an 8-bit address (which includes the R / W bit), right shift the address by 1 and then use it in the Wire Library. The library will automatically adjust the address depending on the Read or Write operation. Also, make sure that the slave address is unique and no two slaves should have the same address. Coming back to the code, I declared two functions “DataReceive” and “DataRequest” to be called when data is received by the slave or data is requested from the slave. The data received by the Slave in the DataReceive function contains the PWM value sent by the Master. The data to be transmitted through the DataRequest function is the PWM value from Slave to Master.
Conclusion
A simple two-way communication between two Arduino Boards using I2C Communication is demonstrated in this tutorial. You learned about Arduino I2C Peripheral, few important basics of I2C Communication, the Wire Library and also how to setup and use Arduino I2c Communication. Comment * Name * Email * Website
Δ