The Keys
scanner is the simplest. Each key or button is connected to its own pin on your microcontroller board. When you create a Keys
scanner, you give it a sequence of pins, and say whether the pins become True
or False
(high or low logic value) when pressed. You also say whether internal pull-up or pull-down resistors need to be enabled on the pins to force a stable voltage level when the keys or buttons are not pressed.
One terminal of a button is connected to pin D5 on this Feather board, and the other terminal is grounded. D5 will need to be pulled up, because there is no external pull-up resistor. When the button is not pressed, D5 will be high (True
), and when it is pressed, D5 will be low (False
).
# SPDX-FileCopyrightText: 2022 Dan Halbert for Adafruit Industries # # SPDX-License-Identifier: MIT import board import keypad keys = keypad.Keys((board.D5,), value_when_pressed=False, pull=True) while True: event = keys.events.get() # event will be None if nothing has happened. if event: print(event)
The program creates a Keys
object, and passes it a tuple of one pin (D5). That pin will be key_number
0.
We set value_when_pressed
to False
, because the pin goes low when the button is pressed. We set pull
to True
because we haven't provided an external resistor. When pull
is True
, it will enable a pull-up or a pull-down appropriately:
- If
value_when_pressed
isTrue
, enable an internal pull-down resistor, to hold the pin low when not pressed. - If
value_when_pressed
isFalse
, enable an internal pull-up resistor, to hold the pin high when not pressed.
When you press the button, you'll get an Event
saying that key_number
0 has been pressed (see below). When you release, the button you'll get a released event. The output will look like this:
<Event: key_number 0 pressed> <Event: key_number 0 released> <Event: key_number 0 pressed> <Event: key_number 0 released>
Events and EventQueues
We glossed over how events are fetched in the example above. When you press or release a key, the scanner notices that a key has changed state. It records an Event
in the EventQueue
attached to the scanner. You get the EventQueue
by accessing the events
property of the scanner. In the example above the EventQueue
is available from keys.events
.
To fetch the next Event
from the EventQueue
, you use events.get()
. If nothing has happened (no press or release of any key) since you last asked, events.get()
returns None
.
Every Event
has four properties:
-
key_number
: the number of the key that changed. Keys are numbered starting at 0. -
pressed
:True
if the event is a transition from released to pressed. -
released
:True
if the event is a transition from pressed to released.released
is always the opposite ofpressed
; it's provided for convenience and clarity, in case you want to test for key-release events explicitly. -
timestamp
: The time in milliseconds when the event occurred. The timestamp is the value ofsupervisor.ticks_ms
at the time of the event. You can use the timestamp to determine, for instance, how long a key was pressed down, or the interval between presses,
You only get a pressed
or released
event once per transition. If you keep holding down a key, you won't get multiple pressed
events.
The Adafruit MacroPad has 12 keys, with one key per pin. This program illuminates a key when it's pressed, and turns off the illumination when it's released.
Note that the key pin names are KEY1
to KEY12
, but the key_number
values are 0
to 11
.
# SPDX-FileCopyrightText: 2022 Dan Halbert for Adafruit Industries # # SPDX-License-Identifier: MIT import board import keypad import neopixel import usb_hid from adafruit_hid.keyboard import Keyboard from adafruit_hid.keycode import Keycode KEY_PINS = ( board.KEY1, board.KEY2, board.KEY3, board.KEY4, board.KEY5, board.KEY6, board.KEY7, board.KEY8, board.KEY9, board.KEY10, board.KEY11, board.KEY12, ) KEYCODES = ( Keycode.SEVEN, Keycode.EIGHT, Keycode.NINE, Keycode.FOUR, Keycode.FIVE, Keycode.SIX, Keycode.ONE, Keycode.TWO, Keycode.THREE, Keycode.BACKSPACE, Keycode.ZERO, Keycode.ENTER, ) ON_COLOR = (0, 0, 255) OFF_COLOR = (0, 20, 0) keys = keypad.Keys(KEY_PINS, value_when_pressed=False, pull=True) neopixels = neopixel.NeoPixel(board.NEOPIXEL, 12, brightness=0.4) neopixels.fill(OFF_COLOR) kbd = Keyboard(usb_hid.devices) while True: event = keys.events.get() if event: key_number = event.key_number # A key transition occurred. if event.pressed: kbd.press(KEYCODES[key_number]) neopixels[key_number] = ON_COLOR if event.released: kbd.release(KEYCODES[key_number]) neopixels[key_number] = OFF_COLOR
Here's some sample output from the program. In this case I pressed down key number 0, held it down, and then pressed key 1. Then I released key 0 and then released key 1. Then I pressed key 2.
<Event: key_number 0 pressed> <Event: key_number 1 pressed> <Event: key_number 0 released> <Event: key_number 1 released> <Event: key_number 2 pressed> <Event: key_number 2 released>
MacroPad HID Example
You can use keypad with CircuitPython's HID capability to send keypresses to a host computer. The example below is a number pad implemented on a MacroPad with backspace and enter keys.
# SPDX-FileCopyrightText: 2022 Dan Halbert for Adafruit Industries # # SPDX-License-Identifier: MIT import board import keypad import neopixel import usb_hid from adafruit_hid.keyboard import Keyboard from adafruit_hid.keycode import Keycode KEY_PINS = ( board.KEY1, board.KEY2, board.KEY3, board.KEY4, board.KEY5, board.KEY6, board.KEY7, board.KEY8, board.KEY9, board.KEY10, board.KEY11, board.KEY12, ) KEYCODES = ( Keycode.SEVEN, Keycode.EIGHT, Keycode.NINE, Keycode.FOUR, Keycode.FIVE, Keycode.SIX, Keycode.ONE, Keycode.TWO, Keycode.THREE, Keycode.BACKSPACE, Keycode.ZERO, Keycode.ENTER, ) ON_COLOR = (0, 0, 255) OFF_COLOR = (0, 20, 0) keys = keypad.Keys(KEY_PINS, value_when_pressed=False, pull=True) neopixels = neopixel.NeoPixel(board.NEOPIXEL, 12, brightness=0.4) neopixels.fill(OFF_COLOR) kbd = Keyboard(usb_hid.devices) while True: event = keys.events.get() if event: key_number = event.key_number # A key transition occurred. if event.pressed: kbd.press(KEYCODES[key_number]) neopixels[key_number] = ON_COLOR if event.released: kbd.release(KEYCODES[key_number]) neopixels[key_number] = OFF_COLOR