ESP32 I²C Guide: Default Pins, Pull-ups and Common Failures
Which two pins to use for I²C on the ESP32, what pull-up value to pick, and why your device never shows up on the bus scan.
The short version
On the original ESP32, I²C defaults to SDA = GPIO21 and SCL = GPIO22 in Arduino Core and most examples. That is not a hardware limit — I²C runs through the GPIO matrix, so almost any output-capable pin works. The real problems are the next three.
1. You must add external pull-ups
The ESP32's internal pull-ups are roughly 45 kΩ, far too weak for I²C. Rising edges crawl and 400 kHz will fail. Fit a 4.7 kΩ pull-up to 3.3 V on each line (2.2 kΩ for many devices or long runs).
2. Avoid constrained pins
- Flash pins: GPIO 6–11 on the original ESP32 connect to internal flash. Never use them.
- Strapping pins: GPIO 0 / 2 / 5 / 12 / 15 participate in boot configuration; pull resistors here can stop the chip from booting. GPIO2 also carries the on-board LED.
- Input-only pins: GPIO 34–39 have no output driver, so they cannot be SDA (which is bidirectional).
3. 7-bit vs 8-bit addresses
Datasheets usually quote the 8-bit address including the R/W bit (0xD0 / 0xD1 for the same MPU6050). ESP-IDF and Wire.beginTransmission() expect a 7-bit address, so shift the datasheet value right by one (0xD0 >> 1 = 0x68). Getting this wrong looks exactly like "no devices found".
Default pins by chip
| Chip | Common default SDA | Common default SCL | Note |
|---|---|---|---|
| ESP32 (original) | GPIO21 | GPIO22 | Arduino / most examples |
| ESP32-S2 / S3 / C3 / C6 / H2 / P4 | Verify against official docs | Defaults have changed across ESP-IDF versions — check the documentation or soc headers for your target | |
Recovering a locked bus
If a slave is reset mid-transfer it may hold SDA low forever, killing the bus. The standard fix is for the master to emit nine clock pulses so the slave releases the line; failing that, power-cycle the slave. It is worth adding a bit-banged recovery routine that runs when init fails.