how to test by i2c scanner at different Wire.setClock(i2cclock) reliably

tito-t:
As Wire.setClock() does not return an error if an arbitrary clock speed is not supportet and cannot be set, how can I be sure then that the i2c clock actually had run at the desired speed and was performed correctly?

You can't.
This is a problem for MANY of the APIs that team arduino created.
They didn't define the API with return status so you can't tell when things work/don't-work/fail.

There is no work around for this in s/w.
You have some options and IMO, they all kind of suck.

  • You can try to see what is supported by looking at the i2c code.
    The issue with this is that each core has its own code and they don't all have the same capabilities or support the same rates or behave the same way for unsupported clock rates.
    A core may pick a clock that is the highest rate supported that does not exceed the requested rate.
    Another core may not change the clock at all if it isn't one of the specific ones supported.
    I have seen both of these behaviors in various cores.
    I even saw one core that picked the closest one supported even if it was over the requested rate.
    IMO, this last one is just plain wrong, and I argued with the authors about it, but they refused to change it.

So what might work for AVR, may not work for ARM, ESP8266, or pic32.
Even worse, some microcontrollers have Arduino core code provided by more than one vendor.
For example, there are multiple boards that use ARM controllers but they use different Arduino cores.
i.e. DUE and Teensy3 are both ARM but they each use their own Arduino core code and board package libraries.

  • You can hook up a logic analyzer or scope and watch the signals.
    This is the only true way to see what clock rate the bus is actually using.
    Unfortunately, there is no way to automate this with a s/w test.

  • You could spin through the possible frequencies you want to test and see if they appear to "work".
    This issue with this, is that testing for reliability when overclocking is not a simple task.
    It requires more than just a simple "hey, look, Ma, it works" type of test that merely does a handshake or moves a bit of small bit of data.

In the larger picture, the maximum reliable clock rate used for a slave is determined by the chipset used by the slave. You can find this by looking at the datasheet for the chipset used by the slave device.

If you are wanting to push the slave beyond its specified ratings, then determining what is "reliable" is more complex than just a simple test.
You have test across temperature ranges, voltage ranges, and various pullup values AND you have to do this with all the slaves attached as there can be interaction between them as the slaves get pushed beyond their specs.
So even if the Wire library setClock() API did provide a means for determining if a desired clock frequency was actually supported, it isn't as simple as doing a simple handshake or small data transfer to determine if a frequency is reliable for the slave, particularly when over-clocking the slave on a bus with multiple slaves.

Also keep in mind that there are various issues in i2c h/w and s/w which can make Arduino libraries or i2c h/w unstable and lock-up when unexpected things happen on the i2c buss.
(And unexpected things will happen when overclocking slaves)
I have seen these types of issues in several cores including the AVR Wire library code.
That core can lock up if there is a glitch on the SDA signal right on the final status bit.
It will confuse the AVR Master i2c h/w into thinking that there is another Master on the bus so it backs off waiting for the other Master to complete. But since there is not another master and the s/w doesn't account for this, the s/w is waiting for interrupt from the other Master completing its transaction that never occurs.
At this point the Wire code is hung in a loop and will never return back to the sketch.

The pic32 core has an issue that if you don't wait long enough between the end and the beginning of a transaction, the i2c h/w will lockup. The period of time that you must wait is based on the clock frequency used.
The easy thing in that case is to simply wait 20us as that works on the low end so it will also work on the higher frequencies.

These are the two cores I've tested the most, but I'm sure other cores probably have similar issues.

For maximum reliability, my recommendation would be look at the datasheets for all your slaves that you intend to use at the same time.
Pick the lowest maximum i2c frequency specified in the datasheets by all the slaves being used, and use that with setClock()
That will give the highest reliable i2c frequency for all the slaves being used.

100k is supported by pretty much everything.
If you avoid older chips you can move up to 400k.
Beyond that, it really starts to thin out.

--- bill