-
- Posts: 20
- Joined: Thu Aug 27, 2015 1:07 pm
- Location: Minneapolis, MN, USA
ISO GPIO pins 41-x expander
I have done some googling in an attempt to find a GPIO "expander", I am coming up with things like MCP230XX but that seems to be designed for the Pi 1. I am looking for an expander that will give me pins 41 and beyond(in total I need 65 unique [i.e. not a multiplexer] generic I/O pins) for the raspberry pi 2 and beyond (40 pin GPIO style) any products available?
Re: ISO GPIO pins 41-x expander
The MCP230XX series was certainly not designed specifically for the Pi 1. Whilst many tutorials may use a Pi 1, it will work just as well with any other version of the Pi (and thousands of other microcontrollers/processors).rhinotekmn wrote: ↑Thu Apr 12, 2018 9:53 pmI have done some googling in an attempt to find a GPIO "expander", I am coming up with things like MCP230XX but that seems to be designed for the Pi 1. I am looking for an expander that will give me pins 41 and beyond(in total I need 65 unique [i.e. not a multiplexer] generic I/O pins) for the raspberry pi 2 and beyond (40 pin GPIO style) any products available?
8 MCP230XX chips can share an I2C bus meaning that with the following parts you can have a large number of GPIO pins
8x MCP23008 = 64 GPIO pins
8x MCP23017 = 128 GPIO pins.
Electronic and Computer Engineer
Pi Interests: Home Automation, IOT, Python and Tkinter
Pi Interests: Home Automation, IOT, Python and Tkinter
- DougieLawson
- Posts: 40825
- Joined: Sun Jun 16, 2013 11:19 pm
- Location: A small cave in deepest darkest Basingstoke, UK
- Contact: Website Twitter
Re: ISO GPIO pins 41-x expander
The MCP23017 or MCP23008 is an I2C device that works on every model of RPi (26 pin or 40 pin). You can stack up to eight MCP23017s on a single bus to give you an extra 128 GPIO pins.
https://pinout.xyz/pinout/i2c
https://pinout.xyz/pinout/i2c
Any language using left-hand whitespace for syntax is ridiculous
Any DMs sent on Twitter will be answered next month.
Fake doctors - are all on my foes list.
Any requirement to use a crystal ball or mind reading will result in me ignoring your question.
Any DMs sent on Twitter will be answered next month.
Fake doctors - are all on my foes list.
Any requirement to use a crystal ball or mind reading will result in me ignoring your question.
Re: ISO GPIO pins 41-x expander
Is there an echo in here? 

