Imagine you have two Arduinos, and you want them to talk to each other—maybe one collects data, and the other controls a motor based on that data. There could be many reasons where you may have to use multiple arduinos to communication with each other and there could be many ways to accomplish this task. But how do they communicate? That’s where I2C comes in, which is one of the many ways to let two microcontrollers communicate with each other.
It’s like a conversation between two friends, where one listens and the other speaks, taking turns. By using I2C communication, you can connect multiple devices without using a ton of wires or running out of pins. It’s neat, efficient, and a smart way to get your Arduinos to work together as a team. Let’s dive in and see how we can make one Arduino the listener, or “slave,” in this setup, ready to respond to the other.
Hardware setup
For this example, our aim is to show how you can use Arduino as i2c Slave more than focusing on how to set the Arduino as a Master. You may have already used the Arduino as i2c Master when you try to interface the Arduino with other i2c sensors or peripherals like the i2c MPU6050 or DS1307 RTC module or DS3231 RTC module. These all behave like i2c Slaves and when you try to communicate with them using Arduino, you are basically letting Arduino behave like a master which asks data from the slaves.
But to make the example simple, we need to use two Arduino boards one of Arduino i2c master sends data to another Arduino i2c Slave. So here is the list of components you may required.
- Arduino UNO boards(2)
- jumper wires (as many as required)
- 10K pullup resistors(2)
- USB cable to connect Arduino with your PC
To set up I2C communication between your master device and Arduino, you’ll need to connect the SDA (data) and SCL (clock) lines correctly. First, connect the SDA pin of the master device to the SDA pin on your Arduino, and the SCL pin of the master to the SCL pin on the Arduino. Don’t forget to add pull-up resistors (typically 4.7kΩ or 10kΩ) between these lines and VCC to ensure stable communication. Also, make sure both devices share a common ground (GND). If you’re using an Arduino Uno, you’ll find SDA on pin A4 and SCL on pin A5. On an Arduino Mega, SDA is on pin 20 and SCL on pin 21.
How to use Arduino as I2C Master?
To use an Arduino as an I2C master device, start by connecting the SDA (A4 on Arduino Uno, pin 20 on Arduino Mega) and SCL (A5 on Arduino Uno, pin 21 on Arduino Mega) pins of the Arduino to the corresponding pins on the slave device. Include pull-up resistors (4.7kΩ or 10kΩ) between SDA/SCL and VCC for reliable communication. In your Arduino code, use the Wire.begin()
function to initialize the I2C bus as the master. Then, to communicate with the slave, use Wire.beginTransmission(slaveAddress)
, followed by Wire.write(data)
to send data and Wire.endTransmission()
to complete the transmission. For reading data from the slave, use Wire.requestFrom(slaveAddress, quantity)
and Wire.read()
to receive the data.
How to use Arduino as i2c slave?
The utilization of an Arduino microcontroller as an Inter-Integrated Circuit (I²C) slave device necessitates a comprehensive understanding of both the I²C protocol and the specific programming paradigms that facilitate such a configuration. The I²C protocol is characterized by its synchronous, multi-master, multi-slave architecture, which operates over a two-wire bus system comprising a Serial Data Line (SDA) and a Serial Clock Line (SCL). In configuring an Arduino as an I²C slave, one must instantiate the Wire library within the Arduino Integrated Development Environment (IDE), thereby enabling the requisite abstractions for I²C communication.
Upon initializing the Arduino as an I²C slave, it is imperative to define its unique address within the 7-bit addressing scheme employed by the protocol. This address serves as a critical identifier in facilitating communication with master devices on the bus. Subsequently, one must implement callback functions to handle incoming requests from master devices effectively. The onRequest()
and onReceive()
methods are integral to this process; they permit the Arduino to transmit data upon receipt of a request from the master or to process incoming data sent by said master, respectively. Henceforth, through meticulous handling of these events and judicious management of data buffers, one can achieve seamless inter-device communication within multifaceted electronic systems predicated on I²C topology.
Moreover, consideration must be given to potential issues related to bus arbitration and timing constraints inherent in I²C communications. Asynchronous behaviors may arise due to clock stretching mechanisms utilized by slaves when processing requests—a phenomenon that merits careful programming attention to ensure robust interaction with master devices. Consequently, leveraging interrupt-driven architectures alongside systematic error-checking methodologies can significantly enhance reliability in multi-device environments while optimizing throughput across the communication medium. Such advanced configurations underscore not only the versatility of Arduino microcontrollers but also their pivotal role in contemporary embedded systems design frameworks reliant on efficient serial communication protocols like I²C.
Arduino to Arduino i2c Communication Code
Now we will present the complete code for Arduino-to-Arduino i2c Communication which we can test over serial monitor in our PC. This way, we do not need extra hardware for displaying purposes.
Example I2C master code
Here is the example code for how to use Arduino as I2C master.
#include <Wire.h>
void setup() {
Wire.begin(); // Join the I2C bus as master
Serial.begin(9600);
}
void loop() {
Wire.requestFrom(0x08, 12); // Request 12 bytes from the slave with address 0x08
while (Wire.available()) {
char c = Wire.read(); // Receive byte as a character
Serial.print(c); // Print the received data to the serial monitor
}
delay(1000); // Wait for a second before the next request
}
Code language: Arduino (arduino)
Arduino I2C Slave Code
Here is the final Arduino I2C Slave code which will communicate with the Master.
#include <Wire.h>
const int SLAVE_ADDRESS = 0x08; // Set the I2C address for the slave
void setup() {
Wire.begin(SLAVE_ADDRESS); // Join the I2C bus as a slave with the specified address
Wire.onReceive(receiveEvent); // Register the receive event handler
Wire.onRequest(requestEvent); // Register the request event handler
Serial.begin(9600);
}
void loop() {
// The main loop can remain empty for simple slave operations
}
// This function is called when the master sends data to the slave
void receiveEvent(int bytes) {
while (Wire.available()) {
char c = Wire.read(); // Receive byte as a character
Serial.print(c); // Print the received data to the serial monitor
}
}
// This function is called when the master requests data from the slave
void requestEvent() {
Wire.write("Hello Master"); // Send a string to the master
}
Code language: Arduino (arduino)