Connecting multiple tact switches on a single input pin of a microcontroller

Normally one tact switch requires one digital input pin of a microcontroller. Some designs implement keypad style multiplexing to get multiple switches on fewer inputs. However, there exist other techniques that allow you to connect many switches on a single input pin of a microcontroller. This tutorial demonstrates one such technique as applied to PIC12F683 microcontroller. In this example, there are four LEDs and four tact switches connected to the PIC12F683 microcontroller. While each LED is controlled through an individual I/O pin, the four switches are connected to one ADC input pin of the PIC12F683 microcontroller.

Connecting multiple tact switches to one input pin of PIC micro

Theory

The theory of connecting multiple switches on a single ADC input channel is very simple. One end of each switch is connected to the power supply voltage through an individual pull-up resistor, whereas the other end is grounded through a common resistor. When a switch is pressed, it creates a voltage divider network between the power supply and ground terminals. The value of the divided voltage can be made unique for all four switches by selecting different values of pull-up resistors. The voltage is then measured with the ADC to determine which switch has been pressed.

The circuit diagram shown below will probably give you a more clear picture of this technique. There are four switches (SW1-Sw4) connected to the AN0 input pin of the PIC12F683 microcontroller. Their one end is grounded through a common resistor R (=470 ?), whereas the other end is pulled high through different value resistors (R1‘-R4‘), giving rise to different values of the voltage divider output. The voltage drop across the resistor R is thus unique for each switch press and is measured through the AN0 ADC channel. When no switch is pressed, the AN0 pin is pulled low through R, and the ADC should ideally measure 0 V.

Circuit diagram for connecting four tact switches to one ADC input channel of PIC12F683

There are four LEDs (LED1-LED4) connected to pins GP1, GP2, GP4, and GP5 of the PIC12F683 microcontroller. They will be toggled ON and OFF through the four switches.

Calculation of resistor R’

The resistors R1‘ – R4‘ determine the value of the voltage divider output for each switch press. We know that each resistor value must be different to create an unique analog voltage output across R for each switch. But how should we select their values? You should keep in mind that the resistors do have certain tolerance values and their values also change with temperature. Therefore, you should provide enough gap between any two consecutive values of the voltage divider output to avoid any conflict. The best practice would be to implement an evenly spaced values of the voltage divider for all 4 switches. Remember that when you press a switch, you should not expect a precise value of the analog voltage across the resistor R. It would fluctuate little bit within a certain range which is defined by the resistors’ tolerance values, temperature, contact resistance of the switches, and the stability of the power supply voltage. So, in order to identify the switch, what you are actually looking at is a range of voltage that the voltage divider output falls in.

The table below shows the ranges of DN defined for all four switches, and the corresponding values for resistor R’. DN stands for digital number and represents the 10-bit A/D conversion output, which is proportional to the input analog voltage. Suppose, we define the DN range of switch SW1 as 100-300. Our goal is to find the appropriate value of R’ to ensure that when SW1 is pressed, the 10-bit A/D output will be always in between 100 and 300 count. The minimum value of R’ would correspond to the maximum value of the count, which is 300 for SW1. The equation to find R’ for DN = 100 is,

1024*R/(R+R’) = 100, where R = 470 ?.

This gives, R’ = 4342.8 ?. Similarly, for DN = 300, the value of R’ should be 1134.3 ?. Therefore, R’= 2.2 K would be an appropriate value for SW1. The rest of the R’ values for other switches are shown in the table below.

Table showing the appropriate values of R' for voltage divider network

Circuit setup on a breadboard

Software

The software involves few if checks to compare the A/D output with the predefined ranges to determine the switch that has been pressed.

   ADC_Value = ADC_Read(0);
   if(ADC_Value > 700) {                     // SW4 is pressed
     LED4 = ~LED4;
     Delay_250ms();
   }
   if(ADC_Value> 500 && ADC_Value < 700) {  // SW3 is pressed
     LED3 = ~LED3;
     Delay_250ms();
   }
   if(ADC_Value > 300 && ADC_Value < 500) {  // SW2 is pressed
     LED2 = ~LED2;
     Delay_250ms();
   }
   if(ADC_Value > 100 && ADC_Value < 300) {  // SW1 is pressed
     LED1 = ~LED1;
     Delay_250ms();
   }

Download complete mikroC source code and HEX file

Note: The microcontroller runs at 4.0 MHz using its internal clock source and the MCLR is disabled.

Each tact switch toggles an LED ON and OFF

Summary

A technique of interfacing multiple tact switches using a single ADC input pin was demonstrated using the PIC12F683 microcontroller. A digital input from four tact switches were individually read through the AN0 ADC channel and displayed it back on an LED. While this technique saves input pins and reduces the size, one downside of the design is detecting combination of switches. The calculations of R’ resistors become more complex in such a case. The resistor values must be chosen very carefully so that the voltage resulting from a switch combination is unique.

Related Posts

6 comments

  • Hi
    What happens if you press two buttons at once?
    Simon

  • Pingback: Connecting multiple tact switches on a single input pin of a microcontroller » Hallo, here is Pane!

  • I have yet to try an idea I’ve been kicking around that’s similar to this one, but instead of reading voltages with an ADC channel my idea is to use RC time constants to uniquely identify which button has been pressed. In the schematic above, that would mean replacing the 470 ohm resistor going to ground on the input side of the circuit with a capacitor–say 0.1uf–and then reading to time it takes to charge (and come up to the threshold voltage of a digital input) through different-value resistors.

    PicBasic Pro (and certainly other compiler languages) has a built-in “pot” function that works in this way, and it can be used on any digital input pin.

    Has anyone done this? I’m going to try it very soon.

    By the way, this is a wonderful and extremely useful site. Thanks for creating and maintaining it!

  • Try an R/2R ladder. With that you can easily get 8 inputs with only 2 different values of resistor. And you can read multiple inputs by the regular spaced voltage increments on an R/2R ladder. This is the same technique used by some DACs.

  • super good idea!

    thanks!

  • This is best technique i ever seen but will not it consume time in between two switch push ?

Leave a Reply

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