The 4×4 membrane keypad gives you 16 keys from 8 wires, the usual input for door locks and voting machines.
It needs no power and no extra parts on the Uno: four row pins and four column pins. The sketch prints each key and collects a code that you confirm with # and clear with *.
Wiring
| Arduino Uno R3 | 4×4 matrix membrane keypad | Wire | Notes |
|---|---|---|---|
| D2 | R1 | red | |
| D3 | R2 | orange | |
| D4 | R3 | yellow | |
| D5 | R4 | green | |
| D6 | C1 | blue | |
| D7 | C2 | purple | |
| D8 | C3 | white | |
| D9 | C4 | brown |
No supply — passive switch matrix part, 5 V board. The keypad has no electronics, so it works at 3.3 V or 5 V. It does need eight GPIOs; on ESP32 avoid the strapping pins (0, 2, 5, 12, 15) and the input-only pins (34–39) for the row outputs.
Board quirks
- A keypad is a passive switch matrix: no power pin and no resistors — the library scans rows and uses the Uno’s internal pull-ups on the columns.
- D2–D9 leave D0/D1 (USB serial) and D13 (on-board LED) free.
- Pin 1 of the ribbon is usually R1 at the left when the keys face you; if keys come out wrong, reverse the row or column arrays.
Code
// 4×4 membrane keypad on an Arduino Uno R3 with the Keypad library.
// Rows R1-R4 → D2, D3, D4, D5; columns C1-C4 → D6, D7, D8, D9. No resistors needed.
#include <Keypad.h>
const byte ROWS = 4;
const byte COLS = 4;
char keys[ROWS][COLS] = {
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'},
};
byte rowPins[ROWS] = {2, 3, 4, 5};
byte colPins[COLS] = {6, 7, 8, 9};
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
String entry;
void setup() {
Serial.begin(9600);
Serial.println(F("Type digits, # to enter, * to clear"));
}
void loop() {
char key = keypad.getKey();
if (!key) return;
if (key == '#') {
Serial.print(F("Entered: "));
Serial.println(entry);
entry = "";
} else if (key == '*') {
entry = "";
Serial.println(F("Cleared"));
} else {
entry += key;
Serial.print(F("Key: "));
Serial.println(key);
}
}// 4×4 membrane keypad on an Arduino Uno R3 with the Keypad library.
// Rows R1-R4 → D2, D3, D4, D5; columns C1-C4 → D6, D7, D8, D9. No resistors needed.
#include <Keypad.h>
const byte ROWS = 4;
const byte COLS = 4;
char keys[ROWS][COLS] = {
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'},
};
byte rowPins[ROWS] = {2, 3, 4, 5};
byte colPins[COLS] = {6, 7, 8, 9};
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
String entry;
void setup() {
Serial.begin(9600);
Serial.println(F("Type digits, # to enter, * to clear"));
}
void loop() {
char key = keypad.getKey();
if (!key) return;
if (key == '#') {
Serial.print(F("Entered: "));
Serial.println(entry);
entry = "";
} else if (key == '*') {
entry = "";
Serial.println(F("Cleared"));
} else {
entry += key;
Serial.print(F("Key: "));
Serial.println(key);
}
}Library: Keypad (Mark Stanley, Alexander Brevig) — compiled with Keypad 3.1.1.
Expected serial output
Type digits, # to enter, * to clear
Key: 1
Key: 9
Key: 8
Entered: 198Type digits, # to enter, * to clear Key: 1 Key: 9 Key: 8 Entered: 198
Common errors
Wrong keys come out
Rows and columns are mixed up. Swap the row and column pin arrays, or reverse one of them.
Some keys never register
A loose ribbon or one wire on the wrong pin — test each row with a multimeter.