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

MCP2221 slow i2c, possible latency #603

Open
studiostephe opened this issue Aug 19, 2022 · 17 comments
Open

MCP2221 slow i2c, possible latency #603

studiostephe opened this issue Aug 19, 2022 · 17 comments
Assignees
Labels
bug Something isn't working

Comments

@studiostephe
Copy link

I'm having trouble getting adequate i2c speed with the MCP2221.

According to the datasheet:

The I2C/SMBus Master module has the following capabilities:
• sending/receiving data at a multitude of bit rates, up to 400 kbps

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!

@caternuson
Copy link
Contributor

What is the device being written to? How many bytes are sent for each write to the device?

@studiostephe
Copy link
Author

studiostephe commented Aug 19, 2022

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:

start=time.time()
x=0
while time.time()-start < 1:
	pca.channels[15].duty_cycle = 0xFFFF
	x+=1
print('pca9685 updates in 1 second:', x)

I get this result- pca9685 updates in 1 second: 126

Using the same code setup with an aw95230- aw9523 updates in 1 second: 126

Interestingly, with a ht16k33 it takes the same amount of time to update one pixel as it does to update 64:

with matrix[0, 0] = 1

ht16k33 1 pixel updates in 1 second: 97

with matrix.image(img)

ht16k33 64 pixel updates in 1 second: 97

@freemansoft
Copy link

It takes 8 seconds to write "Hello\nCircuitPython" to a 16x2 I2C LCD via the MCP2221.

  1. Windows 11 desktop that has a 16x2 LCD Pi Plate attached to it over i2c.
  2. There are four wires coming off the LCD that was intended for a gen 1 raspberry pi. 5v, Gnd, SDA, SCL.
  3. Python program is running on the desktop with "Blinka"

You can see the wiring on this blog article

Program output Output

>>> start_hello = time.perf_counter()
>>> lcd.message = "Hello\nCircuitPython"
>>> end_hello = time.perf_counter()
>>> print("draw hello time: " + str(end_hello - start_hello))
draw hello time: 8.082552099999987

Source Code

import os
import board
import hid
import adafruit_character_lcd.character_lcd_rgb_i2c as character_lcd
import time

print(hid.enumerate())
device = hid.device()
device.open(0x04D8, 0x00DD)

start_connect = time.perf_counter()
# Modify this if you have a different sized Character LCD
lcd_columns = 16
lcd_rows = 2
# Initialise I2C bus.
i2c = board.I2C()
start_connect = time.perf_counter()
# Point the driver at the bus / device
lcd = character_lcd.Character_LCD_RGB_I2C(i2c, lcd_columns, lcd_rows)
end_connect = time.perf_counter()
print("conect time: " + str(end_connect - start_connect))

# I have the RGB backlit Adafruit device
lcd.clear()
# Set LCD color to red
lcd.color = [100, 0, 0]
# Print two line message
start_hello = time.perf_counter()
lcd.message = "Hello\nCircuitPython"
end_hello = time.perf_counter()
print("draw hello time: " + str(end_hello - start_hello))

The code is located in this Source repository https://github.com/freemansoft/CircuitPython-playground

@freemansoft
Copy link

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:

@makermelissa makermelissa added the bug Something isn't working label Sep 18, 2023
@truher
Copy link

truher commented Jul 22, 2024

curious if anybody's working on this issue? i also notice very slow performance from MCP2221, which limits its utility.

@BhupiMAD
Copy link

I am also having the same issue.
unable to capture accelerometer data at high speed. Barely reaching 44.5Hz frequency.
Can someone from adafruit shed some light on this?

@TurboBG
Copy link

TurboBG commented Jan 15, 2025

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.

@caternuson
Copy link
Contributor

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:
https://github.com/adafruit/Adafruit_CircuitPython_CharLCD/blob/c7bd36e6399503d30de69da6d452b1e58b62b1d6/adafruit_character_lcd/character_lcd.py#L392
Which ends up adding up the USB HID xfer overhead with each character over the course of the loop.

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.

@dhalbert
Copy link
Contributor

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.

@caternuson
Copy link
Contributor

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".

@dhalbert
Copy link
Contributor

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.

@freemansoft
Copy link

I for one would be happy with an 8X improvement even if it didn't get us to high speed sensor land.

@caternuson
Copy link
Contributor

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:
#243

Note it can be set via an env var.

@caternuson
Copy link
Contributor

@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. (1.513195158000599 secs)

@dhalbert
Copy link
Contributor

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.

@freemansoft
Copy link

freemansoft commented Jan 17, 2025

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

  1. Windows 11 PC
  2. Python 3.19
  3. Adafruit 16x2 i2c LCD Pi Plate scavenged from another project
  4. MCP2221 on a USB1 hub
  5. BLINKA_MCP2221_HID_DELAY not set
  6. Same program as above MCP2221 slow i2c, possible latency  #603 (comment)
  7. 13 characters in 8 seconds - same as beforeTry number 2 - setting the HID delay

Try number 2 Windows Desktop setting the HID delay as mentioned in a linked post

