-
Notifications
You must be signed in to change notification settings - Fork 319
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
Add support for multiple mcp2221 i2c busses #496
Conversation
aa42ce2
to
d0cca8d
Compare
This is for using with multiple MCP221s? What is driving the need for more than one I2C bus? |
On my side I use multiple mcp2221a modules for these 3 use-cases:
|
It's now superseded by `examples/mcp2221_multiple_busio_i2c.py`.
d113087
to
9447b81
Compare
Rebased on |
I have a similar setup, and I need to access different sensors connected to multiple MCPs. I tried this PR and the example works:>>> import os
>>> os.environ['BLINKA_MCP2221'] = '1'
>>> os.environ['BLINKA_MCP2221_RESET_DELAY'] = '-1'
>>> import board
>>>
>>> import hid, busio
>>>
>>> MCP2221_VID = 0x04D8
>>> MCP2221_PID = 0x00DD
>>>
>>> i2c_busses = []
>>> addresses = [mcp["path"] for mcp in hid.enumerate(MCP2221_VID, MCP2221_PID)]
>>>
>>> for address in addresses:
... i2c_busses.append(busio.I2C(bus_id=address))
...
>>> for i2c in i2c_busses:
... print("I2C devices found: ", [hex(i) for i in i2c.scan()])
...
I2C devices found: ['0x58']
I2C devices found: ['0x77'] However, if I try the following I get an error: >>> from adafruit_blinka.microcontroller.mcp2221.mcp2221 import MCP2221
>>> MCP2221.get_instance()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File ".../adafruit_blinka/microcontroller/mcp2221/mcp2221.py", line 80, in get_instance
instance = MCP2221()
File ".../adafruit_blinka/microcontroller/mcp2221/mcp2221.py", line 65, in __init__
self._reset()
File ".../adafruit_blinka/microcontroller/mcp2221/mcp2221.py", line 169, in _reset
self._hid.open_path(device_new_path)
File "hid.pyx", line 139, in hid.device.open_path
RuntimeError: already open I also tried physically disconnecting the sensors and reconnecting and still got the same error. The same happens when I simply try to `import board` in my code:File "myscript.py", line 16, in <module>
import board
File ".../board.py", line 180, in <module>
from adafruit_blinka.board.microchip_mcp2221 import *
File ".../adafruit_blinka/board/microchip_mcp2221.py", line 2, in <module>
from adafruit_blinka.microcontroller.mcp2221 import pin
File ".../adafruit_blinka/microcontroller/mcp2221/pin.py", line 5, in <module>
mcp2221 = MCP2221.get_instance()
File ".../adafruit_blinka/microcontroller/mcp2221/mcp2221.py", line 80, in get_instance
instance = MCP2221()
File ".../adafruit_blinka/microcontroller/mcp2221/mcp2221.py", line 65, in __init__
self._reset()
File ".../adafruit_blinka/microcontroller/mcp2221/mcp2221.py", line 169, in _reset
self._hid.open_path(device_new_path)
File "hid.pyx", line 139, in hid.device.open_path
RuntimeError: already open This prevents me to run further tests. In addition, since I'm using two different sensors (one per MCP), in order to create two sensor instances I should:
This is a bit complicated, but I can't think of any other way to find and instantiate the sensors. It might be useful to have a method in the Finally, the PR removes the global If this is done, the changes to |
It looks like the mcp2221 is already used by something else, maybe a test code left running or something? Did you physically disconnect only the sensor from the i2c bus or the full mcp2221 from the usb bus? Disconnecting the mcp2221 from the usb bus should unbind it from at least userspace code. Another datapoint that I can provide right now is that |
I was able to solve the errors reported in my previous message and run a single sensor connected through an MCP2221:
Once I had one sensor running, I worked towards having both of them running. Currently I have multiple independent scripts -- one per sensor -- that I launch in separate processes, whereas I think you (@fgervais) run everything in a single process. The proposed PR seems to work for the single-process scenario, but not for multiple processes:
In order to fix these issues, I tweaked the Currently, if a valid
While this is working fine for me, I'm still not convinced it's the best approach:
I'm still working on solving these issues and doing more tests. Let me know if you want me to update this PR or create a separate one, either based on this or ex-novo. |
Sync the `multiple-mcp2221` branch with upstream
Upon further testing it appears that supporting multiple separate processes might not be doable -- at least without breaking backward compatibility. The
@caternuson, would it be ok to remove the global |
Superseded by #637. |
Thanks for your work on this! |
There a couple different use-cases highlighted in the provided examples. The main one probably being the one where we get all mcp2221 busses:
The current use-case with a single or the first device is still supported as-is or with sda/scl arguments left out:
Those changes should also allow merging in https://github.com/adafruit/Adafruit_Python_Extended_Bus quite easily.
Other Considerations
For now the multiple device support only works for i2c and the pin functionality always work only on the first one like it was before.
I will probably provide the multiple device support for pins in a follow up if I need it in my project. As there is no regression I think it's acceptable to leave it out for now.
Note that the change in busio.I2C._init_() has been done forcing the new parameter as a named argument so you stay in control of the positional arguments and so could add some in the future without breaking code using multiple MCP2221 devices.