Scanning Interval and Debouncing

By default, all the scanners in the keypad module scan their inputs at 20 millisecond intervals. This is enough time to debounce most mechanical keys, which can take quite a few milliseconds to settle down. If you have keys that need more (or less) debouncing, you can set the optional interval parameter when you create a scanner. The interval is given in floating-point seconds. For example:

km = keypad.KeyMatrix(
    row_pins=(board.A0, board.A1, board.A2, board.A3),
    column_pins=(board.D0, board.D1, board.D2),
    # Allow 50 msecs to debounce.
    interval=0.050,
)

Queue Size and Queue Overflow

The EventQueue for each scanner is of fixed size. The default size is 64 events. You can change this value by setting the optional max_events parameter:

k = keypad.Keys(
    (board.D8, board.D9),
    value_when_pressed=False,
    pull=True,
    # Increase event queue size to 128 events.
    max_events=128,
)

If your program doesn't keep up while reading events, the event queue can become full. New events will be discarded. If this happens, the EventQueue.overflowed property is set to True on the event queue. You can clear the event queue with the EventQueue.clear() method; that also sets the overflowed flag to False. Since you have lost events, you probably also want to forget the existing state of the keys and start over. you can do that by calling reset() on the scanner. scanner.reset() clears any key-pressed information, so it will immediately generate key-pressed events for any keys that were pressed at the time you reset. For example:

keys = keypad.Keys(
    (board.D8, board.D9),
    value_when_pressed=False,
    pull=True,
)

while True:
    # Check if we lost some events.
    if keys.events.overflowed:
        keys.events.clear()    # Empty the event queue.
        keys.reset()           # Forget any existing presses. Start over.
    # ...

You don't have to check for queue overflow. For most programs, it will never happen, or it's not important if it happens: the user will adjust.

Avoiding Storage Allocation

EventQueue.get() creates a new Event every time it returns an event. These Events probably become unused quite quickly, and add to the "garbage" that must be collected periodically. You can avoid generating new Event objects each time by using the EventQueue.get_into(event) method, which writes into an existing Event. It returns True if it wrote into the Event, and False otherwise (when EventQueue.get() would have returned None).

Here's an example of using get_into():

import board
import keypad

keys = keypad.Keys((board.D8,), value_when_pressed=False, pull=True)

# Create an event we will reuse over and over.
event = keypad.Event()

while True:
    if keys.events.get_into(event):
        print(event)

Comparing Events and Using Events as Dictionary Keys

Event implements __eq__() and __hash__(), so you can test if two Events are equivalent, and you can store them in a dictionary. For example, here's a program that translates button pushes on pins D8 and D9 into the strings "LEFT" and "RIGHT". And if you push the button on D10, the program stops.

import board

from keypad import Keys, Event

keys = Keys((board.D8, board.D9, board.D10), value_when_pressed=False, pull=True)

LEFT_EVENT = Event(0, True)   # Button 0 (D8) pressed
RIGHT_EVENT = Event(1, True)  # Button 1 (D9) pressed
STOP_EVENT = Event(2, True)   # Button 2 (D10) pressed

DIRECTION = {
    LEFT_EVENT : "LEFT",
    RIGHT_EVENT : "RIGHT",
}

while True:
    event = keys.events.get()
    if event:
        if event == STOP_EVENT:
            print("stop")
            break

        # Look up the event. If not found, direction is None.
        direction = DIRECTION.get(event)
        if direction:
            print(direction)

This guide was first published on Jun 29, 2021. It was last updated on Jun 29, 2021.

This page (Advanced Features) was last updated on Sep 25, 2021.

Text editor powered by tinymce.