-
Notifications
You must be signed in to change notification settings - Fork 354
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
MCP2221 slow i2c, possible latency #603
Comments
What is the device being written to? How many bytes are sent for each write to the device? |
Here's my results from a pca9685, which I think is sending 2 bytes but to be honest I'm not sure! Using this code:
I get this result- Using the same code setup with an aw95230- Interestingly, with a ht16k33 it takes the same amount of time to update one pixel as it does to update 64: with
with
|
It takes 8 seconds to write "Hello\nCircuitPython" to a 16x2 I2C LCD via the MCP2221.
You can see the wiring on this blog article Program output Output
Source Code
The code is located in this Source repository https://github.com/freemansoft/CircuitPython-playground |
I ran a test with the same PC, Python, and Blinka but a different LCD and I2C backpack and got a significantly different result. Probably 10 characters per second using:
|
curious if anybody's working on this issue? i also notice very slow performance from MCP2221, which limits its utility. |
I am also having the same issue. |
Same issue too. Each read of one of my BNO055 register through MCP2221 takes 25ms... It seems to be an issue that a lot of people encountered. |
Sorry for not responding to this thread in...ugh..years. Unfortunately, this is going to be a limit of the MCP2221. It works over USB via raw HID transfers. So there is some latency related to the USB traffic, but also with how the bytes are sent out. It's possible to send multiple bytes in each HID transfer. So some speed improvements can be made that way (vs one byte/HID xfer). But it depends on how the driver is written and if the I2C device itself supports multi-byte read/writes, etc. For example, the LCD character driver sends one character at a time: I'm not seeing 8 seconds though: >>> def foo():
... t1 = time.perf_counter()
... lcd.message = "Hello\nCircuitPython"
... return time.perf_counter() - t1
...
>>> foo()
1.513195158000599 The MCP2221 also only runs at USB 1.0 Full Speed. |
I sped up the CharLCD writes by about a factor of 4 recently: adafruit/Adafruit_CircuitPython_CharLCD#80. That would be downstream from the MCP2221's slowness, but it made it even slower. |
At some point, the bottleneck is the MCP2221. And I think the end result is that it's too slow for what is being attempted here. The character LCD speed may have been improved, but that's taking 8 seconds down to 1 second, which is still fairly slow. There's a chance user code can be tweaked as well. But for trying to read sensor data "quickly" - I don't think there's any hope in that beyond maybe...i dunno...several Hz-ish? I'm trying to think of how best to word this limitation so it can be added to the product guide. Want to provide something more meaningful than just "it's potentially slow...for USB reasons". |
The original post here points to https://forums.adafruit.com/viewtopic.php?p=826229#p826229, which points to https://github.com/nonNoise/PyMCP2221A/blob/master/PyMCP2221A/PyMCP2221A.py as a library that seems to run much faster. Interestingly, that library does not bother to do MCP2221A protocol checks to see if the writes have finished, etc. There are no busy-wait loops in PyMCP2221A. At the low level, it uses a Cython library to do the HID transfers. So I think there may be a faster way to do this. It's worth looking at PyMCP2221A and maybe some others. |
I for one would be happy with an 8X improvement even if it didn't get us to high speed sensor land. |
That's the same low level hid library already being used. Can take a look, but might end up being trade offs of robustness vs. speed. For example, that HID_DELAY was added to fix issues people were seeing on Windows: Note it can be set via an env var. |
@freemansoft Can you test again and see what delay times you are seeing? There may have been various improvements since your original post. I'd hope you'd at least see the timings I got above. ( |
Some quantitative measurements in the guide and/or library README would probably be the best guidance. If we picked some sensor that can return data at a high rate, we can just measure how many measurements per second we can get with the MCP vs direct I2C. |
No change in the timing from 2023. That was fun trying to remember how this was hooked up 2 years ago Try number 1 Windows Desktop
Try number 2 Windows Desktop setting the HID delay as mentioned in a linked postThe HID delay was obviously a bad idea
Try number 3 on Macbook Apple SiliconLooking to see if this was a Windows issue. It was 25 faster.
Windows Installation and configuration for Python tools used in the test
This Adafruit Pi Plate 16x2 is significantly faster when plugged into a Raspberry pi |
Hooked the same LCD panel to an RP2040 running the U2IF firmware with 1.8K pullups on the SCL/SDA lines.
|
I'm having trouble getting adequate i2c speed with the MCP2221.
According to the datasheet:
But interacting with i2c devices seems to be rate limited by something. For example, in my testing I am only able to write to my connected devices ~125 times per second. I think this is an order of magnitude slower than the expected performance but I could be wrong.
Critically, this forum post: MCP2221A has 30ms of latency per write seems to indicate there is no such latency when using the MCP2221 Command Line Interface provided my Microchip. Unfortunately that tool seems to be windows only, so I cannot test it myself (on a Mac).
This is my first time using GitHub so please forgive me!
The text was updated successfully, but these errors were encountered: