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

finding the mcp pin which caused the interrupt #15

Open
Guru-Solidz opened this issue Apr 13, 2023 · 2 comments
Open

finding the mcp pin which caused the interrupt #15

Guru-Solidz opened this issue Apr 13, 2023 · 2 comments

Comments

@Guru-Solidz
Copy link

Guru-Solidz commented Apr 13, 2023

Hi,
I am trying to use the wonderful library that you have provided.

I have connected 1 MCP23017 with esp32, and configured all 16 pins as input.
my requirement is as follows:

I need to need to know which pin of the mcp23017 triggered the input.

My code is as below:
###################################

from machine import Pin, SoftI2C
import mcp23017, time, gc
i2c = SoftI2C(scl=Pin(5), sda=Pin(4), freq=400000, timeout=255)
mcp = mcp23017.MCP23017(i2c, 0x20)

# method interface
mcp.pin(0, mode=1, pullup=0, polarity=0, interrupt_enable=1)
mcp.pin(1, mode=1, pullup=0, polarity=0, interrupt_enable=1)
mcp.pin(2, mode=1, pullup=0, polarity=0, interrupt_enable=1)
mcp.pin(3, mode=1, pullup=0, polarity=0, interrupt_enable=1)
mcp.pin(4, mode=1, pullup=0, polarity=0, interrupt_enable=1)
mcp.pin(5, mode=1, pullup=0, polarity=0, interrupt_enable=1)
mcp.pin(6, mode=1, pullup=0, polarity=0, interrupt_enable=1)
mcp.pin(7, mode=1, pullup=0, polarity=0, interrupt_enable=1)
mcp.pin(8, mode=1, pullup=0, polarity=0, interrupt_enable=1)
mcp.pin(9, mode=1, pullup=0, polarity=0, interrupt_enable=1)
mcp.pin(10, mode=1, pullup=0, polarity=0, interrupt_enable=1)
mcp.pin(11, mode=1, pullup=0, polarity=0, interrupt_enable=1)
mcp.pin(12, mode=1, pullup=0, polarity=0, interrupt_enable=1)
mcp.pin(13, mode=1, pullup=0, polarity=0, interrupt_enable=1)
mcp.pin(14, mode=1, pullup=0, polarity=0, interrupt_enable=1)
mcp.pin(15, mode=1, pullup=0, polarity=0, interrupt_enable=1)

mcp.config(interrupt_polarity=0, interrupt_mirror=1)

# mcp.interrupt_triggered_gpio(port=0)
# mcp.interrupt_captured_gpio(port=0)

# mcp.interrupt_triggered_gpio(port=1)
# mcp.interrupt_captured_gpio(port=1)

p5 = Pin(5, Pin.IN, Pin.PULL_DOWN)
p6 = Pin(6, Pin.IN, Pin.PULL_DOWN)

def int1(pin):

    if Pin(5).value() == 1:
        print ('Int A Triggered')
    elif Pin(5).value() == 0:
        print ('Int A Released')
    gc.collect()
    # print(mcp.porta.interrupt_flag)
    # print(mcp.porta.interrupt_captured)


def int2(pin):

    if Pin(6).value() == 1:
        print ('Int B Triggered')
    elif Pin(6).value() == 0:
        print ('Int B Released')
    gc.collect()

p5.irq(trigger=Pin.IRQ_RISING | Pin.IRQ_FALLING, handler=int1)
p6.irq(trigger=Pin.IRQ_RISING | Pin.IRQ_FALLING, handler=int2)

#################################################

If I uncomment the "print(mcp.porta.interrupt_flag)" i get error as follows:
Traceback (most recent call last):
File "mcptest.py", line 44, in int1
File "mcp23017.py", line 269, in interrupt_triggered_gpio
File "mcp23017.py", line 135, in interrupt_flag
File "mcp23017.py", line 73, in _read
OSError: [Errno 19] ENODEV

Could you kindly help me out in letting me know how to get the pin which generated the interrupt ?

Thanks

@mcauser
Copy link
Owner

mcauser commented Apr 13, 2023

Hi,

OSError: [Errno 19] ENODEV means the device was not found on the I2C bus.
Perform an i2c.scan() and make sure 0x20 or 32 is present.

The two properties you're after are interrupt_flag and interrupt_captured.
When interrupts are enabled on a MCP pin and its set to input, each time it changes state it sets interrupt_flag to the pin that triggered the interrupt (only 1) and the current state of all GPIO pins in interrupt_captured.

Not sure what is connected to p5/p6. Assuming they are connected to INTA and INTB.
You've set interrupt_mirror=1, so it will trigger an interrupt when either port detects a change (internally linked).
This means you only need the one ESP32 pin reading INTA.
If you want them to fire independently, set interrupt_mirror=0 and use two ESP32 pins and two interrupts.

# config mcp using method interface
for i in range(16):
    mcp.pin(i, mode=1, pullup=0, polarity=0, interrupt_enable=1)
mcp.config(interrupt_polarity=0, interrupt_mirror=1)

# or the same using the property interface
mcp.mode = 0xffff
mcp.pullup = 0x0000
mcp.input_polarity = 0x0000
mcp.interrupt_enable = 0xffff
mcp.io_config = 0x40

def int1(pin):
    if pin.value() == 1:
        print('Int Triggered')
    elif pin.value() == 0:
        print('Int Released')
    # this will give you which pin on PortA triggered the int (8-bit value):
    # print(mcp.porta.interrupt_flag)
    # this will give you PortB
    # print(mcp.portb.interrupt_flag)
    # since you are linking INTA and INTB, use the 16-bit value (both ports a and b):
    print(mcp.interrupt_flag)
    # each time you read this property, it is cleared. It is also cleared if you read the GPIO values.

p5 = Pin(5, Pin.IN, Pin.PULL_DOWN)
p5.irq(trigger=Pin.IRQ_RISING | Pin.IRQ_FALLING, handler=int1)

You probably don't need garbage collection inside the interrupt handler.
The interrupt handler has a pin argument, so you don't need to call Pin(5) to get a reference inside.

The mcp.interrupt_triggered_gpio(1) method is the same as calling mcp.portb.interrupt_flag.

The mcp.interrupt_captured_gpio(0) method is the same as calling mcp.porta.interrupt_captured.

If you want to use Pin.PULL_UP on p5, set interrupt_polarity=1 on the mcp.

The mcp clears interrupts when the flag or gpio are read. You probably don't need the pin.irq() to react on both rising and falling edges. Rising is enough as the int is cleared as soon as it is read.

Use mcp.interrupt_compare_default to make the mcp fire an int when the GPIO a) changes state compared to its previous state, or b) compared to the value in mcp.default_value. If you don't have a specific use case for this, use the default mcp.interrupt_compare_default = 0x0000

@Guru-Solidz
Copy link
Author

Guru-Solidz commented Apr 13, 2023 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants