This is a 12-key numeric keypad for use in a range of microcontroller projects (Figure 1). It has the advantage that you only need one analogue input to interface it.
It's on a small 1.2 × 1.6" (30 × 40 mm) PCB, and I've also built a demo circuit to show how to use it.
![]() |
|
| Figure 1. | The 12-key numeric keypad that interfaces to a single analogue input. |
Introduction
Microcontroller projects often need a numeric keypad, and a typical approach is to arrange the keys in a matrix of rows and columns; so for a 3 × 4 numeric keypad you might need to scan seven I/O pins.
This keypad works differently; each key generates a different analogue voltage, and you only need a single analogue input to interface it. I wrote about the idea some time ago in previous articles, and I've incorporated keypads using this approach in several projects, but I've never published a PCB to allow you to create a stand-alone keypad. However, recently I wanted to prototype a project on a breadboard using a keypad, and I wished I had a PCB version. So here it is.
The circuit
The circuit of the keypad is shown in Figure 2.
![]() |
|
| Figure 2. | The circuit of the one-input numeric keypad, which uses a network of six resistors. |
The buttons are widely available 6 × 6 mm tactile buttons. It uses a network of six 0805 surface-mount E6 resistors, arranged as a voltage divider, so each keypress generates a different voltage. It's also designed to draw no current unless a key is pressed. The resistor values are calculated to give the best spread of voltages in the available range from GND to VDD.
The '*' and '#' keys generate the values 10 and 11 respectively; they are useful for functions such as Enter and Delete. The surface-mount resistors are mounted on the back of the board (Figure 3), and the three connections are brought out to a five-way pin header at the top of the board (only three of the pins are used):
![]() |
|
| Figure 3. | The back of the one-input numeric keypad PCB showing the six 0805 surface-mount resistors. |
The program
Here's the ReadKeypad() function that interrogates the keypad:
const int Keypad = PIN_PC0;
const int SmallestGap = 40;
int Values[] = {1023,680,640,590,547,507,464,411,351,273,180,133, 0,-100};
int Buttons[] = { -1, 11, 9, 6, 3, 0, 10, 8, 7, 5, 4, 2, 1};
int ReadKeypad () {
int val, lastval=0, count = 0;
do {
val = analogRead(Keypad);
if (abs(val-lastval)<2) count++;
else { lastval = val; count = 0; }
} while (count < 3);
int i = 0;
val = val - SmallestGap/2;
while (val < Values[i]) { i++; }
return Buttons[i - 1];
}
The constant Keypad specifies the analogue input that the keypad is connected to. The program uses two arrays: Values[] stores the analogue values given by each pin, in descending order, and Buttons[] stores the corresponding button for each voltage. The ReadKeypad() routine reads the analogue input, and then checks the value against each value in Values[] until it's larger; it then returns the corresponding button from Buttons[]. If no key is pressed it returns –1.
Demo circuit
I built a simple circuit to demonstrate the keypad by displaying the key pressed on a seven-segment LED display (Figure 4).
![]() |
|
| Figure 4. | The demonstration circuit for the one-input numeric keypad, based on an AVR32EB14, displays the key pressed on a seven-segment LED display. |
I built the demo circuit on a 360 hole breadboard, using pre-cut colour-coded jumper wires to make the interconnections easier. I used an AVR32EB14 in a TSSOP-14 package, mounted on a breakout board and a 0.56" single-digit seven-segment display. The display is driven directly from the eight I/O pins PA0 to PA1, PC2 to PC3, and PD4 to PD7, with a 220 Ω current-limiting resistor from the common cathode to GND. PC0 is used for the analogue keypad input.



