Interrupt setup using the micropython-MCP230xx library

Discussion about programs, libraries and tools that work with MicroPython. Mostly these are provided by a third party.
Target audience: All users and developers of MicroPython.
Post Reply
Posts: 1
Joined: Sun Jun 16, 2019 2:58 pm

Interrupt setup using the micropython-MCP230xx library

Post by dylan » Sun Jun 16, 2019 3:09 pm

Hi there.

I using a Node MCU V3 board carrying and ESP8266. My project requires a silly number of inputs (about 15 of them) and I have opted to expand the number using a MCP23017 on a waveshare breakout board: ... sion_Board

I am able to read the status of each pin by polling the IC repeatedly... e.g. print(io.input_pins(inPins))

What I am unable to do is configure the IC to change status of one/both of its interrupt pins (something which the datasheet for the MCP23017 says is configurable): ... asheet.pdf

The library I am using:

All other functions appear to be fine.

Please assist me (new in the world of micropython) by explaining how I would configure the IC to set interrupt pins LOW when a change occurs on one of the intput pins.

For simplicity I have set the first 8 pins to inputs and the second 8 to outputs:

Code: Select all

outPins = list(range(9,16))
nextVals = {}
for pinNum in outPins:
    io.setup(pinNum, mcp.OUT)
    nextVals[pinNum] = True

inPins = list(range(0,8))
for pinNum in inPins:
    io.setup(pinNum, mcp.IN)
    io.pullup(pinNum, True)

User avatar
Posts: 1837
Joined: Tue Aug 08, 2017 1:57 am
Location: Sydney, Australia

Re: Interrupt setup using the micropython-MCP230xx library

Post by jimmo » Sun Jun 16, 2019 11:47 pm


Like most I2C devices, the operation of this expander is controlled by writing values to registers. For example in `def write_gpio()`, it sends the current state of the `self.gpio` bytearray to the `GPIO` register, which sets the current value of the pins. These registers are just at some address (e.g. GPIO is 0x12 on your chip).

(Another note, because it's a 16-pin expander and 8-bit registers, there are two registers for each function A, and B). So GPIOA is at 0x12, GPIOB at 0x13. The driver you're using kind of hides that and just writes all 16 bits every time using writeList.

You'll need to extend this driver to add a way to control the interrupt registers.

From the datasheet, this is controlled by the following register GPINTEN register -- each bit enables that pin to generate an interrupt.

The way interrupts work is that when the pin changes state, it sets the corresponding bit in the INTF register, then sets the corresponding INT pin. Then next time you read the state of the GPIO register (or INTCAP), then it resets the INT pin and the INTF flag. (GPIO will give you the current state, INTCAP will give you the "captured" state at the time the interrupt occurred, you probably want that). So in your Python code, when you get an interrupt on INTA / INTB, then you'll need to go and find which pin changed.

Something like:

Code: Select all

def inta_falling_irq(p):
  # read INTF register to find out which pin(s) triggered the interrupt
  # read INTCAP to find out the captured value (and implicitly clear the INTF flag bit and put the INT pin back to high)
It looks like by default you get an interrupt whenever the pin changes, but if you specifically care about rising/falling, you can set INTCON and DEFVAL to only capture one type.

You specifically said you want INT to go low on change, which appears to be the default. (Configurable using the INTPOL bit in IOCON).

If you just want to use a single INT pin (to save one more pin on your ESP), then you can set the MIRROR bit in the IOCON register, which will make both INTA and INTB mirror eachother.

Hope that helps!

Post Reply