Monday, January 10, 2011

Tutorial: Using analog input for multiple buttons

This is chapter twenty-five of a series originally titled “Getting Started/Moving Forward with Arduino!” by John Boxall – A tutorial on the Arduino universe.

The first chapter is here, the complete series is detailed here. Please note from November 1, 2010 files from tutorials will be found here.

Welcome back fellow arduidans!

The purpose of this article is demonstrate how you can read many push buttons (used for user-input) using only one analog input pin. This will allow you to save digital I/O pins for other uses such as LCD modules and so on. Hopefully you recall how we used analogRead() in chapter one, and how we used a potentiometer to control menu options in exercise 10.1.

To recap, an analog input pin is connected to an analog to digital (ADC) converter in our Arduino’s microcontroller. It has a ten bit resolution, and can return a numerical value between 0 and 1023 which relates to an analog voltage being read of between 0 and 5 volts DC.

Example 25.1

With this sketch:

/*  Example 25.1 - Demonstrating analogRead()
http://tronixstuff.com/tutorials > chapter 25
CC by-sa-nc*/
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 2, 3);
int a=0;
void setup()
{
lcd.begin(20, 4);
pinMode(A5, INPUT);
}
void loop()
{
a = analogRead(5);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("  analogRead() ");
lcd.setCursor(0,1);
lcd.print("  value is :");
lcd.print(a);
delay(250);
}

and in the following short video, we have demonstrated the possible values returned by measuring the voltage from the centre pin of a 10k ohm potentiometer, which is connected between 5V and GND:

As the potentiometer’s resistance decreases, the value returned by analogRead() increases. Therefore at certain resistance values, analogRead() will return certain numerical values. So, if we created a circuit with (for example) five buttons that allowed various voltages to be read by an analog pin, each voltage read would cause analogRead() to return a particular value. And thus we can read the status of a number of buttons using one analog pin.

Example 25.2

The following circuit is an example of using five buttons on one analog input, using the sketch from example 25.1:

And here it is in action:

Some of you may have notice that when the right-most button is pressed, there is a direct short between A5 and GND. When that button is depressed, the current flow is less than one milliamp. Also note that you don’t have to use A5, any analog pin is fine.

As shown in the previous video clip, the values returned by analogRead() were:

  • 1023 for nothing pressed (default state)
  • 454 for button one
  • 382 for button two
  • 291 for button three
  • 168 for button four
  • 0 for button five

So for our sketches to react to the various button presses, they need to make decisions based on the value returned by analogRead(). Keeping all the resistors at the same value gives us a pretty fair spread between values, however the values can change slightly due to the tolerance of resistors andparasitic resistance in the circuit.

So after making a prototype circuit, you should determine the values for each button, and then have your sketch look at a range of values when reading the analog pin. Doing so becomes more important if you are producing more than one of your project, as resistors of the same value from the same batch can still vary slightly.

Example 25.3

Using the circuit from example 25.2, we will use a function to read the buttons and return the button number for the sketch to act upon.

/*  Example 25.3 - Digital buttons with analog input  http://tronixstuff.com/tutorials > chapter 25 CC by-sa-nc */ #include <LiquidCrystal.h> LiquidCrystal lcd(12, 11, 5, 4, 2, 3); int a=0; void setup() {
lcd.begin(20, 4);
pinMode(A5, INPUT); // sets analog pin for input }  int readButtons(int pin) // returns the button number pressed, or zero for none pressed // int pin is the analog pin number to read {
int b,c = 0;
c=analogRead(pin); // get the analog value  if (c>1000)
{
b=0; // buttons have not been pressed
}   else
if (c>440 && c<470)
{
b=1; // button 1 pressed
}     else
if (c<400 && c>370)
{
b=2; // button 2 pressed
}       else
if (c>280 && c<310)
{
b=3; // button 3 pressed
}         else
if (c>150 && c<180)
{
b=4; // button 4 pressed
}           else
if (c<20)
{
b=5; // button 5 pressed
}
return b; } void loop() {
a=readButtons(5);
lcd.clear();
if (a==0) // no buttons pressed
{
lcd.setCursor(0,1);
lcd.print("Press a button");
}   else
if (a>0) // someone pressed a button!
{
lcd.setCursor(0,2);
lcd.print("Pressed button ");
lcd.print(a);
}
delay(1000); // give the human time to read LCD }

And now our video demonstration:

So now you have a useful method for receiving input via buttons without wasting many digital input pins. I hope you found this article useful or at least interesting. Stay tuned for upcoming Arduino tutorials by subscribing to the blog, RSS feed (top-right) or joining our Google Group.

If you have any questions about the processes or details in this article, please ask in our Google Group – dedicated to the projects and related items on this website. Sign up – it’s free, there is the odd competition or give-away –  and we can all learn something.

Otherwise, have fun, stay safe, be good to each other – and make something!

No comments:

Post a Comment