From 49713badb2a464725042b60709ffba3c477dc197 Mon Sep 17 00:00:00 2001 From: Neil McKechnie Date: Thu, 2 Feb 2023 12:21:35 +0000 Subject: [PATCH] Update I2CManager_NonBlocking.h Add code to try and recover from stuck bus following a timeout. --- I2CManager_NonBlocking.h | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/I2CManager_NonBlocking.h b/I2CManager_NonBlocking.h index f5caefd..3a33719 100644 --- a/I2CManager_NonBlocking.h +++ b/I2CManager_NonBlocking.h @@ -213,10 +213,21 @@ void I2CManagerClass::checkForTimeout() { // Reset TWI interface so it is able to continue // Try close and init, not entirely satisfactory but sort of works... I2C_close(); // Shutdown and restart twi interface + + // If SDA is stuck low, issue up to 9 clock pulses to attempt to free it. + pinMode(SCL, INPUT_PULLUP); + pinMode(SDA, INPUT_PULLUP); + for (int i=0; !digitalRead(SDA) && i<9; i++) { + digitalWrite(SCL, 0); + pinMode(SCL, OUTPUT); // Force clock low + delayMicroseconds(10); // ... for 5us + pinMode(SCL, INPUT_PULLUP); // ... then high + delayMicroseconds(10); // ... for 5us (100kHz Clock) + } + // Whether that's succeeded or not, now try reinitialising. I2C_init(); _setClock(_clockSpeed); state = I2C_STATE_FREE; -// I2C_sendStop(); // in case device is waiting for a stop condition // Initiate next queued request if any. startTransaction();