The HID delay was obviously a bad idea

  1. Windows 11 PC
  2. Adafruit 16x2 i2c LCD Pi Plate scavenged from another project
  3. Python 3.19
  4. MCP2221 on a USB1 hub
  5. PS > $env:BLINKA_MCP2221=1
  6. PS > $env:BLINKA_MCP2221_HID_DELAY=0.005
  7. Same program as above MCP2221 slow i2c, possible latency  #603 (comment)
  8. 13 characters in 53 seconds

Try number 3 on Macbook Apple Silicon

Looking to see if this was a Windows issue. It was 25 faster.

  1. 13 characters in 6.3 seconds

Windows Installation and configuration for Python tools used in the test

PS C:\Users\joe\Documents\GitHub\freemansoft> pip3 install adafruit-blinka
Requirement already satisfied: adafruit-blinka in c:\users\joe\appdata\local\packages\pythonsoftwarefoundation.python.3.9_qbz5n2kfra8p0\localcache\local-packages\python39\site-packages (8.51.0)
Requirement already satisfied: Adafruit-PlatformDetect>=3.70.1 in c:\users\joe\appdata\local\packages\pythonsoftwarefoundation.python.3.9_qbz5n2kfra8p0\localcache\local-packages\python39\site-packages (from adafruit-blinka) (3.77.0)
Requirement already satisfied: Adafruit-PureIO>=1.1.7 in c:\users\joe\appdata\local\packages\pythonsoftwarefoundation.python.3.9_qbz5n2kfra8p0\localcache\local-packages\python39\site-packages (from adafruit-blinka) (1.1.9)
Requirement already satisfied: binho-host-adapter>=0.1.6 in c:\users\joe\appdata\local\packages\pythonsoftwarefoundation.python.3.9_qbz5n2kfra8p0\localcache\local-packages\python39\site-packages (from adafruit-blinka) (0.1.6)
Requirement already satisfied: pyftdi>=0.40.0 in c:\users\joe\appdata\local\packages\pythonsoftwarefoundation.python.3.9_qbz5n2kfra8p0\localcache\local-packages\python39\site-packages (from adafruit-blinka) (0.54.0)
Requirement already satisfied: adafruit-circuitpython-typing in c:\users\joe\appdata\local\packages\pythonsoftwarefoundation.python.3.9_qbz5n2kfra8p0\localcache\local-packages\python39\site-packages (from adafruit-blinka) (1.8.3)
Requirement already satisfied: pyserial in c:\users\joe\appdata\local\packages\pythonsoftwarefoundation.python.3.9_qbz5n2kfra8p0\localcache\local-packages\python39\site-packages (from binho-host-adapter>=0.1.6->adafruit-blinka) (3.5)
Requirement already satisfied: pyusb!=1.2.0,>=1.0.0 in c:\users\joe\appdata\local\packages\pythonsoftwarefoundation.python.3.9_qbz5n2kfra8p0\localcache\local-packages\python39\site-packages (from pyftdi>=0.40.0->adafruit-blinka) (1.2.1)
Requirement already satisfied: adafruit-circuitpython-busdevice in c:\users\joe\appdata\local\packages\pythonsoftwarefoundation.python.3.9_qbz5n2kfra8p0\localcache\local-packages\python39\site-packages (from adafruit-circuitpython-typing->adafruit-blinka) (5.2.3)
Requirement already satisfied: adafruit-circuitpython-requests in c:\users\joe\appdata\local\packages\pythonsoftwarefoundation.python.3.9_qbz5n2kfra8p0\localcache\local-packages\python39\site-packages (from adafruit-circuitpython-typing->adafruit-blinka) (1.12.12)
Requirement already satisfied: typing-extensions~=4.0 in c:\users\joe\appdata\local\packages\pythonsoftwarefoundation.python.3.9_qbz5n2kfra8p0\localcache\local-packages\python39\site-packages (from adafruit-circuitpython-typing->adafruit-blinka) (4.12.2)


PS C:\Users\joe\Documents\GitHub\freemansoft> pip3 install hidapi
Requirement already satisfied: hidapi in c:\users\joe\appdata\local\packages\pythonsoftwarefoundation.python.3.9_qbz5n2kfra8p0\localcache\local-packages\python39\site-packages (0.14.0.post4)
Requirement already satisfied: setuptools>=19.0 in c:\program files\windowsapps\pythonsoftwarefoundation.python.3.9_3.9.3568.0_x64__qbz5n2kfra8p0\lib\site-packages (from hidapi) (58.1.0)

