May not be relevant to all of the I2C issues people are seeing, but with respect to occasional (or constant) timeout errors from
i2c_master_cmd_begin, there is a change from IDF v2.x to v3.x that caused problems for me talking to a TI BQ27621 battery monitor. Changes in the I2C driver force the bit-timeout, the timeout the hardware uses to make sure it doesnt get locked up on each bit of the transaction (see ESP32 Technical Reference Manual Section 11.5; Register 11.4), to be much shorter (from about 2.5ms to about 20us fro 400Khz I2C SCL frequency!). This bit-timeout applies to the acknowledge bit as well, so from devices that use clock stretching before acknowledging a read/write to do some work, this timeout can be way too short and terminate the transaction prematurely. I noticed that the premature termination also leads to some strange behavior on the bus as its usually partway through a complete transaction when the transaction is cancelled. In my case, the BQ27621 would stall the acknowledge by ~90us after writing the register address to which you want to read/write; causing bit-timeouts in the new IDF with applications using older IDFs worked fine. Note that this timeout is completely independent from the one passed into
i2c_master_cmd_begin, the former being a timeout on each bit of the transaction, the latter being a timeout on the entire transaction. Luckily, you can change this timeout to be more generous using
i2c_set_timeout, making sure to note that this function takes in a count in APB cycles and is only 20-bits wide, so a maximum timeout of ~13ms is possible (but that should be plenty for even the slowest of I2C devices). So, if you are getting frustrated with weird I2C timeouts and bus behavior (like I was
), just trying setting this timeout to something really generous as it probably wont impact your system much otherwise.