Blog

4×4 Matrix Keypad – Complete Guide

Matrix Keypad

4x4 Matrix Keypad

16-Button Membrane Keypad with Row/Column Scanning

Wiring 16 individual buttons to a microcontroller the naive way would need 16 separate input pins plus pull-down resistors for each - a matrix keypad avoids that entirely by arranging its 16 buttons in a 4x4 grid where each button sits at the intersection of one row wire and one column wire, needing only 8 total pins (4 rows plus 4 columns) no matter how many buttons are in the grid. Your microcontroller scans the keypad by driving one row LOW at a time while reading all four column pins - when a button is pressed, it briefly connects its row to its column, so if a specific column reads LOW while a specific row is being driven LOW, your code knows exactly which of the 16 buttons was pressed from that unique row/column combination. This scanning happens fast enough, many times per second, that key presses feel instantaneous even though the microcontroller is really checking one row at a time in rapid succession rather than reading all 16 buttons simultaneously.

16 Buttons
Key Count
4x4 Grid
Layout
8 Pins (Row + Column)
Wiring

Key features

Efficient Pin Usage

Reads 16 buttons using only 8 microcontroller pins.

Row/Column Scanning

A well-understood, widely-documented matrix scanning technique.

Membrane Construction

Thin, flexible, and low-cost compared to individual mechanical buttons.

