The 4×4 keypad has sixteen buttons, which is enough for two octaves of a piano. In this lesson each key plays a different note on the passive buzzer: the top two rows are the white keys of one octave, and the bottom rows continue higher. Two special keys turn it into a small music machine: * starts recording, and # plays back what you recorded.
What you'll learn
- How the Keypad library finds which key is pressed
- How musical notes are frequencies in hertz
- How to store a melody in an array and play it back
- How to look up a value from a key with a simple table
What you need
- UNO R3 board and USB cable (UNO R3 Starter Kit)
- 4×4 keypad module (UNO R3 Starter Kit)
- Passive buzzer (UNO R3 Starter Kit)
- 8 male-to-male jumper wires for the keypad
- The printed parts from the 3D printing box below (keypad stand), or the cardboard version described there
- Breadboard and jumper wires (UNO R3 Starter Kit)
Wiring

| From | To |
|---|---|
| Keypad R1, R2, R3, R4 | UNO pins 9, 8, 7, 6 |
| Keypad C1, C2, C3, C4 | UNO pins 5, 4, 3, 2 |
| Passive buzzer + | UNO pin 11 |
| Passive buzzer − | GND |
With the keys facing you, the keypad's eight pins are R1 to R4 on the left and C1 to C4 on the right. This is the same wiring as the keypad lesson.
The sketch
In the Arduino IDE, open Library Manager and install the Keypad library by Mark Stanley and Alexander Brevig.
#include <Keypad.h>
const byte ROWS = 4, COLS = 4;
char keys[ROWS][COLS] = {
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};
byte rowPins[ROWS] = {9, 8, 7, 6};
byte colPins[COLS] = {5, 4, 3, 2};
Keypad keypad = Keypad(makeKeymap(keys), rowPins, colPins, ROWS, COLS);
const int BUZZER_PIN = 11;
const char NOTE_KEYS[] = "123A456B7890CD"; // 14 keys play notes
// C major scale over two octaves: C4 ... B5
const int NOTES[] = {262, 294, 330, 349, 392, 440, 494, 523, 587, 659, 698, 784, 880, 988};
const int MAX_NOTES = 40;
int tune[MAX_NOTES];
int tuneLength = 0;
bool recording = false;
int frequencyFor(char key) {
for (int i = 0; i < 14; i++) {
if (NOTE_KEYS[i] == key) return NOTES[i];
}
return 0;
}
void setup() {
Serial.begin(9600);
Serial.println("Play! * = record, # = play back");
}
void loop() {
char key = keypad.getKey();
if (!key) return;
if (key == '*') {
recording = !recording;
if (recording) tuneLength = 0;
tone(BUZZER_PIN, recording ? 1500 : 500, 150); // high beep: start, low beep: stop
Serial.println(recording ? "Recording..." : "Recording stopped");
return;
}
if (key == '#') {
Serial.print("Playing ");
Serial.print(tuneLength);
Serial.println(" notes");
for (int i = 0; i < tuneLength; i++) {
tone(BUZZER_PIN, tune[i], 250);
delay(300);
}
return;
}
int freq = frequencyFor(key);
tone(BUZZER_PIN, freq, 250);
if (recording && tuneLength < MAX_NOTES) tune[tuneLength++] = freq;
}
Play a tune
The keys play C D E F on the top row (1 2 3 A), G A B C on the second row (4 5 6 B), and continue higher on 7 8 9 0 C D. "Ode to Joy" starts with 3 3 A 4 4 A 3 2 1 1 2 3 3 2 2. Press *, play it, press * again, then # to hear it back.
How it works
The keypad is a grid of wires: four rows and four columns, with a button at every crossing. The Keypad library switches each row on in turn and checks which column answers. That way 16 buttons need only 8 pins.
Every note is a frequency: the A above middle C vibrates 440 times a second (440 Hz), and each octave higher doubles the frequency. frequencyFor() looks for the key in NOTE_KEYS and returns the matching number from NOTES, the same position in a second list. Recording simply saves each frequency in the tune array; playback walks through it with a for loop.
Try this next
- Record how long you hold each note too, and play the rhythm back.
- Add a second scale (for example a minor scale) and switch with a key.
- Save the tune in EEPROM so it survives switching off.
Troubleshooting
- The wrong notes play: the row and column wires are swapped. Check them against the table.
- No sound: use the passive buzzer, not the active one, and check it is on pin 11.
- A whole row does nothing: one row wire is loose. Press each key in the row and check the Serial Monitor.
- A printed part is too tight or too loose: printers differ by a few tenths of a millimetre. Sand or file a tight hole, and fix a loose part with a drop of hot glue or a strip of tape.