Index
Introduction
I2C (Inter-Integrated Circuit) is a serial communication protocol used for devices to communicate with each other. It was developed by Philips Semiconductors (now NXP Semiconductors) in the 1980s as a way for chips on a circuit board to talk to each other.
I2C is a synchronous protocol, meaning that devices communicate with each other at the same clock speed. It uses two wires for communication: a data line (SDA) and a clock line (SCL). Multiple devices can be connected to the same two wires, and each device has a unique address so that it can be identified on the bus.
I2C supports two modes: master and slave. The master initiates all communication on the bus, while the slave responds to requests from the master. The master can also send commands to the slave to read or write data.
I2C is commonly used in embedded systems and for communication between chips on a circuit board, such as between a microcontroller and a sensor or an EEPROM (electrically erasable programmable read-only memory). It is a popular protocol due to its simplicity and low hardware requirements.
I2C in Arduino
Here’s how to use I2C in different Arduino boards:
- Arduino Uno: The Arduino Uno has two pins, A4 (SDA) and A5 (SCL), that can be used for I2C communication. To use I2C on the Arduino Uno, you can use the Wire library, which is included with the Arduino IDE. You can use the
Wire.begin()
function to start I2C communication, and then use theWire.write()
andWire.read()
functions to send and receive data. - Arduino Mega: The Arduino Mega has four pins, 20 (SDA), 21 (SCL), 70 (SDA1), and 71 (SCL1), that can be used for I2C communication. To use I2C on the Arduino Mega, you can use the same Wire library as the Uno, but you need to specify which I2C bus to use. For example, to use the first I2C bus, you can use the
Wire.begin()
function with the parameterWire.begin(0)
. - Arduino Nano: The Arduino Nano has the same pins as the Uno (A4 and A5) for I2C communication, and can be used in the same way with the Wire library.
Example
here’s a simple example of how to use the I2C communication protocol with an Arduino Uno and a simple I2C device, such as a temperature sensor or an EEPROM memory chip.
In this example, we’ll use the built-in Wire library to communicate with a device that has a known I2C address. For the purpose of this example, let’s assume that the device has an I2C address of 0x68.
#include <Wire.h>
void setup() {
Wire.begin(); // initialize I2C bus
Serial.begin(9600); // initialize serial communication
}
void loop() {
Wire.beginTransmission(0x68); // begin communication with device at address 0x68
Wire.write(0x00); // send the address of the register to read (in this case, register 0x00)
Wire.endTransmission(); // end transmission
Wire.requestFrom(0x68, 2); // request two bytes of data from the device at address 0x68
while(Wire.available()) {
byte msb = Wire.read(); // read the most significant byte
byte lsb = Wire.read(); // read the least significant byte
int temperature = (msb << 8) | lsb; // combine the two bytes into an integer value
Serial.print("Temperature: ");
Serial.print(temperature);
Serial.println(" degrees Celsius");
}
delay(1000); // wait for one second before requesting data again
}
Explanation
here’s a brief explanation of the code line by line:
#include <Wire.h>
– This line includes the Wire library, which provides an easy way to communicate using the I2C protocol.void setup() {
– This line begins the setup function.Wire.begin();
– This line initializes the I2C bus using the Wire library’s begin function, which sets up the I2C hardware on the Arduino Uno.Serial.begin(9600);
– This line initializes serial communication at a baud rate of 9600, which is used to display temperature data on the serial monitor.}
– This line ends the setup function.void loop() {
– This line begins the loop function.Wire.beginTransmission(0x68);
– This line begins an I2C communication transaction with the device at address 0x68.Wire.write(0x00);
– This line sends the address of the register to read (in this case, register 0x00) to the device.Wire.endTransmission();
– This line ends the I2C communication transaction.Wire.requestFrom(0x68, 2);
– This line requests two bytes of data from the device at address 0x68.while(Wire.available()) {
– This line begins a while loop that executes as long as there is data available from the device.byte msb = Wire.read();
– This line reads the most significant byte (MSB) of the temperature data from the device.byte lsb = Wire.read();
– This line reads the least significant byte (LSB) of the temperature data from the device.int temperature = (msb << 8) | lsb;
– This line combines the MSB and LSB of the temperature data into an integer value representing the temperature.Serial.print("Temperature: ");
– This line prints the string “Temperature: ” to the serial monitor.Serial.print(temperature);
– This line prints the temperature value to the serial monitor.Serial.println(" degrees Celsius");
– This line prints the string ” degrees Celsius” to the serial monitor and creates a new line.}
– This line ends the while loop.delay(1000);
– This line causes the program to wait for one second before requesting temperature data again.}
– This line ends the loop function.
Overall, this code uses the Wire library to communicate using the I2C protocol with a device at address 0x68, which is assumed to be a temperature sensor or EEPROM memory chip. The code requests two bytes of temperature data from the device, combines the bytes into an integer value representing the temperature, and then prints the temperature to the serial monitor. The program then waits for one second before requesting temperature data again.
Inbuilt I2C functions
Arduino provides a built-in library called “Wire” that provides functions for communicating using the I2C protocol. Here are some of the most commonly used functions from the Wire library:
Wire.begin()
: Initializes the I2C bus and sets the Arduino as a master device.Wire.beginTransmission(address)
: Begins an I2C transaction with the device at the specified address. This function returns a boolean value indicating whether the transmission was successful.Wire.write(data)
: Sends data over the I2C bus. Data can be a byte, an array of bytes, or a string.Wire.endTransmission()
: Ends an I2C transmission and waits for the device to respond. This function returns an integer value indicating the success or failure of the transmission.Wire.requestFrom(address, length)
: Requests a specified number of bytes from the device at the specified address. This function returns the number of bytes received.Wire.read()
: Reads a byte of data from the I2C bus. This function returns an integer value representing the byte read from the bus.Wire.onReceive(handler)
: Sets a function to be called when the Arduino receives I2C data. The function should take an integer argument representing the number of bytes received.Wire.onRequest(handler)
: Sets a function to be called when the Arduino is requested to send I2C data. The function should return the number of bytes to send.Wire.setClock(clockFrequency)
: Sets the clock frequency of the I2C bus. The clock frequency should be specified in hertz.Wire.setTimeout(timeout)
: Sets the timeout value for I2C transactions. The timeout value should be specified in microseconds.Wire.available()
: Returns the number of bytes available to be read from the I2C bus.Wire.peek()
: Returns the next byte of data on the I2C bus without removing it from the buffer.Wire.flush()
: Clears the I2C buffer.