PS C:\Users\joe\Documents\GitHub\freemansoft> pip3 install adafruit-circuitpython-charlcd
Requirement already satisfied: adafruit-circuitpython-charlcd in c:\users\joe\appdata\local\packages\pythonsoftwarefoundation.python.3.9_qbz5n2kfra8p0\localcache\local-packages\python39\site-packages (3.5.1)
Requirement already satisfied: Adafruit-Blinka in c:\users\joe\appdata\local\packages\pythonsoftwarefoundation.python.3.9_qbz5n2kfra8p0\localcache\local-packages\python39\site-packages (from adafruit-circuitpython-charlcd) (8.51.0)
Requirement already satisfied: adafruit-circuitpython-mcp230xx in c:\users\joe\appdata\local\packages\pythonsoftwarefoundation.python.3.9_qbz5n2kfra8p0\localcache\local-packages\python39\site-packages (from adafruit-circuitpython-charlcd) (2.5.8)
Requirement already satisfied: adafruit-circuitpython-busdevice in c:\users\joe\appdata\local\packages\pythonsoftwarefoundation.python.3.9_qbz5n2kfra8p0\localcache\local-packages\python39\site-packages (from adafruit-circuitpython-charlcd) (5.2.3)
Requirement already satisfied: adafruit-circuitpython-74hc595 in c:\users\joe\appdata\local\packages\pythonsoftwarefoundation.python.3.9_qbz5n2kfra8p0\localcache\local-packages\python39\site-packages (from adafruit-circuitpython-charlcd) (1.4.1)
Requirement already satisfied: adafruit-circuitpython-typing~=1.5 in c:\users\joe\appdata\local\packages\pythonsoftwarefoundation.python.3.9_qbz5n2kfra8p0\localcache\local-packages\python39\site-packages (from adafruit-circuitpython-charlcd) (1.8.3)
Requirement already satisfied: adafruit-circuitpython-requests in c:\users\joe\appdata\local\packages\pythonsoftwarefoundation.python.3.9_qbz5n2kfra8p0\localcache\local-packages\python39\site-packages (from adafruit-circuitpython-typing~=1.5->adafruit-circuitpython-charlcd) (1.12.12)
Requirement already satisfied: typing-extensions~=4.0 in c:\users\joe\appdata\local\packages\pythonsoftwarefoundation.python.3.9_qbz5n2kfra8p0\localcache\local-packages\python39\site-packages (from adafruit-circuitpython-typing~=1.5->adafruit-circuitpython-charlcd) (4.12.2)
Requirement already satisfied: Adafruit-PlatformDetect>=3.70.1 in c:\users\joe\appdata\local\packages\pythonsoftwarefoundation.python.3.9_qbz5n2kfra8p0\localcache\local-packages\python39\site-packages (from Adafruit-Blinka->adafruit-circuitpython-charlcd) (3.77.0)
Requirement already satisfied: Adafruit-PureIO>=1.1.7 in c:\users\joe\appdata\local\packages\pythonsoftwarefoundation.python.3.9_qbz5n2kfra8p0\localcache\local-packages\python39\site-packages (from Adafruit-Blinka->adafruit-circuitpython-charlcd) (1.1.9)
Requirement already satisfied: binho-host-adapter>=0.1.6 in c:\users\joe\appdata\local\packages\pythonsoftwarefoundation.python.3.9_qbz5n2kfra8p0\localcache\local-packages\python39\site-packages (from Adafruit-Blinka->adafruit-circuitpython-charlcd) (0.1.6)
Requirement already satisfied: pyftdi>=0.40.0 in c:\users\joe\appdata\local\packages\pythonsoftwarefoundation.python.3.9_qbz5n2kfra8p0\localcache\local-packages\python39\site-packages (from Adafruit-Blinka->adafruit-circuitpython-charlcd) (0.54.0)
Requirement already satisfied: pyserial in c:\users\joe\appdata\local\packages\pythonsoftwarefoundation.python.3.9_qbz5n2kfra8p0\localcache\local-packages\python39\site-packages (from binho-host-adapter>=0.1.6->Adafruit-Blinka->adafruit-circuitpython-charlcd) (3.5)
Requirement already satisfied: pyusb!=1.2.0,>=1.0.0 in c:\users\joe\appdata\local\packages\pythonsoftwarefoundation.python.3.9_qbz5n2kfra8p0\localcache\local-packages\python39\site-packages (from pyftdi>=0.40.0->Adafruit-Blinka->adafruit-circuitpython-charlcd) (1.2.1)
PS C:\Users\joe\Documents\GitHub\freemansoft> pip3 install hidapi
Requirement already satisfied: hidapi in c:\users\joe\appdata\local\packages\pythonsoftwarefoundation.python.3.9_qbz5n2kfra8p0\localcache\local-packages\python39\site-packages (0.14.0.post4)
Requirement already satisfied: setuptools>=19.0 in c:\program files\windowsapps\pythonsoftwarefoundation.python.3.9_3.9.3568.0_x64__qbz5n2kfra8p0\lib\site-packages (from hidapi) (58.1.0)

This Adafruit Pi Plate 16x2 is significantly faster when plugged into a Raspberry pi

@freemansoft
Copy link

freemansoft commented Jan 20, 2025

Hooked the same LCD panel to an RP2040 running the U2IF firmware with 1.8K pullups on the SCL/SDA lines.

  • It took 3.2 seconds for my sample program to write "Hello\nCircuitPython" to the U2IF device using the same Windows desktop as above.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

8 participants