Skip to main content

Tutorial 4 - Matrix Keypad

Introduction​

A keypad is a rectangular array of buttons. In this tutorial, you will connect a matrix keypad to the Raspberry Pi 5 and read the character input from each key press.

Components Needed​

ComponentQuantity
Raspberry Pi 51
Breadboard1
WiresSeveral
Matrix Keypad1
1K Ohm Resistor8

Matrix keypad components

Image credit: SunFounder

Fritzing Diagram​

Connect the keypad to your Raspberry Pi as shown in the following diagram.

Matrix keypad schematic

Image credit: SunFounder

Code​

from gpiozero import DigitalOutputDevice, Button
from time import sleep

# Configure rows, columns, and keypad layout
rows_pins = [18, 23, 24, 25]
cols_pins = [10, 22, 27, 17]
keys = ["1", "2", "3", "A",
"4", "5", "6", "B",
"7", "8", "9", "C",
"*", "0", "#", "D"]

# Initialize row pins as DigitalOutputDevice
rows = [DigitalOutputDevice(pin) for pin in rows_pins]
# Initialize column pins as Buttons
cols = [Button(pin, pull_up=False) for pin in cols_pins]

def read_keypad():
"""
Read the currently pressed keys on the keypad.
:return: A list of pressed keys.
"""
pressed_keys = []
for i, row in enumerate(rows):
row.on()
for j, col in enumerate(cols):
if col.is_pressed:
index = i * len(cols) + j
pressed_keys.append(keys[index])
row.off()
return pressed_keys

last_key_pressed = []

print("Press keys on the keypad. Press Ctrl+C to exit.")
while True:
pressed_keys = read_keypad()
if pressed_keys and pressed_keys != last_key_pressed:
print(pressed_keys)
last_key_pressed = pressed_keys
sleep(0.1)

Code Overview​

The row pins are configured as outputs and the column pins are configured as inputs. The read_keypad() function activates each row one at a time and checks which columns respond, making it possible to identify the pressed key.

Code Explanation​

rows_pins = [18, 23, 24, 25]
cols_pins = [10, 22, 27, 17]

These lists define the GPIO pins connected to the rows and columns of the keypad.

rows = [DigitalOutputDevice(pin) for pin in rows_pins]
cols = [Button(pin, pull_up=False) for pin in cols_pins]

Rows are set as outputs and columns are set as inputs.

def read_keypad():

This function scans the keypad and returns a list of pressed keys.

index = i * len(cols) + j
pressed_keys.append(keys[index])

This calculates the correct character based on the current row and column.

sleep(0.1)

The small delay lowers CPU usage while continuously scanning the keypad.

Code Password Example​

from gpiozero import DigitalOutputDevice, Button
from time import sleep

rows_pins = [18, 23, 24, 25]
cols_pins = [10, 22, 27, 17]
keys = ["1", "2", "3", "A",
"4", "5", "6", "B",
"7", "8", "9", "C",
"*", "0", "#", "D"]

rows = [DigitalOutputDevice(pin) for pin in rows_pins]
cols = [Button(pin, pull_up=False) for pin in cols_pins]

password = ["1", "2", "3", "4"]
entered_keys = []

def read_keypad():
pressed_keys = []
for i, row in enumerate(rows):
row.on()
for j, col in enumerate(cols):
if col.is_pressed:
index = i * len(cols) + j
pressed_keys.append(keys[index])
row.off()
return pressed_keys

last_key_pressed = []

print("Press keys on the keypad. Press Ctrl+C to exit.")
while True:
pressed_keys = read_keypad()
if pressed_keys and pressed_keys != last_key_pressed:
for key in pressed_keys:
if key == "#":
if entered_keys == password:
print("Access Granted!")
else:
print("Access Denied! Try again.")
entered_keys = []
elif key == "*":
entered_keys = []
else:
entered_keys.append(key)
print(f"Entered keys: {entered_keys}")
last_key_pressed = pressed_keys
sleep(0.1)