Electronic and Computer Engineer
Pi Interests: Home Automation, IOT, Python and Tkinter
Pi Interests: Home Automation, IOT, Python and Tkinter
- DougieLawson
- Posts: 40825
- Joined: Sun Jun 16, 2013 11:19 pm
- Location: A small cave in deepest darkest Basingstoke, UK
- Contact: Website Twitter
Re: ISO GPIO pins 41-x expander
E C H O
Maybe, I didn't see your post when I wrote mine.
echo
Any language using left-hand whitespace for syntax is ridiculous
Any DMs sent on Twitter will be answered next month.
Fake doctors - are all on my foes list.
Any requirement to use a crystal ball or mind reading will result in me ignoring your question.
Any DMs sent on Twitter will be answered next month.
Fake doctors - are all on my foes list.
Any requirement to use a crystal ball or mind reading will result in me ignoring your question.
-
- Posts: 371
- Joined: Thu Mar 28, 2013 9:19 am
- Location: Nottingham, UK
Re: ISO GPIO pins 41-x expander
As an aside, if you use the excellent wiringpi library, this will also let you address those pins using the same mechanism as you do for other pins.
This assumes you use C or C++. Can anyone tell me if there is a python/python3 wrapper for the library that allows the same functionality?
I am slowly coming to terms with learning Python, despite my initial misgivings about using an interpretive language on a (relatively) small system.
This assumes you use C or C++. Can anyone tell me if there is a python/python3 wrapper for the library that allows the same functionality?
I am slowly coming to terms with learning Python, despite my initial misgivings about using an interpretive language on a (relatively) small system.
Steve S
No, I can't think of anything funny that won't offend someone if they want it to...
No, I can't think of anything funny that won't offend someone if they want it to...
-
- Posts: 20
- Joined: Thu Aug 27, 2015 1:07 pm
- Location: Minneapolis, MN, USA
Re: ISO GPIO pins 41-x expander
Thank you for the clarification! I am thinking I will go with the MCP23017. However, I am very new to Python coding. The following code is what I worked out (with the help of my contributors on this forum) using the original 40 pins(3 of which I am using here)...scotty101 wrote: ↑Fri Apr 13, 2018 8:52 amThe MCP230XX series was certainly not designed specifically for the Pi 1. Whilst many tutorials may use a Pi 1, it will work just as well with any other version of the Pi (and thousands of other microcontrollers/processors).rhinotekmn wrote: ↑Thu Apr 12, 2018 9:53 pmI have done some googling in an attempt to find a GPIO "expander", I am coming up with things like MCP230XX but that seems to be designed for the Pi 1. I am looking for an expander that will give me pins 41 and beyond(in total I need 65 unique [i.e. not a multiplexer] generic I/O pins) for the raspberry pi 2 and beyond (40 pin GPIO style) any products available?
8 MCP230XX chips can share an I2C bus meaning that with the following parts you can have a large number of GPIO pins
8x MCP23008 = 64 GPIO pins
8x MCP23017 = 128 GPIO pins.
Code: Select all
import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(xa1,GPIO.OUT)
GPIO.setup(xa2.GPIO.OUT)
GPIO.setup(xV,GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
while True:
if GPIO.input(xV):
GPIO.output(xa1,GPIO.HIGH)
GPIO.output(xa2,GPIO.LOW)
else:
GPIO.output(xa2,GPIO.HIGH)
GPIO.output(xa1,GPIO.LOW)
time.sleep(0.1)
- DougieLawson
- Posts: 40825
- Joined: Sun Jun 16, 2013 11:19 pm
- Location: A small cave in deepest darkest Basingstoke, UK
- Contact: Website Twitter
Re: ISO GPIO pins 41-x expander
Here's a python class that makes driving a MCP23017 easier
Code: Select all
#!/usr/bin/python
# (C) 2017, 2018 Copyright Darkside Logic (One) Ltd. All rights reserved
# Version 0.9.3
import smbus
import syslog
class pinControl():
def __init__(self, addr = 0x27, active='HIGH', aDir = 0x00, bDir = 0x00):
self.ADDR = addr
self.active = (True if active == 'HIGH' else False)
self.IODIRA = 0x00
self.IODIRB = 0x01
self.IPOLA = 0x02
self.IPOLB = 0x03
self.GPINTENA = 0x04
self.GPINTENB = 0x05
self.DEFVALA = 0x06
self.DEFVALB = 0x07
self.INTCONA = 0x08
self.INTCONB = 0x09
self.IOCON1 = 0x0A
self.IOCON2 = 0x0B
self.GPPUA = 0x0C
self.GPPUB = 0x0D
self.INTFA = 0x0E
self.INTFB = 0x0F
self.INTCAPA = 0x10
self.INTCAPB = 0x11
self.GPIOA = 0x12
self.GPIOB = 0x13
self.OLATA = 0x14
self.OLATB = 0x15
self.bus=smbus.SMBus(1)
self.valueA = 0
self.valueB = 0
self.ipolA = 0
self.ipolB = 0
self.gpintenA = 0
self.gpintenB = 0
self.defvalA = 0
self.defvalB = 0
self.intconA = 0
self.intconB = 0
self.gppuA = 0
self.gppuB = 0
try:
self.bus.write_byte_data(self.ADDR,self.IODIRA,aDir)
self.bus.write_byte_data(self.ADDR,self.IODIRB,bDir)
self.chipOK = True
except:
self.chipOK = False
def pinOn(self, bank, pin):
if self.chipOK:
# print (bank, pin, "On")
bit = pin - 1
if bank == 'B':
if self.active:
self.valueB = self.valueB | (1 << bit)
else:
self.valueB = self.valueB & (0xff - (1 << bit))
self.bus.write_byte_data(self.ADDR, self.OLATB, self.valueB)
else:
if self.active:
self.valueA = self.valueA | (1 << bit)
else:
self.valueA = self.valueA & (0xff - (1 << bit))
self.bus.write_byte_data(self.ADDR, self.OLATA, self.valueA)
def pinOff(self, bank, pin):
if self.chipOK:
# print (bank, pin, "Off")
bit = pin - 1
if bank == 'B':
if self.active:
self.valueB = self.valueB & (0xff - (1 << bit))
else:
self.valueB = self.valueB | (1 << bit)
self.bus.write_byte_data(self.ADDR, self.OLATB, self.valueB)
else:
if self.active:
self.valueA = self.valueA & (0xff - (1 << bit))
else:
self.valueA = self.valueA | (1 << bit)
self.bus.write_byte_data(self.ADDR, self.OLATA, self.valueA)
def pinAllOff(self):
if self.chipOK:
# print "All off called"
if self.active:
self.valueA = 0x00
else:
self.valueA = 0xFF
self.bus.write_byte_data(self.ADDR, self.OLATA, self.valueA)
if self.active:
self.valueB = 0x00
else:
self.valueB = 0xFF
self.bus.write_byte_data(self.ADDR, self.OLATB, self.valueB)
def pinRead(self, bank, pin):
if self.chipOK:
bit = pin - 1
if bank == 'B':
busVal = self.bus.read_byte_data(self.ADDR, self.GPIOB)
self.valueB = busVal
state = ((busVal & (1 << bit)) != 0)
else:
busVal = self.bus.read_byte_data(self.ADDR, self.GPIOA)
self.valueA = busVal
state = ((busVal & ( 1<< bit)) != 0)
return "pinRead Bank:", bank, " Pin:", pin, state
else:
return None
def readIOCON(self):
if self.chipOK:
busVal1 = self.bus.read_byte_data(self.ADDR, self.IOCON1)
busVal2 = self.bus.read_byte_data(self.ADDR, self.IOCON2)
return busVal1, busVal2
else:
return None, None
def setMIRROR(self, bit = 6):
if self.chipOK:
busVal1 = self.bus.read_byte_data(self.ADDR, self.IOCON1)
busVal1 = busVal1 | (1 << bit)
self.bus.write_byte_data(self.ADDR, self.IOCON1, busVal1)
busVal2 = self.bus.read_byte_data(self.ADDR, self.IOCON2)
busVal2 = busVal2 | (1 << bit)
self.bus.write_byte_data(self.ADDR, self.IOCON1, busVal2)
def resetMIRROR(self, bit = 6):
if self.chipOK:
busVal1 = self.bus.read_byte_data(self.ADDR, self.IOCON1)
busVal1 = busVal1 & (0xff - (1 << bit))
self.bus.write_byte_data(self.ADDR, self.IOCON1, busVal1)
busVal2 = self.bus.read_byte_data(self.ADDR, self.IOCON2)
busVal2 = busVal2 & (0xff - (1 << bit))
self.bus.write_byte_data(self.ADDR, self.IOCON2, busVal2)
def setIPOL(self, bank, pin):
if self.chipOK:
bit = pin - 1
if bank == 'B':
self.ipolB = self.ipolB | (1 << bit)
self.bus.write_byte_data(self.ADDR, self.IPOLB, self.ipolB)
else:
self.ipolA = self.ipolA | (1 << bit)
self.bus.write_byte_data(self.ADDR, self.IPOLA, self.ipolA)
def resetIPOL(self, bank, pin):
if self.chipOK:
bit = pin - 1
if bank == 'B':
self.ipolB = self.ipolB & (0xff - (1 << bit))
self.bus.write_byte_data(self.ADDR, self.IPOLB, self.ipolB)
else:
self.ipolA = self.ipolA & (0xff - (1 << bit))
self.bus.write_byte_data(self.ADDR, self.IPOLA, self.ipolA)
def setGPINTEN(self, bank, pin):
if self.chipOK:
bit = pin - 1
if bank == 'B':
self.gpintenB = self.gpintenB | (1 << bit)
self.bus.write_byte_data(self.ADDR, self.GPINTENB, self.gpintenB)
else:
self.gpintenA = self.gpintenA | (1 << bit)
self.bus.write_byte_data(self.ADDR, self.GPINTENA, self.gpintenA)
def resetGPINTEN(self, bank, pin):
if self.chipOK:
bit = pin - 1
if bank == 'B':
self.gpintenB = self.gpintenB & (0xff - (1 << bit))
self.bus.write_byte_data(self.ADDR, self.GPINTENB, self.gpintenB)
else:
self.gpintenA = self.gpintenA & (0xff - (1 << bit))
self.bus.write_byte_data(self.ADDR, self.GPINTENA, self.gpintenA)
def falseDEFVAL(self, bank, pin):
if self.chipOK:
bit = pin - 1
if bank == 'B':
self.defvalB = self.defvalB | (1 << bit)
self.bus.write_byte_data(self.ADDR, self.DEFVALB, self.defvalB)
else:
self.defvalA = self.defvalA | (1 << bit)
self.bus.write_byte_data(self.ADDR, self.DEFVALA, self.defvalA)
def trueDEFVAL(self, bank, pin):
if self.chipOK:
bit = pin - 1
if bank == 'B':
self.defvalB = self.defvalB & (0xff - (1 << bit))
self.bus.write_byte_data(self.ADDR, self.DEFVALB, self.defvalB)
else:
self.defvalA = self.defvalA & (0xff - (1 << bit))
self.bus.write_byte_data(self.ADDR, self.DEFVALA, self.defvalA)
def setINTCON(self, bank, pin):
if self.chipOK:
bit = pin - 1
if bank == 'B':
self.intconB = self.intconB | (1 << bit)
self.bus.write_byte_data(self.ADDR, self.INTCONB, self.intconB)
else:
self.intconA = self.intconA | (1 << bit)
self.bus.write_byte_data(self.ADDR, self.INTCONA, self.intconA)
def resetINTCON(self, bank, pin):
if self.chipOK:
bit = pin - 1
if bank == 'B':
self.intconB = self.intconB & (0xff - (1 << bit))
self.bus.write_byte_data(self.ADDR, self.INTCONB, self.intconB)
else:
self.intconA = self.intconA & (0xff - (1 << bit))
self.bus.write_byte_data(self.ADDR, self.INTCONA, self.intconA)
def setGPPU(self, bank, pin):
if self.chipOK:
bit = pin - 1
if bank == 'B':
self.gppuB = self.gppuB | (1 << bit)
self.bus.write_byte_data(self.ADDR, self.GPPUB, self.gppuB)
else:
self.gppuA = self.gppuA | (1 << bit)
self.bus.write_byte_data(self.ADDR, self.GPPUA, self.gppuA)
def resetGPPU(self, bank, pin):
if self.chipOK:
bit = pin - 1
if bank == 'B':
self.gppuB = self.gppuB & (0xff - (1 << bit))
self.bus.write_byte_data(self.ADDR, self.GPPUB, self.gppuB)
else:
self.gppuA = self.gppuA & (0xff - (1 << bit))
self.bus.write_byte_data(self.ADDR, self.GPPUA, self.gppuA)
def readINTF(self):
if self.chipOK:
busVal1 = self.bus.read_byte_data(self.ADDR, self.INTFA)
busVal2 = self.bus.read_byte_data(self.ADDR, self.INTFB)
return busVal1, busVal2
else:
return None, None
def readINTCAP(self):
if self.chipOK:
busVal1 = self.bus.read_byte_data(self.ADDR, self.INTCAPA)
busVal2 = self.bus.read_byte_data(self.ADDR, self.INTCAPB)
return busVal1, busVal2
else:
return None, None
Any language using left-hand whitespace for syntax is ridiculous
Any DMs sent on Twitter will be answered next month.
Fake doctors - are all on my foes list.
Any requirement to use a crystal ball or mind reading will result in me ignoring your question.
Any DMs sent on Twitter will be answered next month.
Fake doctors - are all on my foes list.
Any requirement to use a crystal ball or mind reading will result in me ignoring your question.