How to Communicate Between Raspberry Pi and Arduino Using I2C
To communicate between a Raspberry Pi and an Arduino using
I2C, connect the SDA and SCL pins of both devices and set one as master (usually Raspberry Pi) and the other as slave (Arduino). Use the SMBus library on Raspberry Pi and Wire library on Arduino to send and receive data over the I2C bus.Syntax
The Raspberry Pi uses the SMBus Python library to communicate as an I2C master. The Arduino uses the Wire library to act as an I2C slave or master.
Key parts:
- Raspberry Pi: Initialize bus with
bus = SMBus(1), where 1 is the I2C bus number. - Arduino: Use
Wire.begin(address)to set slave address. - Use
write()andread()functions to send and receive bytes.
python
from smbus2 import SMBus bus = SMBus(1) # Use I2C bus 1 slave_address = 0x08 # Arduino I2C address # Write a byte bus.write_byte(slave_address, 0x01) # Read a byte data = bus.read_byte(slave_address) print(f"Received: {data}")
Example
This example shows how to send a byte from Raspberry Pi to Arduino and have Arduino respond back with a byte.
arduino
// Arduino code (Slave) #include <Wire.h> #define SLAVE_ADDRESS 0x08 volatile byte receivedData = 0; volatile bool dataReceived = false; void setup() { Wire.begin(SLAVE_ADDRESS); Wire.onReceive(receiveEvent); Wire.onRequest(requestEvent); Serial.begin(9600); } void loop() { if (dataReceived) { Serial.print("Received from Pi: "); Serial.println(receivedData); dataReceived = false; } } void receiveEvent(int howMany) { while (Wire.available()) { receivedData = Wire.read(); dataReceived = true; } } void requestEvent() { Wire.write(42); // Send back number 42 }
Example
Raspberry Pi Python code to send and receive data from Arduino slave.
python
from smbus2 import SMBus import time bus = SMBus(1) slave_address = 0x08 try: # Send byte 10 to Arduino bus.write_byte(slave_address, 10) time.sleep(0.1) # Wait for Arduino to process # Read byte from Arduino data = bus.read_byte(slave_address) print(f"Received from Arduino: {data}") finally: bus.close()
Output
Received from Arduino: 42
Common Pitfalls
- Not connecting the Raspberry Pi and Arduino grounds together causes communication failure.
- Using wrong I2C addresses or forgetting to set the Arduino slave address with
Wire.begin(address). - Not enabling I2C on Raspberry Pi via
raspi-config. - Pull-up resistors missing on SDA and SCL lines (usually 4.7kΩ needed).
- Trying to use the same device as both master and slave simultaneously.
arduino
/* Wrong: Arduino without setting slave address */ #include <Wire.h> void setup() { Wire.begin(); // No address set, acts as master } void loop() {} /* Right: Arduino as slave with address 0x08 */ #include <Wire.h> void setup() { Wire.begin(0x08); // Set slave address } void loop() {}
Quick Reference
| Step | Description |
|---|---|
| Connect SDA and SCL pins | Connect Raspberry Pi GPIO 2 (SDA) to Arduino SDA, GPIO 3 (SCL) to Arduino SCL |
| Connect Grounds | Connect Raspberry Pi GND to Arduino GND |
| Enable I2C on Pi | Run sudo raspi-config and enable I2C interface |
| Set Arduino as Slave | Use Wire.begin(address) with unique 7-bit address |
| Use SMBus on Pi | Use smbus2 Python library to send/read bytes |
| Add Pull-up Resistors | Use 4.7kΩ resistors on SDA and SCL lines if needed |
Key Takeaways
Connect SDA, SCL, and GND pins between Raspberry Pi and Arduino for I2C communication.
Set Arduino as I2C slave with Wire.begin(address) and Raspberry Pi as master using smbus2.
Enable I2C interface on Raspberry Pi via raspi-config before running code.
Use pull-up resistors on SDA and SCL lines to ensure signal integrity.
Common mistakes include missing ground connection and wrong slave address setup.