I2C is one of the most useful communication interfaces for Arduino, ESP32, ESP8266, RP2040, Raspberry Pi Pico and CANABLOX projects. It allows many sensors, displays, real-time clocks, ADCs, DACs and I/O expanders to share only two signal wires: SDA and SCL.
But I2C has one important electrical detail that causes many real-world problems: the bus needs pull-up resistors. Without the right pull-ups, an I2C project may work sometimes, fail randomly, or not work at all.
Pull-up problems are especially common when several modules are connected together, because many modules already include their own pull-up resistors. One module may work fine, but five modules together may make the bus unreliable.
Typical Symptoms
- The I2C scanner finds nothing.
- The I2C scanner finds devices only sometimes.
- A display works alone but fails when sensors are added.
- A sensor works on short wires but not on longer wires.
- The bus works at 100 kHz but fails at 400 kHz.
- Some modules work on Arduino Uno but not on ESP32.
- SDA or SCL does not return cleanly to HIGH.
- Adding one more module makes the entire I2C bus fail.
Why I2C Needs Pull-Up Resistors
I2C devices usually do not drive SDA and SCL high directly. Instead, devices pull the lines low when needed, and pull-up resistors bring the lines back high when no device is pulling them low.
This is called an open-drain or open-collector style bus.
The simplified behavior is:
- No device pulls the line low: pull-up resistor makes the line HIGH.
- One or more devices pull the line low: the line becomes LOW.
- Devices release the line: the pull-up resistor brings it HIGH again.
If the pull-up is missing, the line may float. If the pull-up is too weak, the line rises too slowly. If the pull-up is too strong, devices may have to sink too much current to pull the line low.
Common Cause: No Pull-Up Resistors
If there are no pull-up resistors at all, SDA and SCL may not reach a stable HIGH level. The I2C scanner may find nothing, or the bus may behave randomly.
Many modules include pull-ups already, but not all do. Some bare ICs require external pull-ups. Some breakout boards include jumpers to enable or disable pull-ups.
If the I2C scanner finds nothing and the wiring is correct, missing pull-ups are one of the first things to check.
Common Cause: Internal Pull-Ups Are Too Weak
Many microcontrollers have internal pull-up resistors that can be enabled in software. These internal pull-ups are usually weak. They may be useful for buttons, but they are often not ideal for reliable I2C communication.
Internal pull-ups may work with:
- Very short wires.
- Only one slow I2C device.
- Low bus speed.
- Clean breadboard setup.
But for reliable projects, especially with multiple modules, external pull-up resistors are usually better.
Common Cause: Pull-Ups Are Too Weak
A weak pull-up means the resistor value is too high. The bus lines rise slowly from LOW to HIGH. At low speed this may still work, but at higher speed the signal may not reach a valid HIGH level in time.
This can cause:
- Unstable I2C scanning.
- Random sensor errors.
- Display corruption.
- Devices disappearing from the bus.
- Failure at 400 kHz but success at 100 kHz.
Long wires and many connected modules add capacitance, which makes weak pull-ups even worse.
Common Cause: Pull-Ups Are Too Strong
A strong pull-up means the resistor value is too low. This makes the line rise quickly, but it also means devices must sink more current when pulling the line LOW.
If the pull-up is too strong, some devices may not be able to pull the line low enough. This can cause communication errors or stress the chips.
This often happens when many modules are connected and each one has its own pull-up resistors installed.
Common Cause: Too Many Modules with Onboard Pull-Ups
Many I2C modules include pull-up resistors on SDA and SCL. One module may have 4.7kΩ pull-ups. Another may also have 4.7kΩ. A third may have 10kΩ. When connected together, these resistors are in parallel.
Parallel resistors create a lower effective resistance.
For example:
- One 4.7kΩ pull-up: effective pull-up is 4.7kΩ.
- Two 4.7kΩ pull-ups in parallel: effective pull-up is about 2.35kΩ.
- Four 4.7kΩ pull-ups in parallel: effective pull-up is about 1.18kΩ.
That may become too strong for some I2C devices, especially on a 5V bus.
Common Pull-Up Values
There is no single perfect pull-up value for every I2C bus. The right value depends on voltage, bus capacitance, speed, wire length and connected devices.
For many small hobby projects, these are practical starting points:
| Pull-Up Value | Typical Use | Practical Notes |
|---|---|---|
| 10kΩ | Short, slow, low-capacitance bus | May be too weak for longer wiring or 400 kHz |
| 4.7kΩ | Common general-purpose starting value | Often works well for small 3.3V and 5V projects |
| 3.3kΩ | Slightly stronger pull-up | Useful for moderate bus capacitance |
| 2.2kΩ | Higher capacitance or faster bus | Can be useful, but check sink current |
| 1kΩ or lower | Usually too strong for typical hobby I2C | May overload devices when pulling LOW |
3.3V vs 5V Pull-Ups
The pull-up resistors connect SDA and SCL to the bus voltage. This is very important.
If the pull-ups connect to 5V, the I2C lines idle at 5V. That may be unsafe for 3.3V microcontrollers such as ESP32, ESP8266, RP2040, RP2350 and many modern boards.
For 3.3V controllers:
- SDA and SCL should normally be pulled up to 3.3V.
- Do not allow a 5V module to pull the bus to 5V unless proper level shifting is used.
- Check modules that include onboard pull-ups to their own VCC pin.
A module that works on Arduino Uno at 5V may not be safe on ESP32 without checking the pull-up voltage.
How to Measure the I2C Idle Voltage
A simple multimeter can reveal many pull-up problems.
With the circuit powered and no I2C communication happening:
- Measure SDA to GND.
- Measure SCL to GND.
- Both lines should normally be HIGH.
Expected idle voltage:
- About 3.3V on a 3.3V I2C bus.
- About 5V on a 5V I2C bus.
- Near 0V means something is pulling the line low.
- A floating or strange voltage may mean missing pull-ups or bad wiring.
How to Estimate Combined Pull-Up Resistance
If several modules have pull-ups, the combined value is lower than each individual resistor.
For equal resistors, a quick estimate is:
Effective resistance = resistor value / number of modules
Examples:
| Modules with Pull-Ups | Individual Pull-Ups | Approx. Effective Pull-Up |
|---|---|---|
| 1 module | 4.7kΩ | 4.7kΩ |
| 2 modules | 4.7kΩ each | 2.35kΩ |
| 3 modules | 4.7kΩ each | 1.57kΩ |
| 4 modules | 4.7kΩ each | 1.18kΩ |
| 5 modules | 4.7kΩ each | 940Ω |
This is why a bus can work with one or two modules, but become unreliable after more modules are added.
What Happens When Pull-Ups Are Too Weak
When pull-ups are too weak, SDA and SCL rise slowly. On an oscilloscope, the rising edges look rounded instead of sharp.
Practical symptoms:
- Works at 100 kHz but not 400 kHz.
- Works with short wires but not long wires.
- Works with one module but not several modules.
- Random read errors from sensors.
- Display glitches or freezes.
The fix may be stronger pull-ups, shorter wires, lower bus speed or fewer devices on the same bus segment.
What Happens When Pull-Ups Are Too Strong
When pull-ups are too strong, devices must sink more current to pull the line LOW.
Practical symptoms:
- Devices cannot pull SDA or SCL low enough.
- Some modules work, others do not.
- Low level voltage is not close enough to ground.
- Chips may run warmer or be stressed.
- Bus becomes unreliable after adding many modules.
The fix may be removing some onboard pull-ups or using a bus multiplexer to split the bus.
Lowering I2C Speed Can Help
If the bus is marginal because of long wires, capacitance or weak pull-ups, lowering the I2C speed can improve reliability.
Wire.setClock(100000); // 100 kHz standard mode
Use this after Wire.begin().
Many modules work at 400 kHz in ideal conditions, but 100 kHz is often a better troubleshooting speed for mixed modules and longer wiring.
Bus Length and Capacitance
I2C was designed for short connections on a PCB or inside one device. Long wires add capacitance, and capacitance slows down the rising edges of SDA and SCL.
Long wiring may require:
- Lower I2C clock speed.
- Stronger pull-ups within safe limits.
- Shorter or better-routed cables.
- Keeping SDA/SCL away from motor and relay wiring.
- Using bus buffers or different communication methods for longer distances.
If I2C must run over a long cable, it should be treated carefully. For longer-distance communication, interfaces such as RS485, CAN or differential signaling are often better choices.
Pull-Ups on Level Shifters
Many I2C level shifter modules use MOSFETs and pull-up resistors on both sides. This means the low-voltage side and high-voltage side each have their own pull-ups.
When using a level shifter, check:
- Low-voltage side pull-ups go to 3.3V.
- High-voltage side pull-ups go to 5V if needed.
- Additional module pull-ups do not make the effective resistance too low.
- The level shifter is suitable for I2C, not only one-direction logic.
For mixed 3.3V and 5V I2C systems, this is safer than directly pulling a 3.3V controller bus to 5V.
How to Troubleshoot Pull-Up Problems
- Disconnect all I2C modules.
- Connect one known-good module.
- Run the I2C scanner.
- Measure SDA and SCL idle voltage.
- Add modules one at a time.
- Run the scanner after each module is added.
- If the bus fails after adding a module, check its pull-ups and address.
- Try lowering the bus speed to 100 kHz.
- Shorten wires and avoid breadboard rail problems.
- If many modules are used, consider removing extra pull-ups or splitting the bus.
Quick Diagnostic Table
| Symptom | Likely Pull-Up Problem | First Thing to Try |
|---|---|---|
| Scanner finds nothing | Missing pull-ups or stuck bus line | Measure SDA/SCL idle voltage |
| Works at 100 kHz, fails at 400 kHz | Pull-ups too weak or bus capacitance too high | Use stronger pull-ups or lower speed |
| Fails after adding many modules | Too many onboard pull-ups in parallel | Check combined pull-up resistance |
| ESP32 bus idles at 5V | Pull-ups connected to 5V | Use level shifter or pull bus to 3.3V |
| One line stuck near 0V | Device or wiring pulling line low | Disconnect modules one at a time |
| Works with short wires only | Bus capacitance too high | Shorten wires or lower I2C speed |
What Not to Do
- Do not assume every module needs extra pull-up resistors.
- Do not assume onboard pull-ups are always enough.
- Do not pull ESP32, ESP8266 or RP2040 I2C lines up to 5V directly.
- Do not keep adding modules without checking address and pull-up effects.
- Do not use long I2C wires and high bus speed without testing signal reliability.
- Do not use I2C for long-distance wiring when a more robust interface is needed.
CANABLOX Practical Note
CANABLOX is built around modular I2C connections, so pull-up planning is important. The benefit of a structured modular system is that modules can be added and tested one at a time instead of creating a random breadboard wiring mess.
When building a larger CANABLOX project, scan the bus after adding each module. If a bus becomes unreliable after several modules are connected, check both address conflicts and the combined pull-up resistance. For larger systems, using an I2C multiplexer or separating bus sections can make the system much more reliable.
Conclusion
I2C pull-up resistors are simple, but they are responsible for many confusing troubleshooting problems. Missing pull-ups, weak pull-ups, overly strong pull-ups and too many onboard pull-ups can all break communication.
For small projects, 4.7kΩ pull-ups are often a good starting point, but the real answer depends on voltage, speed, wiring length and the number of connected modules.
If an I2C project behaves randomly, measure SDA and SCL, test one module at a time, lower the bus speed and check how many pull-ups are already installed on the modules. Very often, the problem is not the library or the sketch. It is the electrical behavior of the bus.
