Skip to content

Improve interrupt #14

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

Merged
merged 6 commits into from
Jun 5, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 44 additions & 1 deletion adafruit_mcp230xx/mcp23017.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@
_MCP23017_GPPUB = const(0x0D)
_MCP23017_GPIOA = const(0x12)
_MCP23017_GPIOB = const(0x13)
_MCP23017_INTFA = const(0x0E)
_MCP23017_INTFB = const(0x0F)
_MCP23017_INTCAPA = const(0x10)
_MCP23017_INTCAPB = const(0x11)


class MCP23017(MCP230XX):
Expand Down Expand Up @@ -218,7 +222,6 @@ def default_value(self):
def default_value(self, val):
self._write_u16le(_MCP23017_DEFVALA, val)


@property
def io_control(self):
"""The raw IOCON configuration register. Bit 1 controls interrupt
Expand All @@ -234,3 +237,43 @@ def io_control(self):
@io_control.setter
def io_control(self, val):
self._write_u8(_MCP23017_IOCON, val)

@property
def int_flag(self):
"""Returns a list with the pin numbers that caused an interrupt
port A ----> pins 0-7
port B ----> pins 8-15
"""
intf = self._read_u16le(_MCP23017_INTFA)
flags = [pin for pin in range(16) if intf & (1 << pin)]
return flags

@property
def int_flaga(self):
"""Returns a list of pin numbers that caused an interrupt in port A
pins: 0-7
"""
intfa = self._read_u8(_MCP23017_INTFA)
flags = [pin for pin in range(8) if intfa & (1 << pin)]
return flags

@property
def int_flagb(self):
"""Returns a list of pin numbers that caused an interrupt in port B
pins: 8-15
"""
intfb = self._read_u8(_MCP23017_INTFB)
flags = [pin+8 for pin in range(8) if intfb & (1 << pin)]
return flags

def clear_ints(self):
"""Clears interrupts by reading INTCAP."""
self._read_u16le(_MCP23017_INTCAPA)

def clear_inta(self):
"""Clears port A interrupts."""
self._read_u8(_MCP23017_INTCAPA)

def clear_intb(self):
"""Clears port B interrupts."""
self._read_u8(_MCP23017_INTCAPB)
69 changes: 69 additions & 0 deletions examples/mcp230xx_event_detect_interrupt.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
from time import sleep

import board
import busio
from digitalio import Direction, Pull
from RPi import GPIO
from adafruit_mcp230xx.mcp23017 import MCP23017

# Initialize the I2C bus:
i2c = busio.I2C(board.SCL, board.SDA)

# Initialize the MCP23017 chip on the bonnet
mcp = MCP23017(i2c)

# Optionally change the address of the device if you set any of the A0, A1, A2
# pins. Specify the new address with a keyword parameter:
#mcp = MCP23017(i2c, address=0x21) # MCP23017 w/ A0 set

# Make a list of all the pins (a.k.a 0-16)
pins = []
for pin in range(0, 16):
pins.append(mcp.get_pin(pin))

# Set all the pins to input
for pin in pins:
pin.direction = Direction.INPUT
pin.pull = Pull.UP

# Set up to check all the port B pins (pins 8-15) w/interrupts!
mcp.interrupt_enable = 0xFFFF # Enable Interrupts in all pins
# If intcon is set to 0's we will get interrupts on
# both button presses and button releases
mcp.interrupt_configuration = 0x0000 # interrupt on any change
mcp.io_control = 0x44 # Interrupt as open drain and mirrored
mcp.clear_ints() # Interrupts need to be cleared initially

# Or, we can ask to be notified CONTINUOUSLY if a pin goes LOW (button press)
# we won't get an IRQ pulse when the pin is HIGH!
#mcp.interrupt_configuration = 0xFFFF # notify pin value
#mcp.default_value = 0xFFFF # default value is 'high' so notify whenever 'low'

def print_interrupt(port):
'''Callback function to be called when an Interrupt occurs.'''
for pin_flag in mcp.int_flag:
print("Interrupt connected to Pin: {}".format(port))
print("Pin number: {} changed to: {}".format(pin_flag, pins[pin_flag].value))
mcp.clear_ints()

# connect either interrupt pin to the Raspberry pi's pin 17.
# They were previously configured as mirrored.
GPIO.setmode(GPIO.BCM)
interrupt = 17
GPIO.setup(interrupt, GPIO.IN, GPIO.PUD_UP) # Set up Pi's pin as input, pull up

# The add_event_detect fuction will call our print_interrupt callback function
# every time an interrupt gets triggered.
GPIO.add_event_detect(interrupt, GPIO.FALLING, callback=print_interrupt, bouncetime=10)

# The following lines are so the program runs for at least 60 seconds,
# during that time it will detect any pin interrupt and print out the pin number
# that changed state and its current state.
# The program can be terminated using Ctrl+C. It doesn't matter how it
# terminates it will always run GPIO.cleanup().
try:
print("When button is pressed you'll see a message")
sleep(60) # You could run your main while loop here.
print("Time's up. Finished!")
finally:
GPIO.cleanup()