Raspberry Pi I2C Basics
I2C is a simple two-wire bus that lets your Raspberry Pi talk to many sensors and displays at once, each identified by its own address.
What Is I2C?
I2C (Inter-Integrated Circuit) is a communication protocol that lets a single controller — your Raspberry Pi — exchange data with many peripheral chips over just two shared wires. Instead of wiring a separate connection to every sensor or display, every device taps into the same pair of lines and listens for its own unique address. When the Pi wants to talk to a specific chip, it starts by sending that chip's address on the bus, and only the matching device responds; everything else stays silent.
- SDA (Serial Data) carries the actual bits back and forth
- SCL (Serial Clock) keeps both sides synchronized to the same timing
- Each device on the bus has its own 7-bit address, so dozens of chips can share the same two wires
- Standard mode runs at 100 kHz and Fast mode at 400 kHz, both far slower than SPI
- Pull-up resistors on SDA and SCL are required for the bus to work reliably
- Widely used by temperature/pressure sensors, real-time clocks, small OLED displays, and I/O expanders
Wiring and Enabling I2C
On every Raspberry Pi model, the primary I2C bus is exposed on physical pin 3 (GPIO2 / SDA) and physical pin 5 (GPIO3 / SCL), with ground available on several nearby pins. Because the Pi's GPIO header runs at 3.3V logic, make sure any module you connect is 3.3V-tolerant. I2C is disabled by default, so open a terminal and run sudo raspi-config, then choose Interface Options > I2C > Yes, or enable it without the menu using sudo raspi-config nonint do_i2c 0. Either way, reboot afterwards. Then install the tools used throughout this page with sudo apt update && sudo apt install -y i2c-tools python3-smbus2.
Scanning the Bus with i2cdetect
With the tools installed, run i2cdetect -y 1 (bus 1 is the standard user-facing I2C bus on modern Raspberry Pi boards). You'll see a 16x16 grid of two-digit hexadecimal addresses. Most cells show --, meaning nothing answered at that address, while a value such as 3c means a device responded there. A cell showing UU means a kernel driver has already claimed that address, which is common for a HAT's onboard identification chip.
Example
from smbus2 import SMBus
BUS_NUMBER = 1
with SMBus(BUS_NUMBER) as bus:
found = []
for address in range(0x03, 0x78):
try:
bus.read_byte(address)
found.append(hex(address))
except OSError:
pass
print("Devices found:", found)Reading and Writing Registers with smbus2
Example
from smbus2 import SMBus
BMP280_ADDRESS = 0x76
CHIP_ID_REGISTER = 0xD0
with SMBus(1) as bus:
chip_id = bus.read_byte_data(BMP280_ADDRESS, CHIP_ID_REGISTER)
print(f"Chip ID: {hex(chip_id)}")
# Writing a single configuration byte to a register
CONTROL_REGISTER = 0xF4
bus.write_byte_data(BMP280_ADDRESS, CONTROL_REGISTER, 0x27)