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

Add support for MCP23x08, MCP23x17 #199

Open
keriszafir opened this issue Feb 14, 2016 · 27 comments · May be fixed by #651
Open

Add support for MCP23x08, MCP23x17 #199

keriszafir opened this issue Feb 14, 2016 · 27 comments · May be fixed by #651
Projects

Comments

@keriszafir
Copy link

Very popular I/O expanders from Microchip:
MCP23008 - I2C, 8 channels
MCP23017 - I2C, 16 channels
MCP23S08 - SPI, 8 channels
MCP23S17 - SPI, 16 channels

The channels on these devices can be set individually as inputs or outputs, with or without pullup. Interrupt service on inputs is possible.

Up to 8 MCP230xx can run on a single I2C bus, giving the Raspberry's user 128 new GPIOs.

@bennuttall
Copy link
Member

Good suggestion. We'll add these when we get chance. Feel free to pitch in if you feel you can - take a look at the existing base classes for MCP* chips.

@bennuttall
Copy link
Member

@pcopa
Copy link

pcopa commented Feb 14, 2016

Off topic: Can spi and i2c coexist on the same board?

@bennuttall
Copy link
Member

Both SPI and I2C are present on the Raspberry Pi.

@waveform80
Copy link
Member

Yup, this was largely the point of the pins implementation - to allow IO expanders like this to be used with all the existing device classes. Basically what we'll need to support these is a Device class to represent the chip itself which in turn exposes Pin descendents via some property or properties. I'll start looking into it when I get the chance, but it's not going to be soon I'm afraid (too much on my plate already).

@keriszafir
Copy link
Author

I think that these chips should be instances of CompositeDevice (you can configure both inputs and outputs on a single chip), and the GPIOs would then be added to the pool of available ports starting with some initial number (65), chip by chip, ascending by the I2C address. So for MCP23017 at 0x20 we have GPIO65 ... GPIO80, for the chip at 0x21 - GPIO81...GPIO96 etc. The user would then set devices on them like on the normal Raspberry's GPIOs (although the underlying logic will differ, as they're not Broadcom GPIOs).

@waveform80
Copy link
Member

CompositeDevice would be the logical ancestor at the moment, but I'm actually re-working that bit of the hierarchy right now after @lurch (rightly) pointed out that AnalogInputDevice really isn't a composite device (and nor are its descendents in terms of functionality), while everything else shares enough common collection functionality that we ought to gather it into a "real" CompositeDevice class. So, shortly there's going to be a rather bare Device at the base of the hierarchy, GPIODevice, CompositeDevice will descend from that and I suspect SPIDevice and I2CDevice will too. The classes mentioned above would then likely descend from I2CDevice.

As to pin numbering: sorry, we've already got a fairly good mechanism for this worked out. Device classes don't expect integer numbers any more - you can still specify them for the sake of backwards compatibility and convenience, but actually devices expect a Pin implementation (of which there are several). So, the following lines are equivalent:

from gpiozero.pins.rpigpio import RPiGPIOPin
from gpiozero import LED

led = LED(17)
led = LED(RPiGPIOPin(17))

i.e. if devices get an integer number they just assume it's a GPIO number and construct a DefaultPin instance with that number before continuing (see https://github.com/RPi-Distro/python-gpiozero/blob/master/gpiozero/devices.py#L231). You can also use alternate pin implementations like so:

from gpiozero.pins.rpio import RPIOPin
from gpiozero import LED

led = LED(17)
led = LED(RPIOPin(17))

The purpose of this is that IO expander chips can simply provide their pins from a property and they can be numbered exactly as they appear on the chip (or whatever makes the most sense). So in future, once such device classes are implemented we should be able to do things like:

from gpiozero import LED, MCP23017

expander = MCP23017(address=0x20)
led = LED(expander.pins[0])

@peter-allday
Copy link

Hi this would be really useful to me too, as I am just starting a project that will use 2 or 3 of these boards. I just wondered if you had any idea of the current estimates on when you think you are likely to get around to it. I did have a look at the code, but I am way too much of a Python beginner to even know where to start.

@bennuttall
Copy link
Member

I don't think any of us have these chips yet. If you find any Python code that lets you use pins via an extender please post it here for reference.

@lurch
Copy link
Contributor

lurch commented Mar 3, 2016

There's some code here https://github.com/quick2wire/quick2wire-python-api/tree/master/quick2wire/parts but I dunno how easy/hard it'll be to untangle it from the rest of the quick2wire stuff.

EDIT: (There's also http://raspi.tv/2013/using-the-mcp23017-port-expander-with-wiringpi2-to-give-you-16-new-gpio-ports-part-3 but AFAIK it's just a python-wrapper on top of the underlying C-code in the wiringpi library)

EDIT2: Although the RasPi.TV article does have a link to http://www.raspberrypi-spy.co.uk/2013/07/how-to-use-a-mcp23017-i2c-port-expander-with-the-raspberry-pi-part-2/

@peter-allday
Copy link

@bennuttall bennuttall added this to the v1.3 milestone Apr 5, 2016
@mattjlewis
Copy link

@bennuttall
Copy link
Member

There's the start of a Python lib here: https://github.com/ResonantWave/mcp23017_lib

@bennuttall bennuttall mentioned this issue Jun 2, 2016
10 tasks
@waveform80 waveform80 modified the milestones: v1.3, v1.4 Aug 30, 2016
@dgtlmoon
Copy link

dgtlmoon commented Oct 14, 2016

