Skip to content
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
29 changes: 16 additions & 13 deletions lib/mcp23009e/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -194,21 +194,24 @@ Toggles the reset pin to perform a hardware reset.

## Examples

The library includes several examples:

* `buttons.py` - Simple button reading with polling
* `i2c_scan.py` - Scan I2C buses for connected devices
* `test_basic.py` - Basic driver functionality tests
* `test_interrupts.py` - Interrupt system demonstration
* `test_led_simple.py` - Basic active-low LED control example
* `test_output_active_low.py` - Active-low output tests with inverted logic
* `test_output.py` - GPIO output tests using low-level and Pin APIs
* `test_pin.py` - MCP23009Pin class usage examples
* `test_pin_irq.py` - Pin-compatible interrupt examples

The library includes several practical examples:

| Example | Description |
|-----------------------|------------|
| `buttons.py` | Simple D-PAD button reading using polling (no interrupts) |
| `i2c_scan.py` | Scan the I2C bus to detect connected devices |
| `reaction_timer.py` | Reaction time game using D-PAD buttons and interrupts (best of 5 rounds) |
| `simon.py` | Simon Says memory game using the D-PAD |
| `combination_lock.py` | Digital lock using a secret D-PAD sequence |
| `dpad_counter.py` | Simple state machine: increment/decrement/reset/print using D-PAD |
| `morse_code.py` | Morse code input using button press duration (dot/dash detection) |
| `binary_counter.py` | 4-bit binary counter displayed on GPIO outputs (GPIO1–GPIO4 / pins 0–3) |
| `dpad_piano.py` | Play musical notes with the D-PAD and buzzer (multi-press = higher octave) |
| `menu_navigation.py` | Minimal centered UI for navigating a menu on the SSD1327 OLED display |
| `sleep_on_button.py` | Low-power example: wake the board from sleep using MCP23009E interrupts |
Comment thread
Charly-sketch marked this conversation as resolved.

### How to run

```python
mpremote mount lib/mcp23009e run lib/mcp23009e/examples/test_basic.py
mpremote mount lib/mcp23009e run lib/mcp23009e/examples/buttons.py
```
87 changes: 87 additions & 0 deletions lib/mcp23009e/examples/binary_counter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
"""
Binary counter using D-PAD inputs and MCP23009E GPIO outputs.

UP -> increment
DOWN -> decrement
LEFT -> reset
RIGHT -> print current value

The value is displayed on GPIO1..GPIO4 (expander pins 0..3)
as a 4-bit binary number.
"""

from time import sleep_ms

from machine import I2C, Pin
from mcp23009e import MCP23009E
from mcp23009e.const import *

bus = I2C(1)
reset = Pin("RST_EXPANDER", Pin.OUT)

mcp = MCP23009E(bus, address=MCP23009_I2C_ADDR, reset_pin=reset)

BUTTONS = {
MCP23009_BTN_UP: "UP",
MCP23009_BTN_DOWN: "DOWN",
MCP23009_BTN_LEFT: "LEFT",
MCP23009_BTN_RIGHT: "RIGHT",
}

OUTPUT_PINS = [MCP23009_GPIO1, MCP23009_GPIO2, MCP23009_GPIO3, MCP23009_GPIO4]


def wait_all_released():
while True:
if all(mcp.get_level(pin_number) == MCP23009_LOGIC_HIGH for pin_number in BUTTONS):
return
sleep_ms(20)


def wait_for_button():
wait_all_released()
while True:
for pin_number, name in BUTTONS.items():
if mcp.get_level(pin_number) == MCP23009_LOGIC_LOW:
while mcp.get_level(pin_number) == MCP23009_LOGIC_LOW:
sleep_ms(20)
return name
sleep_ms(20)


def update_outputs(value):
for bit_index, pin_number in enumerate(OUTPUT_PINS):
bit_value = (value >> bit_index) & 0x01
mcp.set_level(pin_number, bit_value)


for pin_number in BUTTONS:
mcp.setup(pin_number, MCP23009_DIR_INPUT, pullup=MCP23009_PULLUP)

for pin_number in OUTPUT_PINS:
mcp.setup(pin_number, MCP23009_DIR_OUTPUT)
mcp.set_level(pin_number, MCP23009_LOGIC_LOW)

counter = 0
update_outputs(counter)

