2-Wire Keypad Interface Using a 555 Timer

Keypads are a very commonly used input device in microcontroller-based systems. In a keypad, multiple switches are arranged in rows and columns so that they could be interfaced to a microcontroller with a minimum number of I/O pins. For example, a 12-key keypad is arranged in a 4×3 format, which allows to interface the 12 keys to a microcontroller with only 7 connections. The location of each key on the keypad is defined by two coordinates: the row and the column. When a key is pressed, it connects its row with its column. The microcontroller must scan all the rows and columns to find out which key has been pressed. This is the most common way of interfacing a keypad to a microcontroller. There are tons of resources on the internet regarding this technique and so I am not going to discuss it here.

Today, I am going to share with you about a new keypad interfacing technique that uses only two I/O pins of a microcontroller: one for signalling the microcontroller when a key is pressed, and the other is to read the key information. It is based on a 555 timer IC which is configured as an astable multivibrator. I am not sure if anybody has ever tried using a 555 IC for keypad interfacing, but this technique really works. I am going to demonstrate this with a 4×3 keypad (a standard telephone dial pad). A PIC16F628A microcontroller will read the output of a 555 timer IC, determine what key has been pressed, and display it on a character LCD module.


This technique is based on a very simple principle. The output frequency of a 555 astable multivibrator is defined by two resistors and a capacitor, as shown below.

If we fix R1 and C, the frequency can be varied by varying R2. In this technique, each key on the keypad connects a different R2 resistor when it is pressed, and therefore, generates a different output frequency. The microcontroller can then read the output frequency and determine which key was pressed. At first it does seem more complex as it may require floating point math regarding the frequency calculations. Besides, the frequency may not be precisely stable all the time. But this can be simplified with the proper selection of resistors and the use of the timer module inside the microcontroller. So here’s how it works:

When a key is pressed, a certain value of R2 resistor is connected between pins 7 (Discharge) and 6 (Threshold) of the 555 timer, completing the astable multivibrator circuit. The output pulses are counted for 100 ms through a timer module (used as counter) in the microcontroller. The microcontroller determines the pressed key from the number of times the timer has overflown. If the timer module overflows 5 times, the pressed key is 5. Similarly, if 0 key is pressed, the timer doesn’t overflow in the 100 ms window. Isn’t it simple now?

Circuit diagram

The figure below shows how the 12 keys are connected to the 555 timer IC to generate 12 different frequencies. R0 through R# are 12 different resistors corresponding to those frequencies. You can see when a key is pressed, the corresponding resistor is connected between pins 6 (Threshold) and 7 (Discharge) and the astable multivibrator circuit is completed.

The values of R1 and C are 1 K and 0.01 uF. The following table shows the different values of R2 for each keys, the corresponding frequencies, and the number of times the Timer0 module overflows. Some of these resistors are made from combining two resistors together.

So when the # key is pressed, the Timer0 module overflows 11 times.

Important Note: For more reliable operation of this circuit, use lower tolerance values for capacitor C and R2 resistors. I am using 5% tolerance for R2 and C, but lower than this would be better.

Frequency and Pulse outputs

There are two outputs in this circuit. One is the frequency output derived directly from pin 3 that is fed to the T0CKI (Timer0 input) pin of a PIC16F628A microcontroller for counting. The second one is the smoothed pulse output using a capacitor Cp at the output of 555. When a key is pressed, the train of pulses at the output of 555 is smoothed out to a single pulse by the capacitor. This pulse is to signal the microcontroller when a key is pressed. The Rp (3.6 K) resistor provides the discharge path for the capacitor when the key is released so that another pulse would appear for next key press. The diode (D1) isolates the two outputs.

Significance of Rp and Cp values

