Stuck I2C Bus After Sensor Brownout
A 3.3 V I2C bus runs at 400 kHz with one microcontroller master and seven sensors. The bus has 250 pF of measured capacitance and 4.7 kΩ pull-up resistors to 3.3 V. Fast-mode rise-time limit is 300 ns, and each device is specified to sink 3 mA at V_OL = 0.4 V. After a sensor brownout, the microcontroller is reset, but the bus remains stuck: SDA measures 0.0 V and SCL measures 3.3 V even though the firmware releases both lines. The sensor has no dedicated reset pin and is powered from the same 3.3 V rail as the MCU. A replacement sensor fixes the board, but the failure recurs on other units after supply transients. The production test checks DC levels only, not rise time or bus recovery. The team wants to add a larger pull-up, 10 kΩ, to 'make the bus stronger'.
1. Is the 0.0 V SDA reading a pull-up sizing problem? Explain how to distinguish a stuck slave from a weak pull-up.
Read the worked answer
No. A pull-up resistor can only pull a line high; it cannot hold SDA at 0.0 V unless something is sinking current or the line is shorted. With 4.7 kΩ to 3.3 V and no device pulling low, SDA would sit near 3.3 V. A stable 0.0 V while SCL is high strongly suggests a slave is holding SDA low, likely because the brownout left its internal state machine mid-byte. Measure the current from SDA to ground: with 4.7 kΩ and a hard low, about 3.3 V/4.7 kΩ ≈ 0.70 mA flows. If removing sensors one at a time releases the line, the last removed device is the culprit. A short to ground would show the same voltage but would remain after all devices are removed. Increasing the pull-up to 10 kΩ makes the high level weaker, not stronger, and lowers the current available to charge the bus.
2. Describe a safe bus-recovery sequence the microcontroller can perform without a dedicated reset pin.
Read the worked answer
Configure SCL as an open-drain output and SDA as an input with its pull-up enabled. Do not drive SDA high against a slave that is holding it low. Generate up to nine clock pulses on SCL at a frequency below 100 kHz, monitoring SDA after each falling and rising edge. A slave that lost synchronization should release SDA within those clocks. Once SDA is released, issue a STOP condition: drive SDA low while SCL is high, then release SDA while SCL remains high. If SDA never releases after nine clocks, power-cycle the offending sensor or isolate that bus segment with a switch; a firmware-only recovery cannot clear a device that is latched. After recovery, reinitialize the sensor and verify that it acknowledges. Add a bus timeout or a hardware reset line in the next revision so the master is not dependent on nine clocks forever.
3. Calculate whether the existing 4.7 kΩ pull-ups meet the 300 ns rise-time limit, and select a better value that also respects the 3 mA sink limit.
Read the worked answer
For an RC bus, the 30–70% rise time is approximately 0.847 × R_p × C_b. With R_p = 4.7 kΩ and C_b = 250 pF, t_r ≈ 0.847 × 4.7 kΩ × 250 pF ≈ 1.0 µs, which is more than three times the 300 ns Fast-mode limit. The maximum pull-up is R_p ≤ t_r/(0.847 C_b) = 300 ns/(0.847 × 250 pF) ≈ 1.42 kΩ. Choose 1.2 kΩ, which gives t_r ≈ 254 ns. Check the low-level sink current: with V_OL = 0.4 V, I_OL ≈ (3.3 − 0.4)/1.2 kΩ ≈ 2.4 mA, below the 3 mA device rating. A 1.5 kΩ pull-up gives about 318 ns and is marginal; 1.2 kΩ is safer. The 10 kΩ proposal would make rise time about 2.1 µs and worsen the bus. Confirm the calculation with the actual bus capacitance and account for tolerances.