Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Espressif: 10ms gap between I2C transactions #6263

Closed
dhalbert opened this issue Apr 7, 2022 · 10 comments · Fixed by adafruit/esp-idf#2 or #6366
Closed

Espressif: 10ms gap between I2C transactions #6263

dhalbert opened this issue Apr 7, 2022 · 10 comments · Fixed by adafruit/esp-idf#2 or #6366
Assignees
Labels
bug busio espressif applies to multiple Espressif chips
Milestone

Comments

@dhalbert
Copy link
Collaborator

dhalbert commented Apr 7, 2022

CircuitPython 7.2.5: tested on FeatherS2 and Adafruit Feather ESP32-S2. Also true as far back as 6.3.0 (did not test further back).

Using the PCA9685 driver, there is at minimum an almost 10ms gap between any two I2C transactions. This causes stepper motor rotations to be very slow, etc. This slowness was first noticed by a user here: https://forums.adafruit.com/viewtopic.php?f=60&t=190046.

I see a similar 10ms gap in some case in the SHT4x library, so I think it is generic to I2C.

@dhalbert dhalbert added bug espressif applies to multiple Espressif chips busio labels Apr 7, 2022
@dhalbert dhalbert added this to the 7.2.x milestone Apr 7, 2022
@dhalbert dhalbert self-assigned this Apr 7, 2022
@KurtE

This comment was marked as off-topic.

@dhalbert
Copy link
Collaborator Author

dhalbert commented Apr 9, 2022

@Neradoc noted in discord:

I was doing I2C tests using the MCP23017 on a feather ESP32S2, and the 10ms delay disappears if I change the bus speed from the default (code that takes 100 ms drops to ~6 ms like on the feather RP2040) - frequency=200_000 for example (edited)

@KurtE

This comment was marked as off-topic.

@Neradoc
Copy link

Neradoc commented Apr 9, 2022

To illustrate what I mentioned on discord, here is a low level test code I've been running, with a couple different I2C devices. It does only 2 reads in this case, I've tried different combinations depending on what the devices support with the same results:

import board
import busio
import time

ADDRESS = 0x20
buffer = bytearray([0] * 10)
def measure_time(frequency = 100_000, nsamples = 10):
    print(f"Frequency @ {frequency:7d}", end="")
    with busio.I2C(scl=board.SCL, sda=board.SDA, frequency=frequency) as i2c:
        times = 0
        for i in range(nsamples):
            i2c.try_lock()
            t0 = time.monotonic_ns()
            i2c.readfrom_into(ADDRESS, buffer)
            i2c.readfrom_into(ADDRESS, buffer)
            # i2c.writeto(ADDRESS, buffer)
            # i2c.writeto_then_readfrom(ADDRESS, buffer, buffer)
            t1 = time.monotonic_ns()
            i2c.unlock()
            times += (t1 - t0)
        mean = times // nsamples // 1000 / 1000
        print(f" {mean:8.3f} ms")

import random
frequencies = [50_000, 80_000, 100_000, 110_000, 120_000, 200_000, 400_000]
# frequencies.sort(key=lambda x: random.random())
for freq in frequencies:
    measure_time(freq)
code.py output:
Frequency @   50000   19.583 ms
Frequency @   80000   19.641 ms
Frequency @  100000   19.641 ms
Frequency @  110000    2.005 ms
Frequency @  120000    1.870 ms
Frequency @  200000    1.193 ms
Frequency @  400000    0.686 ms

Adafruit CircuitPython 7.3.0-beta.1 on 2022-04-07; Adafruit Feather ESP32S2 with ESP32S2

@dhalbert
Copy link
Collaborator Author

Some more findings:

  • For the PCA9685, raising the I2C frequency to 125 kHz causes the problem to go away. 110 kHz does not work for the PCA9685: I get errors which I think reflect data errors talking to the device. I tried various frequencies in between, and there are only small ranges that work.
  • CONFIG_FREERTOS_HZ is the FreeRTOS tick rate, and the rate at which it can switch between tasks. In CircuitPython it is set to 100, which is a typical default. In MicroPython and Arduino, it is set to 1000. Arduino typically shows 1ms gaps at that rate, though sometimes they are shorter. I did not test MicroPython again to get the gap change. I tried changing the Arduino CONFIG_FREERTOS_HZ to 100, but couldn't get it to work: there are cached compilations which I tried to remove, but even after that I could not get a loaded program to run.

@ladyada
Copy link
Member

ladyada commented Apr 14, 2022

what if you change it to like 500?

@dhalbert
Copy link
Collaborator Author

dhalbert commented Apr 15, 2022

what if you change it to like 500?

The gap at 100 kHz bus frequency is the interval defined by CONFIG_FREERTOS_HZ, so 10ms at 100, 2ms at 500, 1ms at 1000. There is still some kind of bug/weirdness, because at, say 125 kHz bus frequency, the gap no longer is proportional to CONFIG_FREERTOS_HZ. For instance, at 125000, the gap reduces from 10ms to 600-700ish microseconds. So there is something unusual about the 100kHz rate compared to higher rates.

I wrote this observation up in espressif/esp-idf#8770 as well.

@dhalbert
Copy link
Collaborator Author

I have reproduced this in a small ESP-IDF example. It is related to clock frequency, and can be ameliorated by a small delay in the ESP-IDF code at a crucial spot.
espressif/esp-idf#8770 (comment)
Awaiting further comments in the ESP-IDF issue.

@jepler
Copy link
Member

jepler commented May 8, 2022

should this really be closed, or should it wait for us to switch to this submodule & ref in main?

@dhalbert
Copy link
Collaborator Author

dhalbert commented May 8, 2022

I did not mean to link the issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug busio espressif applies to multiple Espressif chips
Projects
None yet
5 participants