I have the very common PiFace interface board ( http://www.piface.org.uk/products/piface_digital/ ), is there anything I can do to test here? there's some existing library at https://github.com/piface/pifacedigitalio

@dgtlmoon
Copy link

Should this issue be 'closed' ? or still open as a request of some sort?

@bennuttall
Copy link
Member

This issue is still open because none of the chips have yet been added to the library. I2C support is on the list but not in active development. We plan to add some expander chips too, same situation.

pifacedigital might be worth considering. I'm not sure what it includes off the top of my head but I'll take a look another time. If it requires I2C or these expander chips it'll have to wait for those to be added. If you want, create a new issue and we'll see.

@dgtlmoon
Copy link

PiFace is the MCP23S17 (mentioned in the 3rd comment). OK thanks, I'll create a new ticket and see how it goes, happy to test here

@bennuttall bennuttall modified the milestones: v1.4, v1.5 Dec 1, 2016
@ffleandro
Copy link

I have a simple example of controlling input and output pins of a MCP23017 from Python.


import smbus
import time
 
#bus = smbus.SMBus(0)  # Rev 1 Pi uses 0
bus = smbus.SMBus(1) # Rev 2 Pi uses 1
 
DEVICE = 0x20 # Device address (A0-A2)
IODIRA = 0x00 # Pin direction register
IODIRB = 0x01 # Pin direction register
GPPUA  = 0x0C # Pin pull register
GPPUB  = 0x0D # Pin pull register
GPIOA  = 0x12 # Register for inputs
GPIOB  = 0x13 # Register for inputs
OLATA  = 0x14 # Register for outputs
OLATB  = 0x15 # Register for outputs

# Set pins 1 to 4 from module A as inputs 
bus.write_byte_data(DEVICE,IODIRA,0x7E) # 0001 1110
# Set pins 1 to 4 from module A as pull-up
bus.write_byte_data(DEVICE,GPPUA,0x7E)  # 0001 1110
# Set all pins from module B as output
bus.write_byte_data(DEVICE,IODIRB,0x00)


i = 0
while True:
	if i % 2 == 0: # Set all outputs ON
		bus.write_byte_data(DEVICE, OLATB, 0x1E) # 30 = 1E = 0001 1110
	else: # Set all outputs OFF
		bus.write_byte_data(DEVICE, OLATB, 0x00)

	# Read state of GPIOA register
	input_mask = bus.read_byte_data(DEVICE, GPIOA)
	print(input_mask)
	
	if input_mask & 0b00000010 == 0b00000010:
		print("Switch 1 was pressed!")

	if input_mask & 0b00001000 == 0b00001000:
		print("Switch 3 was pressed!")

	i += 1
	time.sleep(1)

I'll try to follow @waveform80 recomendations and create a MCP23017 Pin implementation.

@ffleandro
Copy link

For future reference, there is this Adafruit library: https://github.com/adafruit/Adafruit_Python_GPIO

@ffleandro
Copy link

Also, these are the equivalent commands for configuring and sending output commands using the pigs client from pigpio library.

$ pigs i2co 1 0x20 0 //open returns handle 0
$ pigs i2cwb 0 0x00 0x7E //configure IODIRA
$ pigs i2cwb 0 0x0C 0x7E //configure GPPUA
$ pigs i2cwb 0 0x01 0x00 //configure IODIRB
$ pigs i2cwb 0 0x15 0x1E //output pins to HIGH
$ pigs i2cwb 0 0x15 0x00 //output pins to LOW
$ pigs i2cc 0 //close handle 0

@mgiaco
Copy link

mgiaco commented Mar 7, 2018

Can I help here in any way? Also a very important device is the good old http://www.ti.com/product/PCF8574 which is also supported by the Adafruit Lib

pmuller added a commit to pmuller/python-gpiozero that referenced this issue May 28, 2018
@pmuller pmuller linked a pull request May 28, 2018 that will close this issue
pmuller added a commit to pmuller/python-gpiozero that referenced this issue May 28, 2018
pmuller added a commit to pmuller/python-gpiozero that referenced this issue May 28, 2018
pmuller added a commit to pmuller/python-gpiozero that referenced this issue May 28, 2018
pmuller added a commit to pmuller/python-gpiozero that referenced this issue May 28, 2018
pmuller added a commit to pmuller/python-gpiozero that referenced this issue May 28, 2018
pmuller added a commit to pmuller/python-gpiozero that referenced this issue May 28, 2018
@pmuller
Copy link
Contributor

pmuller commented May 28, 2018

I created a PR for MCP23008 and MCP23017 support : #651
Would be great to get some feedback !

pmuller added a commit to pmuller/python-gpiozero that referenced this issue Jun 24, 2018
pmuller added a commit to pmuller/python-gpiozero that referenced this issue Jun 24, 2018
pmuller added a commit to pmuller/python-gpiozero that referenced this issue Jun 24, 2018
pmuller added a commit to pmuller/python-gpiozero that referenced this issue Jul 17, 2018
@ryanteck
Copy link
Contributor

Is there a status update for this? I have a project that I plan to use this chip in and was expecting it to be added in GPIOZero. Not an issue if not. Was just interested.

@bennuttall bennuttall removed this from the v1.5 milestone Oct 4, 2018
@bennuttall bennuttall added this to Pending suggestions in Triage Feb 11, 2019
@hyansuper
Copy link

When I2C is added, will it be remotely controlled by setting PiGPIOFactory host?

@EternityForest
Copy link

Perhaps this should be a subclass of a new LinuxTWIDevice which descends from TWIDevice. Having the ability to send raw I2C to any device would be useful for education, and having that API would be very valuable with wiringPi on the way out.

@lurch lurch mentioned this issue Apr 28, 2020
@alittlebitweird
Copy link

I’ve been eyeballing this issue for a couple years. Any progress on this front?

@sq6emm
Copy link

sq6emm commented Jan 6, 2023

any progress here?:)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Triage
  
Pending suggestions
Development

Successfully merging a pull request may close this issue.