Standard 0-9/A-D/*/# Layout

Familiar telephone/calculator-style button arrangement.

No External Components Needed

Works directly with a microcontroller's internal pull-ups.

Compact, Flat Form Factor

Easy to mount on an enclosure face or panel.

Technical specifications

Operating Voltage Logic-level, passive (no power pin needed)
Layout 4 rows x 4 columns (16 buttons total)
Interface 8 digital pins (4 row + 4 column)
Construction Flexible membrane / carbon-contact
Default Labels 0–9, A–D, *, # (standard layout)
Actuation Momentary contact, no latching
Connector Flat ribbon cable
Mounting Adhesive backing or panel-mount holes (variant dependent)
Package Flat membrane keypad, no onboard electronics

Pinout

PinFunction
R1–R4 Row pins
C1–C4 Column pins
Ribbon Cable 8-wire flat ribbon - wire order varies by supplier, see tip below

Applications

PIN-code entry and access-control panels Calculator and menu-navigation projects Garage door and gate keypad entry systems Simple game controller input Appliance control panels DIY combination lock projects

What's in the box

1x 4x4 matrix membrane keypad

Downloads

Datasheet (PDF) Arduino Keypad Library Example Sketch
🔌
Pin Connections
1 Table
Pin Connections Table 1
BoardSensor PinConnection
Keypad4 rows + 4 cols8 board digital pins
📟
4x4 Matrix 16 Keyboard Keypad
7 Examples • C/C++ | Boards: Arduino Uno, Arduino Nano, Arduino Mega, ESP32, ESP8266, STM32, Raspberry Pi Pico
4x4 Matrix 16 Keyboard Keypad - Arduino Uno
4x4 Matrix 16 Keyboard Keypad - Arduino Nano
4x4 Matrix 16 Keyboard Keypad - Arduino Mega
4x4 Matrix 16 Keyboard Keypad - ESP32
4x4 Matrix 16 Keyboard Keypad - ESP8266
4x4 Matrix 16 Keyboard Keypad - STM32
4x4 Matrix 16 Keyboard Keypad - Raspberry Pi Pico
📄 File: 4x4_matrix_16_keyboard_keypad_-_arduino_uno.inoArduino Uno
608 characters
1//ekostra.com
2//electronics store in egypt
3//+201008896258
4
5// Row pins on Arduino Uno: 9, 8, 7, 6 Column pins: 5, 4, 3, 2
6#include <Keypad.h>
7
8const byte ROWS = 4;
9const byte COLS = 4;
10char keys[ROWS][COLS] = {
11 {'1','2','3','A'},
12 {'4','5','6','B'},
13 {'7','8','9','C'},
14 {'*','0','#','D'}
15};
16byte rowPins[ROWS] = {9, 8, 7, 6};
17byte colPins[COLS] = {5, 4, 3, 2};
18
19Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
20
21void setup() {
22 Serial.begin(115200);
23}
24
25void loop() {
26 char key = keypad.getKey();
27 if (key) {
28 Serial.print("Key pressed: ");
29 Serial.println(key);
30 }
31}
📄 File: 4x4_matrix_16_keyboard_keypad_-_arduino_nano.inoArduino Nano
609 characters
1//ekostra.com
2//electronics store in egypt
3//+201008896258
4
5// Row pins on Arduino Nano: 9, 8, 7, 6 Column pins: 5, 4, 3, 2
6#include <Keypad.h>
7
8const byte ROWS = 4;
9const byte COLS = 4;
10char keys[ROWS][COLS] = {
11 {'1','2','3','A'},
12 {'4','5','6','B'},
13 {'7','8','9','C'},
14 {'*','0','#','D'}
15};
16byte rowPins[ROWS] = {9, 8, 7, 6};
17byte colPins[COLS] = {5, 4, 3, 2};
18
19Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
20
21void setup() {
22 Serial.begin(115200);
23}
24
25void loop() {
26 char key = keypad.getKey();
27 if (key) {
28 Serial.print("Key pressed: ");
29 Serial.println(key);
30 }
31}
📄 File: 4x4_matrix_16_keyboard_keypad_-_arduino_mega.inoArduino Mega
609 characters
1//ekostra.com
2//electronics store in egypt
3//+201008896258
4
5// Row pins on Arduino Mega: 9, 8, 7, 6 Column pins: 5, 4, 3, 2
6#include <Keypad.h>
7
8const byte ROWS = 4;
9const byte COLS = 4;
10char keys[ROWS][COLS] = {
11 {'1','2','3','A'},
12 {'4','5','6','B'},
13 {'7','8','9','C'},
14 {'*','0','#','D'}
15};
16byte rowPins[ROWS] = {9, 8, 7, 6};
17byte colPins[COLS] = {5, 4, 3, 2};
18
19Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
20
21void setup() {
22 Serial.begin(115200);
23}
24
25void loop() {
26 char key = keypad.getKey();
27 if (key) {
28 Serial.print("Key pressed: ");
29 Serial.println(key);
30 }
31}
📄 File: 4x4_matrix_16_keyboard_keypad_-_esp32.inoESP32
618 characters
1//ekostra.com
2//electronics store in egypt
3//+201008896258
4
5// Row pins on ESP32: 13, 12, 14, 27 Column pins: 26, 25, 33, 32
6#include <Keypad.h>
7
8const byte ROWS = 4;
9const byte COLS = 4;
10char keys[ROWS][COLS] = {
11 {'1','2','3','A'},
12 {'4','5','6','B'},
13 {'7','8','9','C'},
14 {'*','0','#','D'}
15};
16byte rowPins[ROWS] = {13, 12, 14, 27};
17byte colPins[COLS] = {26, 25, 33, 32};
18
19Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
20
21void setup() {
22 Serial.begin(115200);
23}
24
25void loop() {
26 char key = keypad.getKey();
27 if (key) {
28 Serial.print("Key pressed: ");
29 Serial.println(key);
30 }
31}
📄 File: 4x4_matrix_16_keyboard_keypad_-_esp8266.inoESP8266
620 characters
1//ekostra.com
2//electronics store in egypt
3//+201008896258
4
5// Row pins on ESP8266: D0, D3, D4, D5 Column pins: D6, D7, D8, D2
6#include <Keypad.h>
7
8const byte ROWS = 4;
9const byte COLS = 4;
10char keys[ROWS][COLS] = {
11 {'1','2','3','A'},
12 {'4','5','6','B'},
13 {'7','8','9','C'},
14 {'*','0','#','D'}
15};
16byte rowPins[ROWS] = {D0, D3, D4, D5};
17byte colPins[COLS] = {D6, D7, D8, D2};
18
19Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
20
21void setup() {
22 Serial.begin(115200);
23}
24
25void loop() {
26 char key = keypad.getKey();
27 if (key) {
28 Serial.print("Key pressed: ");
29 Serial.println(key);
30 }
31}
📄 File: 4x4_matrix_16_keyboard_keypad_-_stm32.inoSTM32
634 characters
1//ekostra.com
2//electronics store in egypt
3//+201008896258
4
5// Row pins on STM32: PA0, PA1, PA2, PA3 Column pins: PA4, PA5, PA6, PA7
6#include <Keypad.h>
7
8const byte ROWS = 4;
9const byte COLS = 4;
10char keys[ROWS][COLS] = {
11 {'1','2','3','A'},
12 {'4','5','6','B'},
13 {'7','8','9','C'},
14 {'*','0','#','D'}
15};
16byte rowPins[ROWS] = {PA0, PA1, PA2, PA3};
17byte colPins[COLS] = {PA4, PA5, PA6, PA7};
18
19Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
20
21void setup() {
22 Serial.begin(115200);
23}
24
25void loop() {
26 char key = keypad.getKey();
27 if (key) {
28 Serial.print("Key pressed: ");
29 Serial.println(key);
30 }
31}
📄 File: 4x4_matrix_16_keyboard_keypad_-_raspberry_pi_pico.inoRaspberry Pi Pico
630 characters
1//ekostra.com
2//electronics store in egypt
3//+201008896258
4
5// Row pins on Raspberry Pi Pico: 10, 11, 12, 13 Column pins: 14, 15, 16, 17
6#include <Keypad.h>
7
8const byte ROWS = 4;
9const byte COLS = 4;
10char keys[ROWS][COLS] = {
11 {'1','2','3','A'},
12 {'4','5','6','B'},
13 {'7','8','9','C'},
14 {'*','0','#','D'}
15};
16byte rowPins[ROWS] = {10, 11, 12, 13};
17byte colPins[COLS] = {14, 15, 16, 17};
18
19Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
20
21void setup() {
22 Serial.begin(115200);
23}
24
25void loop() {
26 char key = keypad.getKey();
27 if (key) {
28 Serial.print("Key pressed: ");
29 Serial.println(key);
30 }
31}
16-button matrix keypad.
Use a proven matrix-scanning library such as the Arduino Keypad library rather than hand-rolling row/column scanning logic - debouncing and multi-key edge cases are already handled correctly there. The 8 wires on the ribbon connector aren't always in a predictable order across every supplier's keypad - if button presses map to the wrong characters, the most common fix is testing and adjusting the row/column pin order in code rather than assuming a fixed pinout. And since the keypad itself is fully passive with no onboard electronics, it has no VCC/GND to worry about and cannot be plugged in backwards in a way that damages it - only the row/column pin assignments matter.