From dee0bc7e8aee1d2d28b5cc9469ac2bd1f47a5cc3 Mon Sep 17 00:00:00 2001 From: "Jardi A. Martinez Jordan" <1088732+jardiamj@users.noreply.github.com> Date: Sun, 26 May 2019 22:54:00 -0700 Subject: [PATCH 1/6] Added fuctions to clear interrupts and read interrupt flags. --- adafruit_mcp230xx/mcp23017.py | 43 ++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/adafruit_mcp230xx/mcp23017.py b/adafruit_mcp230xx/mcp23017.py index 195afe6..8f489e2 100644 --- a/adafruit_mcp230xx/mcp23017.py +++ b/adafruit_mcp230xx/mcp23017.py @@ -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): @@ -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 @@ -234,3 +237,41 @@ def io_control(self): @io_control.setter def io_control(self, val): self._write_u8(_MCP23017_IOCON, val) + + @property + def flagged(self): + """Returns a list with the pin numbers that caused an interrupt + port A ----> pins 0-7 + port B ----> pins 8-15 + """ + intf = format(self._read_u16le(_MCP23017_INTFA), '016b') + flagged = [i for i, val in enumerate(reversed(intf)) if val == '1'] + return flagged + + @property + def flaggeda(self): + """Returns a list of pin numbers that coused an interrupt in port A + pins: 0-7 + """ + intfa = format(self._read_u8(_MCP23017_INTFA), '08b') + flaggeda = [i for i, val in enumerate(reversed(intfa)) if val == '1'] + return flaggeda + + @property + def flaggedb(self): + """Returns a list of pin numbers that coused an interrupt in port A + pins: 8-15 + """ + intfb = format(self._read_u8(_MCP23017_INTFB), '08b') + flaggeda = [i+8 for i, val in enumerate(reversed(intfb)) if val == '1'] + return flaggeda + + def clear_ints(self): + """Clears interrupts by reading INTCAP.""" + self._read_u16le(_MCP23017_INTCAPA) + + def clear_inta(self): + self._read_u8(_MCP23017_INTCAPA) + + def clear_intb(self): + self._read_u8(_MCP23017_INTCAPB) From df27af02fbf7c021abe129f4502085499e8ab343 Mon Sep 17 00:00:00 2001 From: "Jardi A. Martinez Jordan" <1088732+jardiamj@users.noreply.github.com> Date: Sun, 26 May 2019 22:58:13 -0700 Subject: [PATCH 2/6] Added doc comments. --- adafruit_mcp230xx/mcp23017.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/adafruit_mcp230xx/mcp23017.py b/adafruit_mcp230xx/mcp23017.py index 8f489e2..6fefe6e 100644 --- a/adafruit_mcp230xx/mcp23017.py +++ b/adafruit_mcp230xx/mcp23017.py @@ -259,7 +259,7 @@ def flaggeda(self): @property def flaggedb(self): - """Returns a list of pin numbers that coused an interrupt in port A + """Returns a list of pin numbers that coused an interrupt in port B pins: 8-15 """ intfb = format(self._read_u8(_MCP23017_INTFB), '08b') @@ -271,7 +271,9 @@ def clear_ints(self): 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) From ddd35880f78ad95eb863ff2f7654b53f7fed47c7 Mon Sep 17 00:00:00 2001 From: "Jardi A. Martinez Jordan" <1088732+jardiamj@users.noreply.github.com> Date: Mon, 27 May 2019 22:23:39 -0700 Subject: [PATCH 3/6] Turned interrupt flag properties into faster bitwise operations. --- adafruit_mcp230xx/mcp23017.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/adafruit_mcp230xx/mcp23017.py b/adafruit_mcp230xx/mcp23017.py index 6fefe6e..0c4a99a 100644 --- a/adafruit_mcp230xx/mcp23017.py +++ b/adafruit_mcp230xx/mcp23017.py @@ -239,32 +239,32 @@ def io_control(self, val): self._write_u8(_MCP23017_IOCON, val) @property - def flagged(self): + def int_flg(self): """Returns a list with the pin numbers that caused an interrupt port A ----> pins 0-7 port B ----> pins 8-15 """ - intf = format(self._read_u16le(_MCP23017_INTFA), '016b') - flagged = [i for i, val in enumerate(reversed(intf)) if val == '1'] - return flagged + intf = self._read_u16le(_MCP23017_INTFA) + flg = [i for i in range(16) if (intf & (1 << i))] + return flg @property - def flaggeda(self): + def int_flga(self): """Returns a list of pin numbers that coused an interrupt in port A pins: 0-7 """ - intfa = format(self._read_u8(_MCP23017_INTFA), '08b') - flaggeda = [i for i, val in enumerate(reversed(intfa)) if val == '1'] - return flaggeda + intfa = self._read_u8(_MCP23017_INTFA) + flga = [i for i in range(8) if (intfa & (1 << i))] + return flga @property - def flaggedb(self): + def int_flgb(self): """Returns a list of pin numbers that coused an interrupt in port B pins: 8-15 """ - intfb = format(self._read_u8(_MCP23017_INTFB), '08b') - flaggeda = [i+8 for i, val in enumerate(reversed(intfb)) if val == '1'] - return flaggeda + intfb = self._read_u8(_MCP23017_INTFB) + flgb = [i+8 for i in range(8) if (intfb & (1 << i))] + return flgb def clear_ints(self): """Clears interrupts by reading INTCAP.""" From b7edd4dce3ec58f45ae226b0e37fde2618dce7ae Mon Sep 17 00:00:00 2001 From: "Jardi A. Martinez Jordan" <1088732+jardiamj@users.noreply.github.com> Date: Mon, 27 May 2019 22:32:58 -0700 Subject: [PATCH 4/6] Removed unnecessary parenthesis. --- adafruit_mcp230xx/mcp23017.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/adafruit_mcp230xx/mcp23017.py b/adafruit_mcp230xx/mcp23017.py index 0c4a99a..10453a9 100644 --- a/adafruit_mcp230xx/mcp23017.py +++ b/adafruit_mcp230xx/mcp23017.py @@ -245,7 +245,7 @@ def int_flg(self): port B ----> pins 8-15 """ intf = self._read_u16le(_MCP23017_INTFA) - flg = [i for i in range(16) if (intf & (1 << i))] + flg = [i for i in range(16) if intf & (1 << i)] return flg @property @@ -254,7 +254,7 @@ def int_flga(self): pins: 0-7 """ intfa = self._read_u8(_MCP23017_INTFA) - flga = [i for i in range(8) if (intfa & (1 << i))] + flga = [i for i in range(8) if intfa & (1 << i)] return flga @property @@ -263,7 +263,7 @@ def int_flgb(self): pins: 8-15 """ intfb = self._read_u8(_MCP23017_INTFB) - flgb = [i+8 for i in range(8) if (intfb & (1 << i))] + flgb = [i+8 for i in range(8) if intfb & (1 << i)] return flgb def clear_ints(self): From 83facdfbb5c167db978206cdd1594939ad332822 Mon Sep 17 00:00:00 2001 From: "Jardi A. Martinez Jordan" <1088732+jardiamj@users.noreply.github.com> Date: Tue, 4 Jun 2019 21:41:32 -0700 Subject: [PATCH 5/6] Changed the names of functions and variables to easier to read names. Added Interrupt example using Rpi.GPIO.add_event_detect() and a callback. --- adafruit_mcp230xx/mcp23017.py | 22 +++---- examples/mcp230xx_event_detect_interrupt.py | 69 +++++++++++++++++++++ 2 files changed, 80 insertions(+), 11 deletions(-) create mode 100644 examples/mcp230xx_event_detect_interrupt.py diff --git a/adafruit_mcp230xx/mcp23017.py b/adafruit_mcp230xx/mcp23017.py index 10453a9..250774c 100644 --- a/adafruit_mcp230xx/mcp23017.py +++ b/adafruit_mcp230xx/mcp23017.py @@ -239,32 +239,32 @@ def io_control(self, val): self._write_u8(_MCP23017_IOCON, val) @property - def int_flg(self): + 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) - flg = [i for i in range(16) if intf & (1 << i)] - return flg + flags = [pin for pin in range(16) if intf & (1 << pin)] + return flags @property - def int_flga(self): - """Returns a list of pin numbers that coused an interrupt in port A + 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) - flga = [i for i in range(8) if intfa & (1 << i)] - return flga + flags = [pin for pin in range(8) if intfa & (1 << pin)] + return flags @property - def int_flgb(self): - """Returns a list of pin numbers that coused an interrupt in port B + 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) - flgb = [i+8 for i in range(8) if intfb & (1 << i)] - return flgb + flags = [pin+8 for pin in range(8) if intfb & (1 << pin)] + return flags def clear_ints(self): """Clears interrupts by reading INTCAP.""" diff --git a/examples/mcp230xx_event_detect_interrupt.py b/examples/mcp230xx_event_detect_interrupt.py new file mode 100644 index 0000000..81a55ec --- /dev/null +++ b/examples/mcp230xx_event_detect_interrupt.py @@ -0,0 +1,69 @@ +import board +import busio +from RPi import GPIO +from digitalio import DigitalInOut, Direction, Pull +from adafruit_mcp230xx.mcp23017 import MCP23017 +from time import sleep + +# 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.''' + flga = mcp.int_flaga + flgb = mcp.int_flagb + for pin in mcp.int_flag: + print("Pin number: {} changed to: {}".format(pin, pins[pin].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() From 5383e4a189628187a7e8b171692f2f89402ba07c Mon Sep 17 00:00:00 2001 From: "Jardi A. Martinez Jordan" <1088732+jardiamj@users.noreply.github.com> Date: Tue, 4 Jun 2019 22:14:24 -0700 Subject: [PATCH 6/6] Fixed pylint errors --- examples/mcp230xx_event_detect_interrupt.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/mcp230xx_event_detect_interrupt.py b/examples/mcp230xx_event_detect_interrupt.py index 81a55ec..f7f9ff7 100644 --- a/examples/mcp230xx_event_detect_interrupt.py +++ b/examples/mcp230xx_event_detect_interrupt.py @@ -1,9 +1,10 @@ +from time import sleep + import board import busio +from digitalio import Direction, Pull from RPi import GPIO -from digitalio import DigitalInOut, Direction, Pull from adafruit_mcp230xx.mcp23017 import MCP23017 -from time import sleep # Initialize the I2C bus: i2c = busio.I2C(board.SCL, board.SDA) @@ -20,7 +21,7 @@ for pin in range(0, 16): pins.append(mcp.get_pin(pin)) -# Set all the pins to input +# Set all the pins to input for pin in pins: pin.direction = Direction.INPUT pin.pull = Pull.UP @@ -40,10 +41,9 @@ def print_interrupt(port): '''Callback function to be called when an Interrupt occurs.''' - flga = mcp.int_flaga - flgb = mcp.int_flagb - for pin in mcp.int_flag: - print("Pin number: {} changed to: {}".format(pin, pins[pin].value )) + 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.