How to Enable I2C on Raspberry Pi
I2C (Inter-Integrated Circuit, pronounced "I-squared-C") is a two-wire serial bus used to connect low-speed peripherals — sensors, displays, EEPROMs — to a microcontroller or SoC. It uses two lines: SDA (data) and SCL (clock). Each device on the bus has a unique 7-bit address (0x00–0x7F), and communication follows a master/slave model where the Raspberry Pi acts as the master.
Understanding Device Tree Overlays
The Linux kernel uses a device tree — a data structure that describes the hardware on the
board — to discover which peripherals exist and how they are connected. The base device tree
shipped with the Raspberry Pi describes the default configuration, but some peripherals (like
I2C) are disabled by default. Instead of modifying the base tree, you can apply a device tree
overlay that merges additional nodes or property changes at boot time. For example, adding
dtoverlay=i2c1 (or dtparam=i2c_arm=on) to config.txt tells the bootloader to merge an
overlay that enables the I2C controller node and configures the correct GPIO pins for SDA and
SCL. The kernel then sees the I2C bus as an active device and loads the appropriate driver.
For a deeper look at device tree syntax, overlays, and how the kernel matches devices to drivers, see the Device Tree and Drivers Reference.
Check If I2C Is Already Enabled
Check for available I2C interfaces:
If nothing shows up the I2C interface is not enabled.
Check If I2C Kernel Module is Loaded
Open a terminal and run list kernel modules:
Info
lsmod lists all currently loaded kernel modules — chunks of driver code that the kernel loaded to support specific hardware or features. The grep i2c filter shows only modules related to I2C. If no I2C modules appear, the kernel has not yet been told to enable the I2C subsystem.
Expected output (example):
If nothing else is shown, I2C is not yet enabled.
Enable I2C via raspi-config
To enable the I2C interface:
Then navigate:
Reboot your Raspberry Pi to apply changes:
Load I2C Kernel Modules Manually
If the modules are not loaded automatically, load them manually:
Uncomment the following line in /boot/firmware/config.txt
dtparam stands for device tree parameter — it tells the kernel's device tree which hardware peripherals to enable at boot. Setting i2c_arm=on activates the ARM-side I2C controller.
To load them automatically at boot:
Whysudo tee instead of sudo echo >>? The >> redirect is handled by your current (non-root) shell, so sudo echo "text" >> /protected/file fails with "Permission denied." Using sudo tee -a runs tee as root, so the write to the protected file succeeds.
Login again via SSH
Install I2C Utilities
Make sure the necessary tools and libraries are installed:
i2c-tools: command-line utilities for I2Cpython3-smbus: Python library for I2C communication. SMBus (System Management Bus) is a subset of I2C with stricter timing and protocol rules — most I2C sensors work fine over SMBus.git: to version control and access source repositories
Verify I2C Bus is Active
Check for available I2C interfaces:
Expected output:
Then scan the appropriate I2C bus for connected devices:
The -y flag skips the interactive confirmation prompt (safe for most devices). The 1 is the bus number — on Raspberry Pi, I2C bus 1 corresponds to GPIO2 (SDA, Pin 3) and GPIO3 (SCL, Pin 5).
This shows a grid with detected I2C addresses. It will probably be empty until you connect a sensor:
linux@eslinux:~ $ i2cdetect -y 1
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
Troubleshooting: i2cdetect shows no devices
- Check wiring: ensure SDA→GPIO2 (Pin 3) and SCL→GPIO3 (Pin 5) connections are solid
- Check pull-up resistors: I2C requires pull-ups on SDA and SCL (most breakout boards include them)
- Check
config.txt: verifydtparam=i2c_arm=onis present in/boot/firmware/config.txt - Reboot: I2C changes in
raspi-configorconfig.txtrequire a reboot to take effect
Connect the MCP9808 temperature module
Connect the MCP9808 temperature module using cables to the RPI following the pinout.
Pinout
You can find the pinout of the Raspberry Pi here.

Connecting a Temperature Sensor (MCP9808) to Raspberry Pi:
| Temperature Sensor Pin | Connect to Raspberry Pi | Notes |
|---|---|---|
| +3V3 | 3.3V (Pin 1) | Power supply |
| GND | GND (Pin 6) | Ground connection |
| SDI | GPIO2 (Pin 3) | I2C data line |
| SCK | GPIO3 (Pin 5) | I2C clock line |
| Alert | - | Alert pin |
Warning
The MCP9808 operates at 3.3V only. Connect it to the 3.3V pin (Pin 1), not the 5V pin (Pin 2). Applying 5V will damage the sensor.
Note
Always consult your sensor's datasheet for proper connection details.
Now scan the appropriate I2C bus again for connected devices:
The MCP9808 have to show up at the address 0x18:
linux@eslinux:~ $ i2cdetect -y 1
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- 18 -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
Example Python Code to Use I2C
Create a test script in Python top read and decode the temperature.
import smbus
bus = smbus.SMBus(1)
address = 0x18 # MCP9808 default I2C address
# MCP9808 temperature register
# 0101 =Temperature register (TA)
TEMP_REG = 0x05
# Read 2-byte word from the temperature register
raw_temp = bus.read_word_data(address, TEMP_REG)
# Decode following the EXAMPLE 5-1: SAMPLE INSTRUCTION CODE
# Byte-swap: the MCP9808 sends data in big-endian order (most significant
# byte first), but SMBus read_word_data returns it in little-endian order
# (least significant byte first). This swap puts the bytes back in the
# correct order for decoding.
raw_temp = ((raw_temp << 8) & 0xFF00) + (raw_temp >> 8)
raw_temp &= 0x1FFF
celsius = raw_temp & 0x0FFF
celsius /= 16.0
if raw_temp & 0x1000:
celsius -= 256
print(f"Temperature: {celsius:.2f} °C")
How to decode the sensor values can found in the MCP9808 documentation.
Note: You can find further details about SMBus here