The value of Rp is not picked randomly, it has its significance. If Rp is too high, there will be a long waiting time between any two key presses as the capacitor takes longer time to discharge through a higher resistance. Meanwhile, the value of Rp could not be too low that the capacitor voltage drops significantly between two successive pulses at the 555 output. With Rp=3.6 K and Cp = 1 uF, the RC time constant becomes 0.0036 s. It means that if the 555 output frequency is 278 Hz (1/0.0036), the voltage across the capacitor could fall down to 63% of its peak value in between the two consecutive pulses. This means the current values of Rp and Cp are not good enough to smooth out the signal. Therefore, the values of Rp and Cp must be chosen such that the RC time constant should be sufficient enough to smooth out the entire frequencies of operation and meanwhile it should be low enough that the user could press keys in sequence with minimum wait time. The current values of Rp and Cp introduces about 5 ms wait time and we don’t press keys that fast. Besides, the minimum frequency output is 1516 Hz (from the table above) which is much higher than 278 Hz.

Role of Rc resistor

If you look at the circuit diagram you will see a Rc (= 10 M?) resistor that is permanently connected between Vcc and C. This resistor plays a very interesting role. When you release a key, the astable multivibration is stopped because there is no R2 in the circuit. We know that the output stage of the 555 IC has a R-S flip-flop, the complement of which actually appear at the 555 output. Suppose the flip-flop was reset (which means the 555 output is high) at the moment when the key was released. Then there will be no way for the output to reset to 0 if the path through R2 is broken until we provide an alternative recharge path for the capacitor C. Once the capacitor gets charged to 2Vcc/3, the output will be zero again. Remember, we have to make sure that the output falls to zero before pressing another key. So Rc takes care of this. The high value of Rc (10 M?) makes sure that it has little impact on the charging of C during normal operation. If you didn’t get this part, please refer the functional block diagram of the 555 timer IC.

My 555 based 12-key keypad

I am using 5% tolerance for C

The two outputs from the keypad are connected to the PIC16F628A microcontroller. The pulse output goes to RA2 pin whereas the frequency output goes to RA4/T0CKI input of the microcontroller. A standard character LCD module is also connected to the microcontroller to display what key is pressed. I have also connected an LED with a 470R resistor in series at the output of 555 (not shown in the circuit diagram) so that it glows every time a key is pressed.


I have written a sample test program with MikroC compiler that uses Timer0 module to count the external pulses from the 555 timer output. The program polls for a pulse signal at RA2 pin, and when the pulse is detected, the Timer0 module is activated for 100 ms and the number of overflows is recorded. The pressed key is displayed on a 16×2 character LCD. You can download the source code and HEX file here.

I have got some feedbacks in past few days regarding this technique, and most of them say this would be hard from programming perspective. But let me tell you this. The microcontroller needs a program no matter you use the matrix keypad and scan rows/columns, or use a resistor divider network technique and write the program to read and compare the ADC values for the pressed key. I would say the programming part for this technique is not that hard, as I said you don’t have to deal with calculating any frequency here. You just need to enable a timer for a fixed interval (I am using 100 ms, and of course the key has to be pressed for at least that long) when a key press is detected. Then, the information regarding the pressed key is given by the number of times the timer is overflown. Here’s the flowchart of how this works.


