# Keypad and Matrix Scanning in CircuitPython

## Overview

![](https://cdn-learn.adafruit.com/assets/assets/000/103/236/medium800/circuitpython_4954-00.jpg?1624994564)

The built-in CircuitPython `keypad` module scans a set of one or more keys or buttons in the background, while your program is doing other things, and gives you debounced key-pressed and key-released events. The module provides three different kinds of _scanners_, which cover common ways of connecting keys to pins.

- `Keys`: Each key or button is connected to a separate pin.
- `KeyMatrix`: The keys are wired in a row-column matrix, with or without diodes. This is how most typing keyboards, music keyboards, and telephone-style keypads are wired.
- `ShiftRegisterKeys`: The keys are connected to an external parallel-in serial-out shift register. The keys are read by clocking data from the shift register into a single input pin.

Each time a key is pressed or released, a scanner will record an `Event` in an `EventQueue`. Each event gives the key number, and says whether the key has been pressed or released. Your program can read the events sequentially.

The background scanning does debouncing as well, so you don't have to worry about handling that yourself.&nbsp;

This Guide will explain how each of the scanners works, and provide some simple examples.

Warning: See the [Raspberry Pi RP2350 Erratum Workarounds](https://learn.adafruit.com/key-pad-matrix-scanning-in-circuitpython/raspberry-pi-rp2350-erratum-workarounds) page in this Guide for workarounds needed when using `keypad` on an RP2350.

# Keypad and Matrix Scanning in CircuitPython

## Keys and Events

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-Button Example

Here's a really simple example, with just one button:

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`).

![circuitpython_FeatherM0ExpressButton_bb.jpg](https://cdn-learn.adafruit.com/assets/assets/000/103/218/medium640/circuitpython_FeatherM0ExpressButton_bb.jpg?1624983493)

https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/main/Keypad_Examples/one_button/code.py

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`&nbsp;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` is `True` **,** enable an internal pull-down resistor, to hold the pin low when not pressed.
- If `value_when_pressed` is `False` **,** 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:

```terminal
&lt;Event: key_number 0 pressed&gt;
&lt;Event: key_number 0 released&gt;
&lt;Event: key_number 0 pressed&gt;
&lt;Event: key_number 0 released&gt;
```

## 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.&nbsp;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 of `pressed`; 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 of &nbsp;[`supervisor.ticks_ms`](https://docs.circuitpython.org/en/7.3.x/shared-bindings/supervisor/index.html#supervisor.ticks_ms "supervisor.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.

## MacroPad Example
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`.

![circuitpython_5128-11.jpg](https://cdn-learn.adafruit.com/assets/assets/000/103/221/medium640/circuitpython_5128-11.jpg?1624985733)

https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/main/Keypad_Examples/macropad_simple/code.py

## 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.

![](https://cdn-learn.adafruit.com/assets/assets/000/113/332/medium800/circuitpython_numberpad.png?1658318903)

https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/main/Keypad_Examples/macropad_hid/code.py

# Keypad and Matrix Scanning in CircuitPython

## KeyMatrix

The `KeyMatrix` scanner scans keys that are wired in a row-column matrix. Each key is wired to a single row line and a single column line. Each row and column line goes to a pin. So for instance a 3x4 matrix of 12 keys will have 3 column lines and 4 row lines. We only need 7 pins (3+4) to scan this matrix instead of 12.

Optionally, there is diode attached to each key as well. This prevents false presses when you press several keys at once.

Here is a simple 2x3 matrix without diodes. There are 2 rows and 3 columns.

![circuitpython_2x3-matrix.png](https://cdn-learn.adafruit.com/assets/assets/000/103/229/medium640/circuitpython_2x3-matrix.png?1624991801)

Here is 2x3 matrix with diodes. In this case, the columns are connected to the diode anodes, and the rows are connected to the cathodes. It could be the other way around.

![circuitpython_2x3-with-diodes.png](https://cdn-learn.adafruit.com/assets/assets/000/128/936/medium640/circuitpython_2x3-with-diodes.png?1711468154)

## Keypad Matrix Example

In this example, a `KeypadMatrix` is created and then monitored.

This example is for a 3x4 matrix, such as the Adafruit [3x4 Matrix Keypad](https://www.adafruit.com/product/3845)&nbsp;(pictured), the [Adafruit Membrane 3x4 Keypad](https://www.adafruit.com/product/419), or the [3x4 Phone-style Matrix Keypad](https://www.adafruit.com/product/1824). For details about wiring these keypads, see the [Matrix Keypad Guide](https://learn.adafruit.com/matrix-keypad).

&nbsp;

![circuitpython_3845-01.jpg](https://cdn-learn.adafruit.com/assets/assets/000/103/231/medium640/circuitpython_3845-01.jpg?1624992828)

https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/main/Keypad_Examples/keymatrix/code.py

Here is some output from this program. Remember that the key numbers start from 0, so they probably don't correspond to the labels on the keys themselves.

```terminal
&lt;Event: key_number 0 pressed&gt;
&lt;Event: key_number 0 released&gt;
&lt;Event: key_number 1 pressed&gt;
&lt;Event: key_number 1 released&gt;
&lt;Event: key_number 3 pressed&gt;
&lt;Event: key_number 3 released&gt;
```

## Which Way are the Diodes?

The 3x4 keypads above don't have any diodes, so we don't need specify diode orientation. But if you're building a typing or music keyboard, you probably have diodes, and need to specify their orientation. To do this, you set the `columns_to_anodes` parameter when you construct the `KeyMatrix`.

If the column lines are connected to the diode anodes and the rows are connected to the cathodes, set `columns_to_anodes` to `True`, which is the default. If the reverse is true, set `columns_to_anodes` to `False`.

![circuitpython_diode-anode-cathode.png](https://cdn-learn.adafruit.com/assets/assets/000/103/235/medium640/circuitpython_diode-anode-cathode.png?1624994206)

Danger: See the [Raspberry Pi RP2350 Erratum Workarounds](https://learn.adafruit.com/key-pad-matrix-scanning-in-circuitpython/raspberry-pi-rp2350-erratum-workarounds) page in this Guide for workarounds that are needed when using `keypad.KeyMatrix` on an RP2350.

Here's an example of specifying `columns_to_anodes` when the diode directions match the schematic at the top of this page:

https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/main/Keypad_Examples/keymatrix_columns_to_anodes/code.py

# Keypad and Matrix Scanning in CircuitPython

## ShiftRegisterKeys

The `ShiftRegisterKeys` scanner scans keys that are attached to a parallel-in serial out shift register. The key states are loaded into the shift register all at once, and then clocked out of the shift register into an input pin that is read serially.

**At this time we support basic clocked/latched shift registers such as 74x165 chips. These are very inexpensive, but require external pull-up/down resistors. We do not support shift-register-to-matrix or I2C/SPI expanders.**

Several Adafruit products, such as the [PyBadge](https://www.adafruit.com/product/4200) and the [PyGamer](https://www.adafruit.com/product/4242), use a shift register to monitor their buttons. Other products such as SNES game controllers also use shift registers.

## PyBadge or PyGamer ShiftRegisterKeys Example
This example reads the buttons on a PyBadge or PyGamer. They both work the same way. (The joystick on the PyGamer is an analog joystick, and is read using `AnalogIn`; it can't be read with `keypad`).

![circuitpython_4200-05.jpg](https://cdn-learn.adafruit.com/assets/assets/000/103/247/medium640/circuitpython_4200-05.jpg?1624995780)

![circuitpython_4242-04.jpg](https://cdn-learn.adafruit.com/assets/assets/000/103/248/medium640/circuitpython_4242-04.jpg?1624995798)

We don't know how many keys are connected to the shift register. There could also be multiple shift registers chained together. So we have to specify a `key_count` in the example below, which is the total length of the shift register or registers.

https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/main/Keypad_Examples/shift_register_keys/code.py

## SNES Controller Example
Controllers for the venerable SNES game system also use shift registers. Adafruit stocks an [SNES controller](https://www.adafruit.com/product/131), and they are readily available elsewhere as well. The controller is pictured on the left, with extra labelling for some of the buttons.

These controllers have 12 buttons, so they use two 8-bit shift registers chained together, with the last 4 bits ignored. So we'll set `key_count` to 12 below.

The pinout for the connector is shown on the left. Note there is a group of 3 and a group of 4 pins, and one end is rounded.

![circuitpython_131-01-labelled.jpg](https://cdn-learn.adafruit.com/assets/assets/000/103/255/medium640/circuitpython_131-01-labelled.jpg?1625003380)

![circuitpython_1576-01_pinout.jpg](https://cdn-learn.adafruit.com/assets/assets/000/103/256/medium640/circuitpython_1576-01_pinout.jpg?1625003426)

### Which Way to Latch?

The PyBadge and PyGamer use 74HC165 shift registers. These shift registers latch the input when the **latch** pin is high ( **True** ). That's the default for `ShiftRegisterKeys`. But the SNES controller uses CD4021 shift registers. They latch on low, so we need to specify an extra argument to specify how to latch: we set `value_to_latch` to `False` in the code below (the default is `True`).

### SNES Key Names

The program below prints out the SNES key names by looking up the key numbers in the `SNES_KEY_NAMES` tuple. Key number 0 is "B", 1 is "Y", etc.

https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/main/Keypad_Examples/snes_controller/code.py

Here's some sample output from the program above:

```terminal
START pressed
START released
B pressed
B released
B pressed
B released
X pressed
X released
Y pressed
Y released
L pressed
R pressed
R released
R pressed
R released
L released
DOWN pressed
LEFT pressed
B pressed
DOWN released
LEFT released
B released
LEFT pressed
LEFT released
LEFT pressed
LEFT released
```

# Keypad and Matrix Scanning in CircuitPython

## Advanced Features

## 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:

https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/main/Keypad_Examples/longer_interval/code.py

## 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:

https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/main/Keypad_Examples/max_events/code.py

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:

https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/main/Keypad_Examples/overflow/code.py

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()`:

https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/main/Keypad_Examples/reuse_event/code.py

## 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.

https://github.com/adafruit/Adafruit_Learning_System_Guides/blob/main/Keypad_Examples/comparing_events/code.py

# Keypad and Matrix Scanning in CircuitPython

## Raspberry Pi RP2350 E9 Erratum Workarounds

The Raspberry Pi RP2350 has a [hardware issue](https://github.com/raspberrypi/pico-feedback/issues/401) that can cause its GPIO pins to read as high even when the internal pull-downs on the pins are enabled. See the&nbsp;[**Warning** in the CircuitPython&nbsp;`DigitalInout` documentation](https://docs.circuitpython.org/en/latest/shared-bindings/digitalio/index.html#digitalio.DigitalInOut) for more information about the problem.

This issue means that `keypad` functionality that would normally depend on using the internal pull-down resistors will not work properly.

## `keypad.Keys`

If you are setting up a `keypad.Keys` object where `value_when_pressed=True` (the switch connects to +V when pressed) and you are using `pull=True` to enable the internal pull-down resistor, this will not work properly. Instead, either rewire the switch to be `value_when_pressed=False` (the switch connects the pin to ground when pressed), or add an external pull-down that is 8.2 kohms or less.

The schematic diagram below shows how to wire a button so that its `value_when_pressed` is `False`.

![pushbutton with one end grounded](https://cdn-learn.adafruit.com/assets/assets/000/137/325/medium800/circuitpython_grounding-button.png?1748977616 )

## `keypad.KeyMatrix`

A keypad.KeyMatrix object with `columns_to_anodes=False` will normally depend on using the internal pull-down resistors. This will not work properly. The easiest fix&nbsp; is simply to swap the `row_pins` and `column_pins` and set `columns_to_anodes=True`. An alternative is to add external pull-downs of 8.2 kohms or less, but that will draw more current, and swapping the pins in software is much easier.

![keyboard matrix with diodes with column pins connected to diode anodes](https://cdn-learn.adafruit.com/assets/assets/000/137/327/medium800/circuitpython_2x3-with-diodes-columns-to-anodes-true.png?1748977677 )

An alternative is to add external pull-downs of 8.2 kohms or less, but that will draw more current, and swapping the pins in software is much easier.


## Featured Products

### Adafruit MacroPad RP2040 Starter Kit - 3x4 Keys + Encoder + OLED

[Adafruit MacroPad RP2040 Starter Kit - 3x4 Keys + Encoder + OLED](https://www.adafruit.com/product/5128)
Strap yourself in, we're launching in T-minus 10 seconds...Destination? A new Class M planet called MACROPAD! M here stands for Microcontroller because this 3x4 keyboard controller features the newest technology from the Raspberry Pi sector: say hello to the RP2040. It's a speedy...

Out of Stock
[Buy Now](https://www.adafruit.com/product/5128)
[Related Guides to the Product](https://learn.adafruit.com/products/5128/guides)
### 3x4 Phone-style Matrix Keypad

[3x4 Phone-style Matrix Keypad](https://www.adafruit.com/product/1824)
Hey, Jenny, I've got your number! And I'm going to dial 867-5309 into this very nice phone-style matrix keypad. This keypad has 12 buttons, arranged in a telephone-line 3x4 grid. It's made of plastic with sturdy plastic buttons. The keys are connected to a matrix so you only need 7...

In Stock
[Buy Now](https://www.adafruit.com/product/1824)
[Related Guides to the Product](https://learn.adafruit.com/products/1824/guides)
### Membrane 3x4 Matrix Keypad + extras

[Membrane 3x4 Matrix Keypad + extras](https://www.adafruit.com/product/419)
Punch in your secret key into this numeric matrix keypad. This keypad has 12 buttons, arranged in a telephone-line 3x4 grid. It's made of a thin, flexible membrane material with an adhesive backing (just remove the paper) so you can attach it to nearly anything. The keys are connected into...

In Stock
[Buy Now](https://www.adafruit.com/product/419)
[Related Guides to the Product](https://learn.adafruit.com/products/419/guides)
### Membrane 1x4 Keypad + Extras

[Membrane 1x4 Keypad + Extras](https://www.adafruit.com/product/1332)
Punch in your secret key into this numeric membrane keypad. This keypad has 4 buttons, and since every key has its own wire line, no matrix code is required - just treat these like every day switches. The membrane is soft and has a removable paper backing to expose a strong adhesive so you can...

In Stock
[Buy Now](https://www.adafruit.com/product/1332)
[Related Guides to the Product](https://learn.adafruit.com/products/1332/guides)
### SNES Controller

[SNES Controller](https://www.adafruit.com/product/131)
A third-party SNES (Super Nintendo/Famicom) controller. Works great with Fuzeboxen as well!

No Longer Stocked
[Buy Now](https://www.adafruit.com/product/131)
[Related Guides to the Product](https://learn.adafruit.com/products/131/guides)
### Tactile Switch Buttons (12mm square, 6mm tall) x 10 pack

[Tactile Switch Buttons (12mm square, 6mm tall) x 10 pack](https://www.adafruit.com/product/1119)
Medium-sized clicky momentary switches are standard input "buttons" on electronic projects. These work best in a PCB but [can be used on a solderless breadboard as shown in this tutorial](https://learn.adafruit.com/adafruit-arduino-lesson-6-digital-inputs?view=all). The...

In Stock
[Buy Now](https://www.adafruit.com/product/1119)
[Related Guides to the Product](https://learn.adafruit.com/products/1119/guides)
### Silicone Elastomer 4x4 Button Keypad - for 3mm LEDs

[Silicone Elastomer 4x4 Button Keypad - for 3mm LEDs](https://www.adafruit.com/product/1611)
So squishy! These silicone elastomer keypads are just waiting for your fingers to press them. Go ahead, squish all you like! (They're durable and easy to clean, just wipe with mild soap and water) These are just like the light up rubber buttons you find on stuff like appliances and tools,...

In Stock
[Buy Now](https://www.adafruit.com/product/1611)
[Related Guides to the Product](https://learn.adafruit.com/products/1611/guides)

## Related Guides

- [Adafruit MacroPad RP2040](https://learn.adafruit.com/adafruit-macropad-rp2040.md)
- [3D Printed Stand for MacroPad RP2040](https://learn.adafruit.com/3d-printed-stand-for-macropad-rp2040.md)
- [Ambient Color Control Pad](https://learn.adafruit.com/ambient-color-controller.md)
- [Wireless NeoPixel Controller](https://learn.adafruit.com/neotrellis-neopixel-controller.md)
- [Scrambled Number Security Keypad](https://learn.adafruit.com/scrambled-number-security-keypad.md)
- [Introducing Adafruit Trellis ](https://learn.adafruit.com/adafruit-trellis-diy-open-source-led-keypad.md)
- [MacroPad Summer Olympics Hotkeys](https://learn.adafruit.com/macropad-olympic-hotkeys.md)
- [MacroPad 2FA TOTP Authentication Friend](https://learn.adafruit.com/macropad-2fa-totp-authentication-friend.md)
- [AdaBox 010](https://learn.adafruit.com/adabox010.md)
- [MACROPAD Hotkeys](https://learn.adafruit.com/macropad-hotkeys.md)
- [NeoTrellis MIDI Feedback Controller](https://learn.adafruit.com/neotrellis-midi-feedback-controller.md)
- [Trellis 3D Printed Enclosure](https://learn.adafruit.com/trellis-3d-printed-enclosure.md)
- [Trellis M4 Beat Sequencers](https://learn.adafruit.com/trellis-m4-beat-sequencer.md)
- [NeoTrellis Sound Board](https://learn.adafruit.com/neotrellis-soundboard.md)
- [Portable Trellis Sound Board](https://learn.adafruit.com/portable-trellis-sound-board.md)
- [Trellis M4 Expressive MIDI Controller](https://learn.adafruit.com/trellis-m4-midi-keypad-and-tilt-controller.md)
