I2C fails politely. There is no bang, no smoke, no exception thrown with a helpful message. Your sensor read returns 0xFF, or the HAL function times out after a thousand milliseconds, and you are left staring at two wires that should be doing something. The bus has two lines, a handful of resistors, and a protocol simple enough to explain on a napkin — which makes it maddening when it goes quiet.

The good news is that I2C problems fall into a small number of categories, and they show up in a predictable order. Work through them cheapest first: multimeter, then firmware, then scope. Here is the order that finds most faults fastest.

Start With Idle Voltages

Before touching code, power the board and measure SDA and SCL with a multimeter, referenced to the ground of the same board. Both lines should sit near VDD — 3.3 V on a 3.3 V bus, 5 V on a 5 V bus. Not 0.4 V, not 1.6 V, not floating somewhere in the middle.

Each reading tells you something specific:

  • Both lines at 0 V: no pull-ups, no power, or a dead short to ground.
  • Both lines around 0.5–1.5 V: pull-ups fighting something that is pulling down, or a much weaker pull-up than you think.
  • Both lines at exactly VDD and never moving: electrically fine, but nothing is driving. This is a firmware or address problem, not a wiring one.
  • One line low, one high: a slave device is holding the bus — see the stuck-line section below.

Also confirm that every board shares a common ground. Two boards with separate supplies and one signal wire between them will produce exactly the kind of intermittent garbage that wastes an afternoon. Tie the grounds together, always, before troubleshooting anything else.

Pull-Up Resistors: Size Matters More Than Presence

I2C is open-drain. Devices can only pull a line low; they never drive it high. The resistors do all the pulling up, so without them the bus is a pair of wires connected to nothing. But the value matters as much as the existence.

A 4.7 kΩ pair is the classic choice and works on most small boards at 100 kHz. For 400 kHz Fast Mode, 2.2 kΩ or 1.5 kΩ is common. Going higher slows the rising edge; going lower increases the current each device must sink when it pulls the line down.

The rise time is roughly 0.847 × R × C, where C is total bus capacitance. The I2C specification limits rise times to about 1000 ns in Standard Mode, 300 ns in Fast Mode and 120 ns in Fast Mode Plus, and limits bus capacitance to 400 pF. Long wires, ribbon cables, and every attached device add capacitance, which is why a bus that works on a breadboard with two chips can fall apart with eight modules and 30 cm of wire.

Two traps worth checking:

  • Parallel pull-ups. Many breakout boards include their own 4.7 kΩ resistors. Three modules means three pairs in parallel — about 1.6 kΩ effective. That may still work, but with eight modules you are pulling real current on every low bit.
  • Double-ended pull-ups. Resistors at both ends of a long cable reduce the effective value and can cause reflections at higher speeds.
If a rising edge on your scope looks like a lazy curve instead of a sharp corner, the pull-up is too weak for your capacitance. If SDA cannot reach VDD, it is too strong for your devices.

Addresses and the Scanner Sketch

Run an I2C scanner before you debug your own driver. It removes the entire question of whether the bus works at all.

If the scanner lists nothing, the fault is electrical — go back to pull-ups and grounding. If it lists a device, note the address exactly as reported. The scanner prints 7-bit addresses; many drivers expect the 8-bit form, shifted left by one. A sensor the scanner finds at 0x3C will not answer at 0x78 unless your library expects that form. Check the datasheet convention before rewriting anything.

Two devices sharing an address will both respond, badly. The result is corrupted reads, NACKs, or one device that works only when the other is removed. Look for address-select pins (A0, A1, A2) left floating instead of tied high or low — floating select pins are a frequent cause of "it worked yesterday." If the addresses are hard-wired and collide, a bus multiplexer such as the TCA9548A lets you put each device behind its own switched channel.

Clock Stretching and the Master That Will Not Wait

A slave holds SCL low when it needs more time — an EEPROM committing a page write, an ADC finishing a conversion, a sensor completing an internal measurement. That is legal and expected. Not every master handles it.

Hardware peripherals vary widely here. Some I2C blocks honour stretching fully, some ignore it in certain states, and some have silicon errata that require workarounds. Software bit-banged implementations often skip it entirely because the author never saw a device stretch.

Symptoms look like this: one specific device times out while everything else is fine, a write succeeds but the following read fails, or the bus works at 100 kHz but not at 400 kHz. On a scope, SCL simply sits low longer than a normal clock period while SDA stays where it is. Lower the bus speed first — it is the cheapest test. If that fixes it, you found stretching, not corruption.

When a Line Is Stuck Low

A stuck SDA or SCL usually means a slave was interrupted mid-transaction and is still waiting for clocks that never came. Resetting your microcontroller does not reset the sensor, so the sensor holds the line and the bus stays dead no matter how many times you reinitialise the peripheral.

Bus recovery is straightforward. Toggle SCL manually nine times at roughly 100 kHz to clock out the stuck bit, then generate a STOP condition by pulling SDA low, releasing SCL high, then releasing SDA. Many MCU peripherals have this built in — STM32 calls it bus recovery and exposes it through HAL — but the manual version takes ten lines of code and works everywhere.

There is a second, sneakier cause. Power down one device on a powered bus and its ESD protection diodes can clamp SDA through the pull-up, dragging the line down. Anything that supports hot-plugging or has a switchable power rail needs a buffer or an isolator, not a direct connection.

And check for a short the boring way: power off, measure resistance from SDA and SCL to ground. Solder bridges under a QFN package and bent connector pins both look exactly like a firmware bug until you measure them.

What a Logic Analyzer Actually Shows You

An inexpensive eight-channel USB analyzer with PulseView or a similar decoder will answer most questions in one capture. Sample at 4 MHz or higher so you can see edges, and keep the ground lead short — a long clip lead on a fast edge shows you ringing that is not on the board.

Trigger on a falling edge of SDA and confirm, in order:

  1. Both lines idle high before the start.
  2. A clean START: SDA falls while SCL is high.
  3. The address byte, then an ACK — the ninth clock with SDA pulled low by the slave.
  4. Data bytes with the expected ACK after each.
  5. A STOP, or a repeated START if your driver uses one.

A missing ACK on the address byte means the device did not answer: wrong address, no power, or a wiring fault. A missing ACK on a data byte often means the device is busy or the previous transaction left it confused. If the capture stops halfway, note which line is low at that moment — that is where the recovery routine earns its keep.

Use a scope rather than a logic analyzer when you suspect analog problems. A logic analyzer samples and thresholds; it will happily show you a clean square wave while the real signal never quite reaches VDD.

The Order That Saves Time

Work down this list and you will solve most silent buses in under an hour:

  1. Verify a common ground between every board on the bus.
  2. Power off and check for shorts from SDA and SCL to ground and to VDD.
  3. Power on and measure idle voltages on both lines — they should be at VDD.
  4. Run an address scanner and note the reported addresses.
  5. Compare datasheet addresses with driver addresses, watching for the 7-bit versus 8-bit shift.
  6. Drop the bus to 100 kHz and retest. If that works, suspect rising edges or clock stretching.
  7. Capture a full transaction and find the exact clock where it fails.
  8. If a line is stuck low, run nine-clock bus recovery, then reduce pull-up values or shorten the wiring.
  9. Add devices one at a time until the bus breaks, and the culprit identifies itself.

A silent I2C bus is rarely mysterious. It is almost always a missing pull-up, a shifted address, a missing ground, or a slave left holding a line. Check those four before you rewrite the driver.

Photo: WikimediaImages / Pixabay