Getting Started with ESP32 and I2C Sensor Networks

The Inter-Integrated Circuit (I2C) protocol remains the de-facto standard for connecting microcontrollers to digital peripherals — temperature sensors, OLEDs, barometers, and IMUs. But when scaling from a single breadboard sensor to a robust multi-device bus, developers frequently hit bus hangs, address collisions, and intermittent communication dropouts.

1. Understanding the I2C Physical Layer

Unlike SPI, which uses dedicated chip-select lines, I2C is a 2-wire synchronous bus consisting of SDA (Serial Data) and SCL (Serial Clock). Both lines are open-drain, which means devices can only pull the line to Ground (LOW); they rely on external pull-up resistors to return the lines to 3.3V (HIGH).

Pull-up Resistor Sizing Rule of Thumb

For standard 100 kHz bus speeds and short traces, 4.7 kΩ pull-up resistors are typical. For 400 kHz Fast Mode or longer wires (>30 cm), drop the pull-up resistance to 2.2 kΩ or 1.8 kΩ to combat parasitic capacitance and achieve crisp rising edges.

2. Wiring Multiple Sensors to ESP32 Hardware I2C

The ESP32 features two hardware I2C controllers (I2C0 and I2C1) that can be mapped to virtually any GPIO pins. By default, the Arduino-ESP32 core assigns:

  • SDA: GPIO 21
  • SCL: GPIO 22

Here is a battle-tested scanning routine to identify every responding device on your bus:

#include <Wire.h>

void setup() {
  Serial.begin(115200);
  Wire.begin(21, 22); // SDA = 21, SCL = 22
  Serial.println(\"n--- Starting I2C Bus Scan ---\");

  byte error, address;
  int nDevices = 0;

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

    if (error == 0) {
      Serial.printf(\"Device found at 0x%02Xn\", address);
      nDevices++;
    } else if (error == 4) {
      Serial.printf(\"Unknown error at 0x%02Xn\", address);
    }
  }
  if (nDevices == 0) Serial.println(\"No I2C devices found.n\");
  else Serial.printf(\"Scan complete. %d device(s) found.n\", nDevices);
}

void loop() {
  // Put secondary polling tasks here
  delay(5000);
}

3. Resolving Address Conflicts: Multiplexers vs Secondary Buses

What happens when you need three identical temperature sensors that all share address 0x68? You have two reliable solutions:

  1. I2C Multiplexer (TCA9548A): A bidirectional translation switch allowing you to isolate up to 8 sub-buses under software control.
  2. Secondary Hardware Bus: Initialize TwoWire I2Ctwo = TwoWire(1); and assign separate GPIOs (e.g. GPIO 18 and 19) for your second cluster.
Voltage Mismatch Alert: 5V Sensors vs 3.3V ESP32

Never connect 5V I2C pull-up resistors directly to the ESP32 GPIOs. Although some pins exhibit momentary tolerance, sustained 5V on GPIO 21/22 will degrade the internal ESD clamping diodes over time. Always use a bidirectional logic level shifter (such as BSS138-based modules).

Summary & Next Steps

By correctly sizing pull-ups, monitoring bus capacitance, and utilizing hardware multiplexers when address collisions arise, your ESP32 telemetry system will operate reliably in industrial and field deployments.

Building this project?

Source genuine development boards, modules, sensors, and passive components directly from our Bangalore warehouse with same-day dispatch.

One comment on “Getting Started with ESP32 and I2C Sensor Networks

  1. Excellent guide on pull-up resistor sizing! We were seeing intermittent bus hangs on 400kHz until we dropped to 2.2k.

Leave a Comment or Question

Have a technical question or feedback about this article? Share it below.