← How-Tos
electronics Jun 19, 2026 ◑ 5 views ◯ 3 min read

I2C Wiring and Protocol Guide for Arduino, ESP32, and Raspberry Pi

i2carduinoesp32raspberry pisensorwiringsdasclprotocolelectronics

I2C (Inter-Integrated Circuit) is how most modern sensors communicate with microcontrollers. One pair of wires — SDA and SCL — can connect up to 127 devices on the same bus, each with a unique address. Here's how to wire and use it across the main maker platforms.

How I2C Works

I2C uses two signals:

The controller (Arduino, Pi, etc.) generates the clock and initiates all transfers. Devices on the bus are either controllers or peripherals. Each peripheral has a 7-bit address (0x00–0x7F), letting up to 127 devices share one bus.

Pull-up resistors on both SDA and SCL are required — typically 4.7 kΩ for standard speed, 2.2 kΩ for fast mode. Most breakout boards include these onboard.

Standard I2C Pins

PlatformSDASCL
Arduino Uno R3A4A5
Arduino NanoA4A5
Arduino Mega2021
ESP32 DevKitGPIO 21GPIO 22
ESP8266 NodeMCUD2 (GPIO4)D1 (GPIO5)
Raspberry Pi 40-pinGPIO 2 (Pin 3)GPIO 3 (Pin 5)
Raspberry Pi PicoGP4 (default)GP5 (default)

See the full pinout references for each board on this site for exact physical pin locations.

Wiring Diagram

Sensor VCC  →  3.3V or 5V (check sensor datasheet)
Sensor GND  →  GND
Sensor SDA  →  SDA pin
Sensor SCL  →  SCL pin

Logic level warning: The Raspberry Pi and ESP32 are 3.3V devices. Connect only 3.3V I2C sensors directly. For 5V Arduino + 3.3V sensor, use a bidirectional level shifter (BSS138-based modules are cheap and work well).

Scanning for Device Addresses

Always run an I2C scan first to confirm wiring is correct and find device addresses.

Arduino:

#include <Wire.h>
void setup() {
  Wire.begin();
  Serial.begin(115200);
  for (byte addr = 8; addr < 127; addr++) {
    Wire.beginTransmission(addr);
    if (Wire.endTransmission() == 0) {
      Serial.print("Found device at 0x");
      Serial.println(addr, HEX);
    }
  }
}
void loop() {}

Raspberry Pi:

sudo i2cdetect -y 1

ESP32:

#include <Wire.h>
void setup() {
  Wire.begin(21, 22); // SDA, SCL
  Serial.begin(115200);
  for (byte addr = 8; addr < 127; addr++) {
    Wire.beginTransmission(addr);
    if (Wire.endTransmission() == 0)
      Serial.printf("Found: 0x%02X
", addr);
  }
}

Common I2C Sensor Addresses

DeviceDefault Address
BME280 (temp/humidity/pressure)0x76 or 0x77
BMP180 (pressure)0x77
MPU6050 (accelerometer/gyro)0x68 or 0x69
SSD1306 OLED (128×64)0x3C or 0x3D
ADS1115 (16-bit ADC)0x48–0x4B
PCF8574 (GPIO expander)0x20–0x27
DS3231 RTC0x68
VL53L0X (ToF distance)0x29

Multiple Devices on the Same Bus

Just wire SDA and SCL in parallel across all devices. Each device responds only to its address. For two identical sensors (same address), most have an address select pin (AD0, ADDR) that lets you set a different address — check the datasheet.

Troubleshooting

Nothing found in scan: Check wiring, check power, confirm pull-ups are present, try slower bus speed.

Intermittent errors: Bus speed too high for cable length, or missing/wrong pull-up resistors.

Wrong readings: Confirm sensor address matches library call, check voltage compatibility.

Multiple devices causing problems: One faulty device can pull the bus low and block all others — disconnect devices one by one to find the culprit.