Monday, October 3, 2011

Tutorial: Arduino and Numeric Keypads

This is chapter forty-two of a series originally titled “Getting Started/Moving Forward with Arduino!” by John Boxall – a series of articles on the Arduino universe. The first chapter is here, the complete series is detailed here. Any files from tutorials will be found here.

Welcome back fellow arduidans!

This will be the first of two chapters that will examine another useful form of input – the numeric keypad; and some applications that hopefully may be of use.  Here is the example we will be working with:

It seems quite similar to the keypad from a 1980s-era Dick Smith Electronics cordless phone. Turning the keypad over we find seven pins:

Personally I like this type of connection, as it makes prototyping very easy using a breadboard – you just push it in. Looking at the back the pins are numbered seven to one (left to right). My example was from Futurlec of all places. You can also find types that have solder pads, such as this one. At this point you need to download the data sheet.pdf, as it shows the pinouts for the rows and columns. At first glance trying to establish a way of reading the keypad with the Arduino does seem troublesome – however the basic process is to ‘scan’ each row and then test if a button has been pressed.

If your keypad has more than seven pins or contacts – and the data sheet was not supplied, you will need to manually determine which contacts are for the rows and columns. This can be done using the continuity function of a multimeter (the buzzer). Start by placing one probe on pin 1, the other probe on pin 2, and press the keys one by one. Make a note of when a button completes the circuit, then move onto the next pin. Soon you will know which is which. For example, on the example keypad pins 1 and 5 are for button “1″, 2 and 5 for “4″, etc…

In the interest of keeping things simple and relatively painless we will use the numeric keypad Arduino library. Download the library from here, copy the “Keypad” folder into your ../arduino-002x/libraries folder, then restart the Arduino IDE.

Now for our first example. From a hardware perspective you will need

Connect the keypad to the Arduino in the following manner:
  • Keypad row 1 to Arduino digital 5
  • Keypad row 2 to Arduino digital 4
  • Keypad row 3 to Arduino digital 3
  • Keypad row 4 to Arduino digital 2
  • Keypad column 1 to Arduino digital 8
  • Keypad column 2 to Arduino digital 7
  • Keypad column 3 to Arduino digital 6
Now for the sketch. You can download it here

Example 42.1

/* Example 42.1 - Numeric keypad and I2C LCD http://tronixstuff.wordpress.com/tutorials > chapter 42 Uses Keypad library for Arduino  http://www.arduino.cc/playground/Code/Keypad  by Mark Stanley, Alexander Brevig */  #include "Keypad.h" #include "Wire.h" // for I2C LCD #include "LiquidCrystal_I2C.h" // for I2C bus LCD module http://bit.ly/eNf7jM LiquidCrystal_I2C lcd(0x27,16,2);  // set the LCD address to 0x27 for a 16 chars and 2 line display  // keypad type definition const byte ROWS = 4; //four rows const byte COLS = 3; //three columns char keys[ROWS][COLS] = {{'1','2','3'}, {'4','5','6'}, {'7','8','9'}, {'*','0','#'}}; byte rowPins[ROWS] = { 5, 4, 3, 2}; //connect to the row pinouts of the keypad byte colPins[COLS] = { 8, 7, 6}; // connect to the column pinouts of the keypad int count=0;  Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );  void setup() { lcd.init();          // initialize the lcd lcd.backlight(); // turn on LCD backlight }  void loop() { char key = keypad.getKey(); if (key != NO_KEY) { lcd.print(key); count++; if (count==17) { lcd.clear(); count=0; } } }

For the non-believers, here it is in action:


As you can see the library really does all the work for us. In the section below the comment “keypad type definition” we have defined how many rows and columns make up the keypad. Furthermore which digital pins connect to the keypad’s row and column pins. If you have a different keypad such as a 16-button version these will need to be modified. Furthermore you can also map out what the buttons will represent in the array “keys”. Then all of these variables are passed to the library in the function Keypad keypad = Keypad() etc.

Reading the buttons pressed is accomplished in void loop()… it reads the keypad by placing the current value into the char variable “key”. The if… statement tests if a button has been pressed. You can reproduce this loop within your own sketch to read values and then move forward to other functions. Let’s do that now in our next example.

Keypad Switch

Using our existing example hardware we can turn something on or off by using the keypad – replicating what can be found in some alarm systems and so on. Our goal with this example is simple – the systems waits for a PIN to be entered. If the PIN is correct, do something. If the PIN is incorrect, do something else. What the actions are can be up to you, but for the example we will turn on or off a digital output. This example is to give you a concept and framework to build you own ideas with.

The hardware is the same as the previous example but without the LCD. Instead, we have a 560 ohm resistor followed by an LED to GND from digital pin ten. Now for the sketch. You can download it from here.

Example 42.2

// Example 42.2 - Six-digit keypad switch // http://tronixstuff.wordpress.com/tutorials > chapter 42  #include "Keypad.h"  const byte ROWS = 4; //four rows const byte COLS = 3; //three columns char keys[ROWS][COLS] = {{'1','2','3'}, {'4','5','6'}, {'7','8','9'}, {'*','0','#'}}; byte rowPins[ROWS] = { 5, 4, 3, 2}; //connect to the row pinouts of the keypad byte colPins[COLS] = { 8, 7, 6}; //connect to the column pinouts of the keypad  Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );  char PIN[6]={'1','2','3','4','5','6'}; // our secret (!) number char attempt[6]={ 0,0,0,0,0,0}; // used for comparison int z=0;  void setup() { pinMode(10, OUTPUT); pinMode(11, OUTPUT); incorrectPIN(); }  void correctPIN() // do this if correct PIN entered { digitalWrite(11, LOW); digitalWrite(10, HIGH); }  void incorrectPIN() // do this if incorrect PIN entered { digitalWrite(10, LOW); digitalWrite(11, HIGH); }  void checkPIN() { int correct=0; for (int q=0; q<6; q++) { if (attempt[q]==PIN[q]) { correct++; } } if (correct==6) { correctPIN(); } else { incorrectPIN(); } for (int zz=0; zz<6; zz++) // wipe attempt { attempt[zz]=0; } }  void readKeypad() { char key = keypad.getKey(); if (key != NO_KEY) { switch(key) { case '*': z=0; break; case '#': delay(100); // for extra debounce checkPIN(); break; default: attempt[z]=key; z++; } } }  void loop() { readKeypad(); }

And the ubiquitous demonstration video:

This sketch is somewhat more complex. It starts with the usual keypad setting up and so on. We have two arrays, attempt and PIN. PIN holds the number which will successfully activate the switch, and attempt is used to store the key presses entered by the user. Users must press ‘*’ then the PIN then ‘#’ to activate the switch.

The comparison to check for accuracy is in the function checkPIN(). It compares the contents of PIN against attempt. If they match, the function correctPIN() is called. If the entered PIN is incorrect, the function incorrectPIN() is called. We also call the functionincorrectPIN() in void setup to keep things locked down in case of a power failure or a system reset.

You can now see that such a complex device can be harnessed very easily, and could have a variety of uses. In part two, we will look at the 16-digit keypad and more advanced applications and monitoring.

So have fun and keep checking into tronixstuff.com. Why not follow things on twitterGoogle+, subscribe  for email updates or RSS using the links on the right-hand column, or join our Google Group – dedicated to the projects and related items on this website. Sign up – it’s free, helpful to each other –  and we can all learn something.

No comments:

Post a Comment