-
Notifications
You must be signed in to change notification settings - Fork 39
Description
The Qwiic Button uses sub-one cycle clock stretching on the I2C bus. This causes the standard beginTransmission
endTransmission
'scanner' test for an I2C device to return a false positive.
Steps To Replicate:
Connect an unmodified Qwiic Button to e.g. an Artemis Thing Plus.
Load core v2.1.0.
Upload the following simple 'I2C scanner' sketch:
#include <Wire.h>
void setup()
{
Serial.begin(115200);
Wire.begin();
Wire.setClock(100000);
for (byte address = 1; address < 127; address++ )
{
Wire.beginTransmission(address);
byte error = Wire.endTransmission();
if (error == 0)
{
Serial.print("I2C device found at address 0x");
Serial.println(address, HEX);
}
else
{
Serial.print("I2C error ");
Serial.print(error);
Serial.print(" at address 0x");
Serial.println(address, HEX);
}
}
}
void loop()
{
}
The Qwiic Button has a default address of 0x6F, so you should see this (as captured with an ESP32 Thing Plus):
...
I2C error 2 at address 0x66
I2C error 2 at address 0x67
I2C error 2 at address 0x68
I2C error 2 at address 0x69
I2C error 2 at address 0x6A
I2C error 2 at address 0x6B
I2C error 2 at address 0x6C
I2C error 2 at address 0x6D
I2C error 2 at address 0x6E
I2C device found at address 0x6F
I2C error 2 at address 0x70
I2C error 2 at address 0x71
I2C error 2 at address 0x72
I2C error 2 at address 0x73
I2C error 2 at address 0x74
I2C error 2 at address 0x75
I2C error 2 at address 0x76
...
but instead we get this:
I2C device found at address 0x1
I2C device found at address 0x2
I2C device found at address 0x3
I2C device found at address 0x4
I2C device found at address 0x5
I2C device found at address 0x6
I2C device found at address 0x7
I2C device found at address 0x8
I2C device found at address 0x9
I2C device found at address 0xA
I2C device found at address 0xB
I2C device found at address 0xC
I2C device found at address 0xD
I2C device found at address 0xE
I2C device found at address 0xF
I2C device found at address 0x10
I2C device found at address 0x11
...
Diagnosis:
Looking at the I2C bus with a logic analyzer, we can see the sub-one cycle clock stretching (note the gap before the NACK):
The I2C bus traffic is correct and the processor should see this as a NACK (device not present). But endTransmission
is returning zero. It shouldn't...
Here's the correct ACK at address 0x6F:
Here's the same test at 400kHz. It gives the same false positives. The clock stretching is much more obvious:
But at 50kHz (thank you v2!), all is well. Note the lack of clock-stretching:
...
I2C error 2 at address 0x6B
I2C error 2 at address 0x6C
I2C error 2 at address 0x6D
I2C error 2 at address 0x6E
I2C device found at address 0x6F
I2C error 2 at address 0x70
I2C error 2 at address 0x71
I2C error 2 at address 0x72
I2C error 2 at address 0x73
...
Suspected cause:
I think the root cause is our old friend SMPCNT:
100kHz and 400kHz set SMPCNT to 3:
But the default
setting (which is what would be used for 50kHz), sets SMPCNT to 33 (0x21):
Now, I don't know what the answer to this is... I've tried manually setting SMPCNT for 100kHz and I can't find a value which works. There is a cryptic note in the Apollo3 Blue datasheet:
so maybe only certain values work for SMPCNT which "allow for synchronization time"? Multiples of three perhaps?