Related Posts


  • bhavani sankar Appalla

    i like the following Statement of your RB
    I will gradually move towards that. Actually, I am still educating myself about dsPICs.

  • use lower tolerance values for capacitor C and R2 resistors.

    It is actually called “higher tolerance.”

  • i had develope the circuit as per ur diagram in proteous..bt what ever key you press ..it only shows that “keypressed : 0…”

    in short it not working..i can send you that proteous project.
    Have you any solution regarding it???

  • and one more thing before I put PIC16F628A on the socket. then I pressed a key, I got a pulses with the frequency the same as the output of 555 timer ( with the amplitude of 250mVp-p – same as after I put the PIC on the board)
    What happened?

    • Thanh,
      It seems like when you connect the output of 555 to PIC’s I/O pin, it is shorted. Make sure you are connecting the frequency pulses to the T0CKI pin. And the pin is defined as input in TRISA register.

  • hey bro, I got a problem using ur schematic . I implemented the same as ur schematic, I have the frequencies at the output of 555 quite the same as what u have but the thing happen is when I feed this output to PIC16F628A. it produces very small output like 250mVp_p so I could not drive that to the LCD.

    Secondly, I used ur code ( hex code) to program the IC ( using NEI programmer) with those options:
    .oscillator type: EXTCLK ( because we use 4MHz oscillator)
    .WATCH GOG TIMER : disable
    .power up timer : enable ( I think because we need it for the timer module)
    .RA5/Master clear select: pin used as MCLR
    .Brown_out reset: Disable
    .Low voltage programming : Enable
    .Data Memory Code Protect: Off
    .Code Protect: Code protected

    is it correct?
    hope u can reply ASAP. U will save my life bro

  • Pingback: BajHack » Podcast: Episodio 1 Piloto

  • Awesome awesome. love the way u think! 😉

  • how can we move the digit display to the right ,if i will use six digit display,thnaks for you reply .,

  • Great idea! I love this simple solution mentality. Some people would just give up and buy a bigger microcontroller. Nice job!

  • Just had another idea. (Sorry Ned) 🙂

    Why not eliminate the 555 altogether?
    The idea is to use only a single microcontroller pin. PA1.

    Buttons with series resistors are connected to VCC.
    The other side of all resistor / button combo’s are connected to PA1 and a capacitor.
    The other side of the capacitor is connected to ground.

    The software does something like:
    PA1 starts with output low to discharge the capacitor.
    PA1 switches to input and a timer is started.
    After a certain RC time PA1 goes high.
    Measure the time in an interrupt.
    Repeat the process a few times to make sure a button is pressed.

    • Hey Paul,
      I liked your suggestions; there are opportunities for further improvements in this technique but as you said that’s gonna overkill the programming part. While I was working on this project, I thought about its application to mid-range microcontrollers that don’t have ADC channels and are limited with their program memory and I/O resources. That’s why I emphasized more on calculating the proper values for the key resistances so that the programming part would just require counting the timer overflows. This helped to minimize the use of program memory.

  • found ya on hackaday.

    Fun idea to use a frequency input instead of a voltage divider and adc.

    Just some extra ideas to improve on a good concept:

    1). Software does not have to measure the frequency (overflows) for 100ms. You can generate an interrupt on the flanks of the 555 output and measure the time with a free running timer.
    2). This would also eliminate the need for the second input pin.
    3). Rc can also be removed if this algorithm is used.
    4). By connecting the button resistors in series you have smaller errors because of the tolerance of the resistors.
    5). System could easily be calibrated in software to detect the actual generated frequencys for further independence of the resistor tolerances.
    6). Robustness can be improved by only accepting frequency’s within small windows and rejecting all other frequencies.
    7). Key response can be a lot faster if for example 5 consecutive pulses of a 1kHz frequency are detected, you have a 5ms responce (Contact jitter will disrupt the consecutive pulse count).
    8). Maybe some of this is overkill for the design time and software size.

    I apologize to Ned for throwing code at everything 🙂

  • Pingback: Keypad input scanning by a 555 timer « Black Hat Security

  • Neat idea, and good writeup! I like this kind of thinking instead of the approach of throwing a uC and code at everything.

  • Pingback: Keypad input scanning by a 555 timer - Hack a Day

  • pls upload programe of 4 * 3 keapad

  • I am just wondering… Wouldn’t it be easier to just use different resistor dividers for each button and use an ADC channel to read the keys?

    • I agree that would be easier, and that’s why I am demonstrating the 555 based technique with PIC16F628A which doesn’t have any ADC channels.

  • Pingback: Electronics-Lab.com Blog » Blog Archive » 2-Wire Keypad Interface with a 555 Timer

  • I really enjoy these posts. Have you considered doing examples with more advanced PICs such as the PIC18F series or a dsPIC?

Leave a Reply

Your email address will not be published. Required fields are marked *