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

Add MCP23009 I/O Expander Button Input Reading via I2C #73

Merged
merged 3 commits into from
Jun 3, 2024

Conversation

McJackson164
Copy link
Contributor

@McJackson164 McJackson164 commented Jun 1, 2024

This pull request adds functionality to interface with the MCP23009 I/O Expander to read button inputs via the I2C protocol. The implementation includes setting up the I2C communication, configuring the MCP23009 registers, reading the input state of the buttons and debounce button inputs.

Changes Implemented:

I2C:

  • Added MCP23009 class.
    • Handles short and long press.
    • Handles debouncing.
    • The logic can easily be used to implement other I/O Expanders or raw button handling.
  • Added MCP23009 auto-detect.

Button Config:

  • Added a new default button configuration for MCP23009.

Example circuit as used by me:

circuit_mcp23009

@hishizuka
Copy link
Owner

Great!

This is an alternative to a BUTTON SHIM. I am just designing a custom PCB and will try to incorporate it in the near future.

BTW, is it compatible with the following libraries?
https://github.com/adafruit/Adafruit_CircuitPython_MCP230xx ?

@McJackson164
Copy link
Contributor Author

Yes, it is compatible. I tested my setup using the following code:

import board
import busio
from digitalio import Direction, Pull
from adafruit_mcp230xx.mcp23008 import MCP23008

i2c = busio.I2C(board.SCL, board.SDA)

# Override address because the MCP23008 address differs from the MCP23009 address
# The register addresses are the same
mcp = MCP23008(i2c, address=0x27)

channels = 8

pins = []
for pin in range(channels):
    pins.append(mcp.get_pin(pin))

for pin in pins:
    pin.direction = Direction.INPUT
    pin.pull = Pull.UP

while True:
    for num, button in enumerate(pins):
        if not button.value:
            print("Button #", num, "pressed!")

@McJackson164
Copy link
Contributor Author

I moved the logic into a separate base file to easily allow to implement other I/O Expanders from the MCP series.
A new implementation should (hopefully) be as simple as the following implementation of the MCP23009:

from .base.button_io_expander import ButtonIOExpander
from adafruit_mcp230xx.mcp23008 import MCP23008 as MCP
import board
import busio

# https://www.microchip.com/en-us/product/mcp23009
# https://ww1.microchip.com/downloads/en/DeviceDoc/20002121C.pdf


# NOTE: no need to set TEST and RESET address and value, due to adafruit_mcp230xx library handling it.
class MCP23009(ButtonIOExpander):

    # address
    SENSOR_ADDRESS = 0x27

    # The amount of available channels (8 for MCP23009)
    CHANNELS = 8

    def __init__(self, config):
        i2c = busio.I2C(board.SCL, board.SDA)
        self.mcp = MCP(i2c, address=self.SENSOR_ADDRESS)

        super().__init__(config, self.mcp)

Unfortunately the classes of the adafruit_mcp230xx library do not contain the amount of channels as a variable, so you have to define them yourself.

@hishizuka hishizuka merged commit 5f4b746 into hishizuka:master Jun 3, 2024
1 check failed
@McJackson164 McJackson164 deleted the feat/mcp23009 branch June 3, 2024 22:29
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

Successfully merging this pull request may close these issues.

2 participants