print("=================================")
print("Binary Counter")
print("=================================\n")
print("Displaying the 4-bit value on GP0..GP3")
print("UP=+1 DOWN=-1 LEFT=reset RIGHT=print\n")

while True:
button = wait_for_button()

if button == "UP":
counter = (counter + 1) & 0x0F
elif button == "DOWN":
counter = (counter - 1) & 0x0F
elif button == "LEFT":
counter = 0
elif button == "RIGHT":
pass

update_outputs(counter)
print("Value:", counter, " Binary:", "{:04b}".format(counter))
73 changes: 73 additions & 0 deletions lib/mcp23009e/examples/combination_lock.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
"""
Digital combination lock using the MCP23009E D-PAD.

Enter the secret button sequence to unlock.
A wrong input resets the attempt.
"""

from time import sleep_ms

from machine import I2C, Pin
from mcp23009e import MCP23009E
from mcp23009e.const import *

bus = I2C(1)
reset = Pin("RST_EXPANDER", Pin.OUT)

mcp = MCP23009E(bus, address=MCP23009_I2C_ADDR, reset_pin=reset)

BUTTONS = {
MCP23009_BTN_UP: "UP",
MCP23009_BTN_DOWN: "DOWN",
MCP23009_BTN_LEFT: "LEFT",
MCP23009_BTN_RIGHT: "RIGHT",
}

SECRET = ["UP", "UP", "DOWN", "LEFT", "RIGHT"]


def wait_all_released():
while True:
if all(mcp.get_level(pin_number) == MCP23009_LOGIC_HIGH for pin_number in BUTTONS):
return
sleep_ms(20)


def wait_for_button():
wait_all_released()
while True:
for pin_number, name in BUTTONS.items():
if mcp.get_level(pin_number) == MCP23009_LOGIC_LOW:
while mcp.get_level(pin_number) == MCP23009_LOGIC_LOW:
sleep_ms(20)
return name
sleep_ms(20)


for pin_number in BUTTONS:
mcp.setup(pin_number, MCP23009_DIR_INPUT, pullup=MCP23009_PULLUP)

print("=================================")
print("Combination Lock")
print("=================================\n")
print("Enter the secret D-PAD sequence.\n")

entered = []

while True:
button = wait_for_button()
entered.append(button)

print("Input:", "-".join(entered))

expected_prefix = SECRET[: len(entered)]
if entered != expected_prefix:
print("WRONG")
entered = []
print()
continue

if len(entered) == len(SECRET):
print("UNLOCKED")
entered = []
print()
70 changes: 70 additions & 0 deletions lib/mcp23009e/examples/dpad_counter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
"""
Simple D-PAD counter.

UP -> increment
DOWN -> decrement
LEFT -> reset
RIGHT -> print current value
"""

from time import sleep_ms

from machine import I2C, Pin
from mcp23009e import MCP23009E
from mcp23009e.const import *

bus = I2C(1)
reset = Pin("RST_EXPANDER", Pin.OUT)

mcp = MCP23009E(bus, address=MCP23009_I2C_ADDR, reset_pin=reset)

BUTTONS = {
MCP23009_BTN_UP: "UP",
MCP23009_BTN_DOWN: "DOWN",
MCP23009_BTN_LEFT: "LEFT",
MCP23009_BTN_RIGHT: "RIGHT",
}


def wait_all_released():
while True:
if all(mcp.get_level(pin_number) == MCP23009_LOGIC_HIGH for pin_number in BUTTONS):
return
sleep_ms(20)


def wait_for_button():
wait_all_released()
while True:
for pin_number, name in BUTTONS.items():
if mcp.get_level(pin_number) == MCP23009_LOGIC_LOW:
while mcp.get_level(pin_number) == MCP23009_LOGIC_LOW:
sleep_ms(20)
return name
sleep_ms(20)


for pin_number in BUTTONS:
mcp.setup(pin_number, MCP23009_DIR_INPUT, pullup=MCP23009_PULLUP)

value = 0

print("=================================")
print("D-PAD Counter")
print("=================================\n")
print("UP=+1 DOWN=-1 LEFT=reset RIGHT=print\n")

while True:
button = wait_for_button()

if button == "UP":
value += 1
print("Increment ->", value)
elif button == "DOWN":
value -= 1
print("Decrement ->", value)
elif button == "LEFT":
value = 0
print("Reset ->", value)
elif button == "RIGHT":
print("Current value ->", value)
Loading
Loading