0
0
Iot-protocolsHow-ToBeginner · 4 min read

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() and read() 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

StepDescription
Connect SDA and SCL pinsConnect Raspberry Pi GPIO 2 (SDA) to Arduino SDA, GPIO 3 (SCL) to Arduino SCL
Connect GroundsConnect Raspberry Pi GND to Arduino GND
Enable I2C on PiRun sudo raspi-config and enable I2C interface
Set Arduino as SlaveUse Wire.begin(address) with unique 7-bit address
Use SMBus on PiUse smbus2 Python library to send/read bytes
Add Pull-up ResistorsUse 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.