Table of Contents
- What Is I2C and How Does It Work?
- The Arduino I2C Scanner Sketch
- Common I2C Device Addresses Reference Table
- I2C Wiring Guide: Pull-Up Resistors and Cable Length
- Connecting Multiple I2C Devices on One Bus
- Troubleshooting: When Devices Are Not Detected
- Advanced Scanning: Speed Tests and Bus Health
- Frequently Asked Questions
- Conclusion
What Is I2C and How Does It Work?
I2C (Inter-Integrated Circuit, pronounced “eye-squared-see”) is a two-wire communication protocol used by hundreds of sensors, displays, and modules in the Arduino ecosystem. An arduino i2c scanner is the essential diagnostic tool for finding, verifying, and debugging I2C devices connected to your Arduino board.
The I2C bus uses just two signal lines: SDA (Serial Data) and SCL (Serial Clock). On the Arduino Uno, SDA is pin A4 and SCL is pin A5. On the Mega 2560, they are pins 20 (SDA) and 21 (SCL). Every device on the bus has a unique 7-bit address (0x00 to 0x7F), and the Arduino (acting as the master) communicates with each device by sending its address first.
The beauty of I2C is that you can connect dozens of devices using only two wires. An OLED display, a temperature sensor, an RTC module, and a digital potentiometer can all share the same SDA and SCL lines. Each device responds only when its address is called, ignoring traffic meant for other devices.
The Arduino I2C Scanner Sketch
The I2C scanner works by attempting to communicate with every possible address (0x01 to 0x7F) on the bus. If a device acknowledges (ACKs) the address, it is present and working. If no device acknowledges, the scanner moves to the next address.
// Arduino I2C Scanner - finds all devices on the I2C bus
#include <Wire.h>
void setup() {
Wire.begin();
Serial.begin(9600);
while (!Serial); // Wait for Serial Monitor (Leonardo/Nano 33)
Serial.println("I2C Scanner Starting...");
Serial.println("Scanning addresses 0x01 to 0x7F...");
Serial.println();
}
void loop() {
byte deviceCount = 0;
for (byte address = 1; address < 127; address++) {
Wire.beginTransmission(address);
byte error = Wire.endTransmission();
if (error == 0) {
Serial.print("Device found at address 0x");
if (address < 16) Serial.print("0");
Serial.print(address, HEX);
Serial.print(" (");
Serial.print(address);
Serial.println(" decimal)");
deviceCount++;
} else if (error == 4) {
Serial.print("Unknown error at address 0x");
if (address < 16) Serial.print("0");
Serial.println(address, HEX);
}
}
if (deviceCount == 0) {
Serial.println("No I2C devices found!");
Serial.println("Check wiring: SDA to A4, SCL to A5");
} else {
Serial.print("Found ");
Serial.print(deviceCount);
Serial.println(" device(s).");
}
Serial.println();
delay(5000); // Scan every 5 seconds
}
How to Use:
- Upload this sketch to your Arduino
- Connect your I2C device(s) — SDA to A4, SCL to A5, plus VCC and GND
- Open the Serial Monitor at 9600 baud
- The scanner reports found device addresses every 5 seconds
Understanding Return Codes:
error == 0: Device acknowledged — it is present and respondingerror == 1: Data too long for transmit buffererror == 2: Address NACK — no device at this addresserror == 3: Data NACK — device present but refusing dataerror == 4: Other error (bus stuck, SDA/SCL shorted, etc.)
Common I2C Device Addresses Reference Table
Here is a quick reference of I2C addresses for popular modules used in Arduino projects in India:
| Device | Address(es) | Notes |
|---|---|---|
| SSD1306 OLED (128×64) | 0x3C or 0x3D | Check address jumper on back |
| BME280 / BMP280 | 0x76 or 0x77 | SDO pin selects address |
| MPU6050 (Gyro/Accel) | 0x68 or 0x69 | AD0 pin selects address |
| DS3231 RTC | 0x68 | Fixed address — conflicts with MPU6050! |
| PCF8574 LCD Backpack | 0x27 or 0x3F | Address jumpers A0-A2 |
| ADS1115 ADC | 0x48-0x4B | ADDR pin to GND/VDD/SDA/SCL |
| PCA9685 PWM Driver | 0x40-0x7F | 6 address jumpers (64 possible) |
| AT24C256 EEPROM | 0x50-0x57 | A0-A2 address pins |
| BH1750 Light Sensor | 0x23 or 0x5C | ADDR pin LOW or HIGH |
| MCP23017 I/O Expander | 0x20-0x27 | A0-A2 address pins |
Note the address conflict between the DS3231 RTC and MPU6050 — both default to 0x68. If you need both on the same bus, change the MPU6050 to 0x69 by connecting its AD0 pin to VCC, or use a TCA9548A I2C multiplexer.
I2C Wiring Guide: Pull-Up Resistors and Cable Length
Correct wiring is critical for reliable I2C communication. Here are the rules:
Basic Connections:
- Arduino A4 (SDA) to device SDA
- Arduino A5 (SCL) to device SCL
- Arduino 5V to device VCC (or 3.3V for 3.3V devices)
- Arduino GND to device GND
Pull-Up Resistors: I2C requires pull-up resistors on both SDA and SCL lines. Most breakout boards (OLED displays, sensor modules) include 4.7K or 10K pull-up resistors on the PCB. If your device is a bare chip or your wires are long, you may need external pull-ups.
- 4.7K ohm: Standard value, works for most setups with short wires (under 50 cm)
- 2.2K ohm: Stronger pull-up for faster bus speeds (400 kHz) or longer wires
- 10K ohm: Weaker pull-up, suitable for very short buses with few devices
Important: Do not stack too many pull-up resistors. If three breakout boards each have 4.7K pull-ups, the effective pull-up is 1.57K ohm, which may be too strong. Desolder extra pull-ups from additional boards, leaving only one set active.
Cable Length: Standard I2C at 100 kHz works reliably up to about 1 metre with 4.7K pull-ups. At 400 kHz (Fast Mode), keep cables under 30 cm. For longer runs (up to 10 metres), reduce the clock speed to 10 kHz and use stronger pull-ups (1K ohm) or a dedicated I2C bus extender chip (P82B715).
Connecting Multiple I2C Devices on One Bus
I2C’s greatest strength is that all devices share the same two wires. Here is a practical multi-device setup:
// Reading 4 sensors on one I2C bus
#include <Wire.h>
#include <Adafruit_BME280.h>
#include <Adafruit_SSD1306.h>
#include <BH1750.h>
#include <RTClib.h>
Adafruit_BME280 bme; // 0x76
Adafruit_SSD1306 display(128, 64, &Wire, -1); // 0x3C
BH1750 lightMeter; // 0x23
RTC_DS3231 rtc; // 0x68
void setup() {
Wire.begin();
bme.begin(0x76);
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
lightMeter.begin();
rtc.begin();
}
void loop() {
DateTime now = rtc.now();
float temp = bme.readTemperature();
float hum = bme.readHumidity();
float lux = lightMeter.readLightLevel();
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0, 0);
display.print(now.hour()); display.print(":"); display.println(now.minute());
display.print("Temp: "); display.print(temp, 1); display.println(" C");
display.print("Humidity: "); display.print(hum, 1); display.println(" %");
display.print("Light: "); display.print(lux); display.println(" lux");
display.display();
delay(2000);
}
All four devices (BME280, OLED, light sensor, RTC) share the same SDA and SCL wires. The Arduino addresses each one individually. This setup uses only 2 pins but provides temperature, humidity, pressure, light level, time, and a display — an impressive amount of functionality from just two wires.
Troubleshooting: When Devices Are Not Detected
If the I2C scanner finds no devices, work through this checklist:
1. Check wiring: SDA must go to SDA, SCL to SCL. Swapping them is the most common mistake. On the Uno, SDA is A4 and SCL is A5 — they are labelled on the board near the digital pin headers, not the analogue pins.
2. Check power: Verify the device is powered. Use a multimeter to measure VCC at the device — it should show 5V or 3.3V (depending on the device). A common issue is that VCC and GND are swapped.
3. Check pull-up resistors: Measure the voltage on SDA and SCL with no communication happening. Both should read HIGH (close to VCC) due to pull-up resistors. If either reads LOW, there is a wiring fault or a shorted device.
4. Try a different I2C speed: Some devices require a specific clock speed. Try lowering the speed: Wire.setClock(100000); for 100 kHz (default) or even Wire.setClock(10000); for 10 kHz.
5. Check voltage levels: A 3.3V I2C device connected to a 5V Arduino may not respond if the logic levels are incompatible. Use a logic level converter or power the device from 5V if it supports it.
6. Reset the I2C bus: If the bus is stuck (SDA held LOW), power cycle the Arduino and all connected devices. A software bus recovery involves toggling SCL manually 9 times to free a stuck slave device.
7. Check for address conflicts: Two devices at the same address can cause neither to respond. Disconnect all devices except one and test each individually.
Advanced Scanning: Speed Tests and Bus Health
An enhanced I2C scanner can test bus health and device responsiveness at different speeds:
// Advanced I2C Scanner with speed testing
#include <Wire.h>
void setup() {
Serial.begin(9600);
while (!Serial);
}
void scanAtSpeed(long clockSpeed, const char* speedName) {
Wire.begin();
Wire.setClock(clockSpeed);
Serial.print("Scanning at "); Serial.print(speedName); Serial.println("...");
byte found = 0;
for (byte addr = 1; addr < 127; addr++) {
Wire.beginTransmission(addr);
if (Wire.endTransmission() == 0) {
Serial.print(" 0x");
if (addr < 16) Serial.print("0");
Serial.print(addr, HEX);
Serial.println(" OK");
found++;
}
}
Serial.print(" Devices found: "); Serial.println(found);
Serial.println();
}
void loop() {
scanAtSpeed(10000, "10 kHz (Low Speed)");
scanAtSpeed(100000, "100 kHz (Standard)");
scanAtSpeed(400000, "400 kHz (Fast Mode)");
scanAtSpeed(1000000, "1 MHz (Fast Mode+)");
Serial.println("--- Scan complete. Next scan in 10 seconds ---");
delay(10000);
}
If a device appears at 100 kHz but disappears at 400 kHz, you have a signal integrity problem — usually weak pull-ups, long wires, or too much capacitance on the bus. Strengthening the pull-ups (lower resistance value) or shortening the wires typically fixes this.
Frequently Asked Questions
How many I2C devices can I connect to one Arduino?
The I2C protocol supports up to 127 addresses on a single bus (7-bit addressing). In practice, bus capacitance limits you to about 20-30 devices. With a TCA9548A I2C multiplexer, you can create 8 separate buses, each with its own address space — allowing hundreds of devices.
Why does my OLED display show address 0x3C but the library uses 0x78?
Some datasheets list the 8-bit address (which includes the R/W bit). The 7-bit address 0x3C becomes 0x78 (write) or 0x79 (read) when shifted left by one bit. Arduino’s Wire library uses the 7-bit address (0x3C). If a library or datasheet gives you an 8-bit address, divide by 2 to get the 7-bit version.
Can I use I2C on pins other than A4 and A5?
On the Arduino Uno (ATMega328P), I2C is hardware-mapped to A4 (SDA) and A5 (SCL) only. Software I2C libraries can use any pins but run slower. On the Mega 2560, hardware I2C is on pins 20 (SDA) and 21 (SCL). On ARM-based boards (Due, Zero), you may have multiple I2C ports.
My I2C scanner shows no devices but the wiring is correct. What now?
Try these steps: power cycle everything, swap SDA and SCL (in case they are reversed), try a different I2C device to rule out a faulty module, check that the device voltage matches the Arduino (3.3V vs 5V), and verify the module’s address jumpers are set correctly.
Conclusion
The I2C scanner is the first tool you should reach for when working with I2C devices. It quickly confirms that your wiring is correct, identifies device addresses, and helps diagnose communication problems. Keep this sketch saved in your projects folder — you will use it frequently. Combined with the common address reference table, you can quickly set up multi-device I2C buses for complex sensor and display projects.
Add comment