From 4d19dfb747d9b0ef0d2b5a4a438650d0d6973263 Mon Sep 17 00:00:00 2001 From: aditya Date: Fri, 22 May 2026 17:34:40 +0530 Subject: [PATCH] Add Wire.setWireTimeout to avoid I2C bus hangs (closes #288) If the I2C bus stops responding mid-transaction (noise, the display becomes disconnected, etc.), the underlying Wire library spins in an indefinite loop and the host MCU effectively hangs. The Arduino AVR core fixed this in ArduinoCore-avr@deea929 by exposing setWireTimeout(); cores that implement it define WIRE_HAS_TIMEOUT so callers can detect the feature at compile time. Use that detection: when periphBegin owns the wire->begin() call, follow it with a 25 ms timeout + reset on timeout. We only touch Wire's configuration when we performed the begin() ourselves; if the caller managed Wire externally, leave their configuration untouched. No behavioural change on cores without WIRE_HAS_TIMEOUT (the entire block is compiled out). --- Adafruit_SSD1306.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/Adafruit_SSD1306.cpp b/Adafruit_SSD1306.cpp index 30edde9..cec28ef 100644 --- a/Adafruit_SSD1306.cpp +++ b/Adafruit_SSD1306.cpp @@ -522,8 +522,19 @@ bool Adafruit_SSD1306::begin(uint8_t vcs, uint8_t addr, bool reset, // function if it has unusual circumstances (e.g. TWI variants that // can accept different SDA/SCL pins, or if two SSD1306 instances // with different addresses -- only a single begin() is needed). - if (periphBegin) + if (periphBegin) { wire->begin(); +#ifdef WIRE_HAS_TIMEOUT + // Avoid indefinite hangs in the Wire library when the I2C bus stops + // responding (e.g. SDA/SCL noise or the display disconnects). The + // setWireTimeout() API is exposed by Arduino cores that define + // WIRE_HAS_TIMEOUT (Arduino AVR core >= 1.8.6, see ArduinoCore-avr#42). + // We only set the timeout when we owned the begin() call -- if the + // caller managed Wire themselves, leave their configuration untouched. + // See Adafruit_SSD1306 issue #288. + wire->setWireTimeout(25000 /* us */, true /* reset on timeout */); +#endif + } } else { // Using one of the SPI modes, either soft or hardware pinMode(dcPin, OUTPUT); // Set data/command pin as output pinMode(csPin, OUTPUT); // Same for chip select