Closed pe1obw closed 5 months ago
Hello.
I have no clue. You said that in another similar PC this delay does not happen? It may be some driver that interferes with USB or some weird USB controller.
You can try to activate the trace messages in order to debug the issue. See the end of this section: https://easymcp2221.readthedocs.io/en/latest/api_reference.html#low-level-and-debug (Device.debug_messages and Device.trace_packets).
It might be related to your FPGA or clock stretching. To discard some things, do you experiment the same delay with another scripts? Try some of the ones in https://github.com/electronicayciencia/EasyMCP2221/tree/master/examples. Let's say read/write an EEPROM (well known I2C, no clock stretching) or DAC output (continuous commands, easy to see the timing issues in the scope).
Some of the EasyMCP2221 routines retries multiple times. Maybe your USB port is unreliable and it takes several attempts to get the data.
73
Thanks for answering! I activated the logging but see no errors or unexpected things. 'Internal status' is 55.
It might be related to your FPGA or clock stretching
It's also slow without any slave attached, as shown in the oscilloscope diagram there is quite a long delay between the 'start' condition and the first address byte.
The example program I2C_scan.py
from your site takes minutes to complete (with or without slave attached).
or DAC output (continuous commands, easy to see the timing issues in the scope).
Good idea! The triangle has a period time of 6.5 seconds 😄!
So, also the DAC commands are very slow. Even the mcp = EasyMCP2221.Device()
takes 0.77 seconds.
Some of the EasyMCP2221 routines retries multiple times.
I expected these to be visible in the trace messages. Also, some test code using the PyMCP2221A driver from https://pypi.org/project/PyMCP2221A/ uses the same underlying library and does not have the delays, while using the same USB device. I must say I don't see it as well, there's not so much code in the EasyMCP2221 driver that can do this, I think? Maybe a version conflict? pip freeze
gives me
EasyMCP2221==1.7.1
hidapi==0.14.0
setuptools==69.2.0
(this is the same as on the computer where the software gave no delays).
Thanks anyway, and if you come up with something brilliant I'd be happy to try it, as the EasyMCP2221 driver is the best I could find so far (I also tried pyFTDI - good, but no support for clock stretching).
I could not resist playing with it some more!
The gpio toggle rate with your gpio example code is ~4.6 Hz on my PC, i.e., a bit more than 100ms between each toggle.
After some more experiments, I found that adding a short sleep between the calls to hidapi write()
and read()
helps.
time.sleep(1e-3) # this "fixes" very long delays...
r = self.hidhandler.read(PACKET_SIZE, 50)
With the additional sleep, it toggles at ~250 Hz!
On my PC, the 1ms is a 'magic' value, 0.8 ms is too short, then you see occasional long delays. Weird.
An even better solution was to set the timeout parameter in the read()
to 0, or remove the timeout parameter completely:
r = self.hidhandler.read(PACKET_SIZE)
This works for me, also 250 Hz toggle rate and i2c functionality (read & write) seems to work ok. Any other timeout results in the delay! Do you think the timeout parameter can safely be removed?
Hello.
Thank you for further investigate the issue!
Do you think the timeout parameter can safely be removed?
I'm not sure about the side effects of removing that parameter . I'll try to find out. I'll at least include an option to allow the user to modify it.
I've released EasyMCP2221==1.7.2 without this parameter. Now the HID read should fail after the default 1000ms delay instead of 50ms. Please, can you confirm if that fixed the issue?
Great!
I can confirm that the long delays, observed with v1.7.1, are gone with v1.7.2 🥳! Speed is as expected now, with only the expected USB delays (a few ms) between the transfers.
Also, my other PC, which did not show the delays with v1.7.1 works ok with v1.7.2 (no regression).
Thanks a lot for fixing this!
Hi again.
I've read this part of your README:
The MCP2221A does support clock stretching, but it can leave the i2c bus in a 'hang' state when a transfer is terminated unexpectedly. I could reproduce this by terminating the program while reading the flash contents, after that SDA stayed low and the interface needed to be reset. This problem might be fixed in the future...
I think you mean: https://easymcp2221.readthedocs.io/en/latest/api_reference.html#EasyMCP2221.exceptions.LowSDAError
You can try this if you have one spare i/o pin: Just connect it to the SCL line (with a resistor) and manually cycle it multiple times until the slave finishes the transfer and releases SDA. Then proceed as usual.
Hi,
Great, thanks for pointing me to this hint! Yes, this is the issue, and the proposed workaround will for sure work. Indeed, pulsing SCL 9 times should be enough to free the bus in any case.
I'll try it! I'll put a diode between GPIO and SCL, I think, to avoid ever driving the bus high (e.g., when the MCP2221 has not been configured yet or is misconfigured).
I connected an MCP2221A board to an i2c slave (implemented in FPGA, using clock stretching). Then I made a simple test program:
The code works, but slowwww... There's a long time between the i2c start, the write and the read. See oscilloscope diagram. First you see the start (halfway the first division), then after ~440 ms the write is done, then after 330 ms the read and stop are executed. My PC runs Windows 11 and Python 3.12. On the same PC, the
PyMCP2221A
driver, does not show this delay. However, this driver has other issues (it hangs the bus when reading > 40 bytes) and I like the API of EasyMCP2221 more 😄.On another Windows 11 PC, this all runs without the weird delays!
Any idea? Thanks in advance!