When it comes to connecting sensors to a microcontroller, the I2C (Inter-Integrated Circuit) protocol is industry standard. It's simple, efficient, and most importantly, it allows you to connect dozens of devices using only two wires.
1. Understanding the Two-Wire Interface
I2C uses two specific lines for communication:
- SDA (Serial Data): The line used to send and receive data.
- SCL (Serial Clock): The line used to synchronize data transfer with a clock pulse.
Unlike SPI, which requires a "Select" pin for every device, I2C uses unique 7-bit addresses to identify which device the microcontroller is talking to.
💡 The Power of Daisy-Chaining
Because every device is connected to the same SDA and SCL bus, you can daisy-chain multiple sensors (like an OLED + BME280 + MPU6050) without using up any extra GPIO pins on your ESP32 or Arduino.
2. The Critical Role of Pull-Up Resistors
One of the most common reasons for I2C failure is missing Pull-Up Resistors. The SDA and SCL lines are "open-drain," meaning they can pull the voltage down to GND but cannot push it up to VCC (3.3V or 5V).
Without pull-up resistors (typically 4.7kΩ), the signal lines will "float" in an undefined state, leading to timeouts or scrambled data.
3. Handling I2C Address Conflicts
If you have two identical sensors (e.g., two BME280s), they likely share the same default I2C
address
(usually 0x76 or 0x77). If they both try to talk at once, the data
will collide.
Most I2C modules have an ADR or A0 pin. Connecting this pin to GND or VCC will toggle the last bit of the address, allowing you to have at least two of the same device on a single bus.
4. Code Snippet: I2C Address Scanner
Unsure if your sensor is connected correctly? Use this universal scanner to find the I2C address of every device currently on your bus.
#include <Wire.h>
void setup() {
Wire.begin();
Serial.begin(115200);
while (!Serial);
Serial.println("\nI2C 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.print(address, HEX);
Serial.println(" !");
nDevices++;
}
}
if (nDevices == 0) Serial.println("No I2C devices found\n");
else Serial.println("done\n");
delay(5000); // Wait 5 seconds for next scan
}
🚀 Summary
I2C is the ultimate protocol for low-speed sensor communication. Just remember: keep your wires short, include your pull-up resistors, and always check for address conflicts!