Mastering the I2C Address Scanner: A Quick Reference Guide

When integrating new sensors, OLED displays, or port expanders into an Arduino or ESP32 project, the very first step is always verifying communication. The I2C address scanner is an essential diagnostic sketch that sweeps the Inter-Integrated Circuit (I2C) bus to identify connected devices by their unique 7-bit hexadecimal addresses. Because I2C relies on a multi-master, multi-slave architecture, knowing the exact hex address of your peripheral is mandatory before writing any functional library code.

This FAQ and quick reference guide provides the canonical scanner sketch, a lookup table for common maker modules, and deep-dive troubleshooting for the most frequent I2C bus failures.

The Canonical I2C Address Scanner Sketch

Below is the optimized, widely accepted scanner sketch utilizing the standard Arduino Wire library. It sweeps addresses 0x01 through 0x7F (the valid 7-bit address space, excluding reserved addresses) and outputs the results to the Serial Monitor at 115200 baud.

#include <Wire.h>

void setup() {
  Wire.begin(); // Join I2C bus as master
  Serial.begin(115200);
  while (!Serial); // Wait for serial monitor (Leonardo/Micro)
  Serial.println("\n--- I2C Address Scanner ---");
}

void loop() {
  byte error, address;
  int nDevices = 0;

  Serial.println("Scanning...");

  for(address = 1; address < 127; address++ ) {
    Wire.beginTransmission(address);
    error = Wire.endTransmission();

    if (error == 0) {
      Serial.print("I2C device found at address 0x");
      if (address < 16) Serial.print("0");
      Serial.println(address, HEX);
      nDevices++;
    } else if (error == 4) {
      Serial.print("Unknown error at address 0x");
      if (address < 16) Serial.print("0");
      Serial.println(address, HEX);
    }    
  }
  if (nDevices == 0)
    Serial.println("No I2C devices found\n");
  else
    Serial.println("Scan complete.\n");

  delay(5000); // Wait 5 seconds before next scan
}

Quick Reference Table: Common Maker I2C Hex Addresses

Use this table to verify if your scanner is returning the expected default address. Note that many modules have jumper pads or pins to shift the address, allowing multiple identical sensors on the same bus.

Sensor / Module Default Address (Hex) Alternate Address (Hex) Address Selection Method
BME280 (Temp/Hum/Press) 0x76 0x77 SDO pin (GND = 0x76, VCC = 0x77)
MPU6050 (Gyro/Accel) 0x68 0x69 AD0 pin (LOW = 0x68, HIGH = 0x69)
SSD1306 (0.96" OLED) 0x3C 0x3D Hardware resistor shift on PCB
PCF8574 (I/O Expander) 0x20 0x21 - 0x27 A0, A1, A2 pins
VL53L0X (Time-of-Flight) 0x29 Software configurable Requires XSHUT pin to change via code
INA219 (Current Sensor) 0x40 0x41, 0x44, 0x45 A0, A1 jumper pads on PCB

For a more exhaustive list of I2C addresses, refer to the Adafruit I2C Address Directory.

FAQ: Troubleshooting I2C Scanner Failures

Q: Why does the scanner say "No I2C devices found"?

If your serial monitor outputs "No I2C devices found" despite the sensor being wired, you are likely facing one of three physical layer issues:

  1. SDA and SCL Swapped: Unlike UART, I2C lines are strictly directional regarding the clock. SDA (Data) and SCL (Clock) cannot be crossed. Verify your pinout against the specific microcontroller (e.g., on an Arduino Uno, SDA is A4 and SCL is A5; on an ESP32, default SDA is GPIO 21 and SCL is GPIO 22).
  2. Missing Pull-Up Resistors: I2C is an open-drain bus. It requires pull-up resistors on both SDA and SCL lines to pull the voltage HIGH when no device is actively pulling it LOW. While microcontrollers have internal pull-ups (typically 20kΩ to 50kΩ), they are often too weak for reliable I2C communication at 100kHz or 400kHz. Ensure your breakout board includes 4.7kΩ or 2.2kΩ external pull-ups.
  3. Power Starvation: Ensure the sensor's VCC is connected to the correct logic voltage (3.3V or 5V) and that the ground (GND) is shared with the microcontroller. A missing common ground will prevent the ACK (acknowledge) bit from registering.

Q: What if the scanner returns "Unknown error" or garbage addresses?

An "Unknown error" (typically error == 4 in the Wire library) indicates a bus collision or a hardware fault. This often happens when a 5V microcontroller (like the Arduino Uno) is connected directly to a strictly 3.3V sensor (like the BME280 or MPU9250) without a logic level shifter. The 5V HIGH signal can trigger the sensor's internal protection diodes, causing the bus to lock up. Solution: Use a bidirectional logic level converter, such as a BSS138 MOSFET-based shifter, between the 5V and 3.3V domains.

Q: How do I use multiple sensors with the exact same I2C address?

If your project requires three BME280 sensors but they all default to 0x76, you cannot simply wire them in parallel; the bus will experience data collisions. You have two options:

  • Address Jumpers: Modify the hardware by cutting traces or soldering jumper pads to shift the addresses (e.g., setting one to 0x77).
  • I2C Multiplexer: Use a multiplexer IC like the TCA9548A. This chip acts as a switchboard, allowing you to route the master I2C bus to one of 8 separate sub-buses via software commands, effectively bypassing address conflicts.

Advanced Diagnostics: Pull-Up Resistor Math & Bus Capacitance

When your I2C address scanner works on a breadboard but fails when you move the circuit to a custom PCB with long traces, you have likely hit the I2C bus capacitance limit. According to the NXP I2C-bus specification (UM10204), the maximum allowable bus capacitance is 400 pF.

Pro-Tip: Every wire, pin, and breakout board adds parasitic capacitance to the I2C lines. If your total capacitance exceeds 400 pF, the RC time constant created by your pull-up resistors will cause the signal rise time to exceed the I2C specification, resulting in corrupted data or total scanner failure.

To calculate the minimum required pull-up resistor ($R_{p(min)}$) to ensure the VOL (Voltage Output Low) stays below 0.4V at a maximum sink current ($I_{OL}$) of 3mA:

R_p(min) = (V_DD - V_OL) / I_OL

For a 5V system: (5V - 0.4V) / 0.003A = 1533Ω (approx 1.5kΩ).

However, to achieve faster rise times for 400kHz Fast Mode I2C on a bus with higher capacitance, you should use a resistor value closer to this minimum, such as 2.2kΩ. For standard 100kHz mode on short wires, 4.7kΩ remains the industry standard.

Summary Checklist for I2C Success

  • Always run the I2C address scanner sketch before integrating library code.
  • Verify SDA/SCL pin mappings for your specific MCU architecture.
  • Ensure external 4.7kΩ or 2.2kΩ pull-up resistors are present on the bus.
  • Use a logic level shifter when mixing 5V and 3.3V I2C devices.
  • Keep I2C trace lengths under 30cm to avoid exceeding the 400pF capacitance limit.