microbit-foundation / micropython-microbit-v2

Temporary home for MicroPython for micro:bit v2 as we stablise it before pushing upstream
MIT License
42 stars 23 forks source link

Can pins 5 and 11 be used as general purpose IO? #100

Closed martinwork closed 2 years ago

martinwork commented 2 years ago

From https://support.microbit.org/helpdesk/tickets/54607 (private)

Is it possible to disable buttons A and B, so that pins 5 and 11 can be used as general purpose IO?

This seems to be possible in C++ with CODAL, as discussed in https://github.com/lancaster-university/codal-microbit-v2/issues/84#issuecomment-798773312, but I couldn't find an API in python.

It's understood that the 10K pull ups will still be active.

microbit-carlos commented 2 years ago

You can use then already a digital pins. In the REPL:

>>> pin5.read_digital()
1
>>> pin5.read_digital() # while pressing down button A
0
martinwork commented 2 years ago

Yes, I think it's the Output side that needs the button object to be disabled.

microbit-carlos commented 2 years ago

Oh right, thanks for the clarification.

Right now MicroPython doesn't support a way to reuse pin5/11 as outputs, but we could write to the GPIO registers directly to control the pin. This is an example for controlling Button A as an output pin in micro:bit V2:

from microbit import *
from micropython import const
from machine import mem32

REG_GPIO_P0 = const(0x50000000)                 # Base address for the GPIO 0 peripheal
REG_GPIO_OUTSET = const(REG_GPIO_P0 + 0x508)    # When a 32bit value is written to this address, each bit set to 1 sets the output pin high
REG_GPIO_OUTCLR = const(REG_GPIO_P0 + 0x50C)    # When a 32bit value is written to this address, each bit set to 1 sets the output pin low
REG_GPIO_DIRSET = const(REG_GPIO_P0 + 0x518)    # When a 32bit value is written to this address, each bit set to 1 sets the pin to output 
REG_GPIO_DIRCLR = const(REG_GPIO_P0 + 0x51C)    # When a 32bit value is written to this address, each bit set to 1 sets the pin to input

BUTON_A_PIN = const(14)    # Button A is pin 5 in the edge connector -> P0_14 in the nRF52833
BUTON_B_PIN = const(23)    # Button B is pin 5 in the edge connector -> P0_23 in the nRF52833

# First we set Button A to be an output
mem32[REG_GPIO_DIRSET] = 1 << BUTON_A_PIN

def set_button_a_low():
    mem32[REG_GPIO_OUTCLR] = 1 << BUTON_A_PIN

def set_button_a_high():
    mem32[REG_GPIO_OUTSET] = 1 << BUTON_A_PIN

def restore_button_a_as_input():
    # If we want to use button_a.is_pressed() again we need to set it as input
    mem32[REG_GPIO_DIRCLR] = 1 << BUTON_A_PIN

while True:
    display.show(Image.ARROW_S)
    set_button_a_low()
    sleep(5000)
    display.show(Image.ARROW_N)
    set_button_a_high()
    sleep(5000)
microbit-carlos commented 2 years ago

If it's okay as a workaround was provided I'll close this as a resolved 👍

martinwork commented 2 years ago

Yes, thanks @microbit-carlos