Tuesday, July 25, 2017

Using Single Pin to Detect Multiple Push Buttons

Yes Guys, you read it right, and its very simple also. So in this post i will show you a method by which you can sense multiple push button, using single micro-controller pin, but that pin must be a Analog to Digital Converter pin of the micro-controller.

Concept
We will make a circuit, in such a way that for each push button press, we will get a different voltage value on the corresponding analog pin of the micro-controller, and then based on the converted digital values, the software will determine, which key is pressed.
So for this resistors will be placed in a sequential order (Resistor Ladder Network).

Proof of Concept
To prove this concept, we will take an Arduino Uno board and few resistors and seven push buttons, and we connect them in such a way that on each key press we get different voltage value.
The schematic diagram is shown below.
Schematic
As you can see clearly in above schematic, all the switches are directly connected to AN0 pin of the Arduino with a common pull-down resistor of 10k, so by default we will get Zero voltage on the micro-controller pin, 
In schematic Switch-1(Top one) is connected to 5V, so whenever it is pressed, we will get 5V on analog pin of micro-controller, pin similarly for other switches resistor divider network is formed in such a way that, on each push button press, we get a different voltage.
So I am using the following Resistor values for all the switches, you can you the ones you have with you.
Switch-1 --> No Resistor (Directly Connected to 5V)
Switch-2 --> 220 Ohm --> 4.892367V on Button Press
Switch-3 --> 470 Ohm --> 4.775549V on Button Press
Switch-4 --> 1Kohm    --> 4.545454V on Button Press
Switch-5 --> 4.7Kohm --> 3.401360V on Button Press
Switch-6 --> 10Kohm  --> 2.500000V on Button Press
Switch-7 --> 100Kohm--> 0.454545V on Button Press

So on each button press, we will get a particular voltage, which can be converted into digital value and checked with the desired values, but again as we know resistors has certain amount tolerance with them, which means that, 10k resistor is not exactly of 10k resistance, it can be 9.9k or 10.1k, depending on tolerance and accuracy.
So to compensate for that thing, we will take a threshold in code, to determine the actual key press, in my case I am using "10" threshold, as i am using simulation environment, it works perfectly, and I am sure on real hardware it will work, but it can be possible that you have to play with this threshold value.

The following video shows the demo of this post.


The Arduino code is as follow:

/* Main.ino file generated by New Project wizard
 *
 * Created:   Tue Jul 25 2017
 * Processor: Arduino Uno
 * Compiler:  Arduino AVR
 */

#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

/*
Push Buttons Voltage Values
SW1 -> 5V -> 1023
SW2 -> 5*(10k/(10k+220)) = 4.892367V -> 1001
SW3 -> 5*(10k/(10k+470)) = 4.775549V -> 977
SW4 -> 5*(10k/(10k+1k))  = 4.545454V -> 930
SW5 -> 5*(10k/(10k+4.7k))= 3.401360V -> 696
SW6 -> 5*(10k/(10k+10k)) = 2.500000V -> 512
SW7 -> 5*(10k/(10k+100k))= 0.454545V -> 93
*/
#define SW1_COUNT     1023u
#define SW2_COUNT     1001u
#define SW3_COUNT     977u
#define SW4_COUNT     930u
#define SW5_COUNT     696u
#define SW6_COUNT     512u
#define SW7_COUNT     93u

#define THRESHOLD     10u

#define SW1_UP_LIM    (SW1_COUNT+THRESHOLD)
#define SW1_LW_LIM    (SW1_COUNT-THRESHOLD)
#define SW2_UP_LIM    (SW2_COUNT+THRESHOLD)
#define SW2_LW_LIM    (SW2_COUNT-THRESHOLD)
#define SW3_UP_LIM    (SW3_COUNT+THRESHOLD)
#define SW3_LW_LIM    (SW3_COUNT-THRESHOLD)
#define SW4_UP_LIM    (SW4_COUNT+THRESHOLD)
#define SW4_LW_LIM    (SW4_COUNT-THRESHOLD)
#define SW5_UP_LIM    (SW5_COUNT+THRESHOLD)
#define SW5_LW_LIM    (SW5_COUNT-THRESHOLD)
#define SW6_UP_LIM    (SW6_COUNT+THRESHOLD)
#define SW6_LW_LIM    (SW6_COUNT-THRESHOLD)
#define SW7_UP_LIM    (SW7_COUNT+THRESHOLD)
#define SW7_LW_LIM    (SW7_COUNT-THRESHOLD)

void setup()
{
  lcd.begin(16, 2);
  delay(100);
  lcd.print("  Embedded Lab");
}

void loop()
{
  unsigned int adc_data = analogRead(A0);
  if ( adc_data >= SW1_LW_LIM && adc_data <= SW1_UP_LIM )
  {
    /*Switch-1 is Pressed*/
    lcd.setCursor(0, 1);
    lcd.print("SW1 is Pressed");
  }
  if ( adc_data >= SW2_LW_LIM && adc_data <= SW2_UP_LIM )
  {
    /*Switch-2 is Pressed*/
    lcd.setCursor(0, 1);
    lcd.print("SW2 is Pressed");
  }
  if ( adc_data >= SW3_LW_LIM && adc_data <= SW3_UP_LIM )
  {
    /*Switch-3 is Pressed*/
    lcd.setCursor(0, 1);
    lcd.print("SW3 is Pressed");
  }
  if ( adc_data >= SW4_LW_LIM && adc_data <= SW4_UP_LIM )
  {
    /*Switch-4 is Pressed*/
    lcd.setCursor(0, 1);
    lcd.print("SW4 is Pressed");
  }
  if ( adc_data >= SW5_LW_LIM && adc_data <= SW5_UP_LIM )
  {
    /*Switch-5 is Pressed*/
    lcd.setCursor(0, 1);
    lcd.print("SW5 is Pressed");
  }
  if ( adc_data >= SW6_LW_LIM && adc_data <= SW6_UP_LIM )
  {
    /*Switch-6 is Pressed*/
    lcd.setCursor(0, 1);
    lcd.print("SW6 is Pressed");
  }
  if ( adc_data >= SW7_LW_LIM && adc_data <= SW7_UP_LIM )
  {
    /*Switch-7 is Pressed*/
    lcd.setCursor(0, 1);
    lcd.print("SW7 is Pressed");
  }
}

No comments:

Post a Comment