Skip to content

Commit dc2d256

Browse files
committed
adding experimental i2c sda lock clearing
1 parent 134474a commit dc2d256

File tree

2 files changed

+46
-0
lines changed

2 files changed

+46
-0
lines changed

src/MagneticSensorI2C.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,3 +187,46 @@ int MagneticSensorI2C::read(uint8_t angle_reg_msb) {
187187
readValue += ( ( readArray[0] & msb_mask ) << lsb_used );
188188
return readValue;
189189
}
190+
191+
/*
192+
* Checks whether other devices have locked the bus. Can clear SDA locks.
193+
* This should be called before sensor.init() on devices that suffer i2c slaves locking sda
194+
* e.g some stm32 boards with AS5600 chips
195+
* Takes the sda_pin and scl_pin
196+
* Returns 0 for OK, 1 for other master and 2 for unfixable sda locked LOW
197+
*/
198+
int MagneticSensorI2C::checkBus(byte sda_pin, byte scl_pin) {
199+
200+
pinMode(scl_pin, INPUT_PULLUP);
201+
pinMode(sda_pin, INPUT_PULLUP);
202+
delay(250);
203+
204+
if (digitalRead(scl_pin) == LOW) {
205+
// Someone else has claimed master!");
206+
return 1;
207+
}
208+
209+
if(digitalRead(sda_pin) == LOW) {
210+
// slave is communicating and awaiting clocks, we are blocked
211+
pinMode(scl_pin, OUTPUT);
212+
for (byte i = 0; i < 16; i++) {
213+
// toggle clock for 2 bytes of data
214+
digitalWrite(scl_pin, LOW);
215+
delayMicroseconds(20);
216+
digitalWrite(scl_pin, HIGH);
217+
delayMicroseconds(20);
218+
}
219+
pinMode(sda_pin, INPUT);
220+
delayMicroseconds(20);
221+
if (digitalRead(sda_pin) == LOW) {
222+
// SDA still blocked
223+
return 2;
224+
}
225+
_delay(1000);
226+
}
227+
// SDA is clear (HIGH)
228+
pinMode(sda_pin, INPUT);
229+
pinMode(scl_pin, INPUT);
230+
231+
return 0;
232+
}

src/MagneticSensorI2C.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ class MagneticSensorI2C: public Sensor{
5959

6060
int needsAbsoluteZeroSearch() override;
6161

62+
/** experimental function to check and fix SDA locked LOW issues */
63+
int checkBus(byte sda_pin = SDA, byte scl_pin = SCL);
64+
6265
private:
6366
float cpr; //!< Maximum range of the magnetic sensor
6467
uint16_t lsb_used; //!< Number of bits used in LSB register

0 commit comments

Comments
 (0)