This is the second part of our numeric keypad tutorial – in which we use the larger keypads with four rows of four buttons. For example:

Again, the keypad looks like a refugee from the 1980s – however it serves a purpose. Notice that there are eight connections at the bottom instead of seven – the extra connection is for the extra column of buttons – A~D. This example again came from Futurlec. For this tutorial you will need the data sheet for the pinouts, so download it from here (.pdf).

To use this keypad is very easy, if you haven’t already done so, download the numeric keypad Arduino library from here, copy the “Keypad” folder into your ../arduino-002x/libraries folder, then restart the Arduino IDE.

Now for our first example – just to check all is well. From a hardware perspective you will need:

LiquidCrystal_I2Clcd(0x27,16,2);// set the LCD address to 0x27 for a 16 chars and 2 line display

constbyteROWS=4;//four rows

constbyteCOLS=4;//four columns

charkeys[ROWS][COLS]=

{{'1','2','3','A'},

{'4','5','6','B'},

{'7','8','9','C'},

{'*','0','#','D'}};

byterowPins[ROWS]={

5,4,3,2};//connect to the row pinouts of the keypad

bytecolPins[COLS]={

9,8,7,6};//connect to the column pinouts of the keypad

intcount=0;

Keypadkeypad=Keypad(makeKeymap(keys),rowPins,colPins,ROWS,COLS);

voidsetup()

{

Serial.begin(9600);

lcd.init();// initialize the lcd

lcd.backlight();// turn on LCD backlight

}

voidloop()

{

charkey=keypad.getKey();

if(key!=NO_KEY)

{

lcd.print(key);

Serial.print(key);

count++;

if(count==17)

{

lcd.clear();

count=0;

}

}

}

And our action video:

Now for another example – we will repeat the keypad switch from chapter 42 – but allow the letters into the PIN, and use the LCD instead of LEDs for the status. In the following example, the PIN is 12AD56. Please remember that the functions correctPIN() and incorrectPIN() are example functions for resulting PIN entry – you would replace these with your own requirements, such as turning something on or off:

LiquidCrystal_I2Clcd(0x27,16,2);// set the LCD address to 0x27 for a 16 chars and 2 line display

constbyteROWS=4;//four rows

constbyteCOLS=4;//four columns

charkeys[ROWS][COLS]=

{{'1','2','3','A'},

{'4','5','6','B'},

{'7','8','9','C'},

{'*','0','#','D'}};

byterowPins[ROWS]={

5,4,3,2};//connect to the row pinouts of the keypad

bytecolPins[COLS]={

9,8,7,6};//connect to the column pinouts of the keypad

Keypadkeypad=Keypad(makeKeymap(keys),rowPins,colPins,ROWS,COLS);

charPIN[6]={'1','2','A','D','5','6'};// our secret (!) number

charattempt[6]={

0,0,0,0,0,0};// used for comparison

intz=0;

voidsetup()

{

lcd.init();// initialize the lcd

lcd.backlight();// turn on LCD backlight

lcd.print(" Enter PIN...");

}

voidcorrectPIN()// do this if correct PIN entered

{

lcd.print("* Correct PIN *");

delay(1000);

lcd.clear();

lcd.print(" Enter PIN...");

}

voidincorrectPIN()// do this if incorrect PIN entered

{

lcd.print(" * Try again *");

delay(1000);

lcd.clear();

lcd.print(" Enter PIN...");

}

voidcheckPIN()

{

intcorrect=0;

for(intq=0;q<6;q++)

{

if(attempt[q]==PIN[q])

{

correct++;

}

}

if(correct==6)

{

correctPIN();

}else

{

incorrectPIN();

}

for(intzz=0;zz<6;zz++)// wipe attempt

{

attempt[zz]=0;

}

}

voidreadKeypad()

{

charkey=keypad.getKey();

if(key!=NO_KEY)

{

switch(key)

{

case'*':

z=0;

break;

case'#':

delay(100);// for extra debounce

lcd.clear();

checkPIN();

break;

default:

attempt[z]=key;

z++;

}

}

}

voidloop()

{

readKeypad();

}

Now let’s see it in action:

So now you have the ability to use twelve and sixteen-button keypads with your Arduino systems.

Have fun and keep checking into tronixstuff.com. Why not follow things on twitter, Google+, 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.

This is part one 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. 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

An Arduino Uno or 100% compatible board

A numeric keypad

An LCD of some sort. We will be using an I2C-interface model. If you are unsure about LCD usage, please see this tutorial

If you don’t have an LCD – that’s ok. After installing the keypad library, select File>Examples>Keypad>Examples>HelloKeypad in the IDE.

LiquidCrystal_I2Clcd(0x27,16,2);// set the LCD address to 0x27 for a 16 chars and 2 line display

// keypad type definition

constbyteROWS=4;//four rows

constbyteCOLS=3;//three columns

charkeys[ROWS][COLS]=

{{'1','2','3'},

{'4','5','6'},

{'7','8','9'},

{'*','0','#'}};

byterowPins[ROWS]={

5,4,3,2};//connect to the row pinouts of the keypad

bytecolPins[COLS]={

8,7,6};// connect to the column pinouts of the keypad

intcount=0;

Keypadkeypad=Keypad(makeKeymap(keys),rowPins,colPins,ROWS,COLS);

voidsetup()

{

lcd.init();// initialize the lcd

lcd.backlight();// turn on LCD backlight

}

voidloop()

{

charkey=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:

Arduino

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

// Example 42.2 - Six-digit keypad switch

// http://tronixstuff.com/tutorials > chapter 42

#include "Keypad.h"

constbyteROWS=4;//four rows

constbyteCOLS=3;//three columns

charkeys[ROWS][COLS]=

{{'1','2','3'},

{'4','5','6'},

{'7','8','9'},

{'*','0','#'}};

byterowPins[ROWS]={

5,4,3,2};//connect to the row pinouts of the keypad

bytecolPins[COLS]={

8,7,6};//connect to the column pinouts of the keypad

Keypadkeypad=Keypad(makeKeymap(keys),rowPins,colPins,ROWS,COLS);

charPIN[6]={'1','2','3','4','5','6'};// our secret (!) number

charattempt[6]={

0,0,0,0,0,0};// used for comparison

intz=0;

voidsetup()

{

pinMode(10,OUTPUT);

pinMode(11,OUTPUT);

incorrectPIN();

}

voidcorrectPIN()// do this if correct PIN entered

{

digitalWrite(11,LOW);

digitalWrite(10,HIGH);

}

voidincorrectPIN()// do this if incorrect PIN entered

{

digitalWrite(10,LOW);

digitalWrite(11,HIGH);

}

voidcheckPIN()

{

intcorrect=0;

for(intq=0;q<6;q++)

{

if(attempt[q]==PIN[q])

{

correct++;

}

}

if(correct==6)

{

correctPIN();

}else

{

incorrectPIN();

}

for(intzz=0;zz<6;zz++)// wipe attempt

{

attempt[zz]=0;

}

}

voidreadKeypad()

{

charkey=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++;

}

}

}

voidloop()

{

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 function incorrectPIN() in void setup to keep things locked down in case of a power failure or a system reset.

Have fun and keep checking into tronixstuff.com. Why not follow things on twitter, Google+, 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.

A more contemporary type of lock could be controlled electronically, for example by a keypad where the user enters a series of digits to cause something to happen. Such as the keypad on this dodgy $30 safe from Officeworks:

As you can see there is a button for each digit. You would think that this would be a good idea – however people can watch you enter the digits, or users can be silly enough to write down the combination somewhere. In some cases the more cunning monkeys have even placed cameras that can observe keypads to record people entering the combination. There must be a better way. Possibly! However in the meanwhile you can consider my idea instead – just have one button. Only one button – and the combination is made up of the time that elapses between presses of the button. There are many uses for such an odd lock:

A type of combination lock that controls an electric door strike, or activates a device of some sort;

A way of testing mind-hand coordination for skill, or the base of a painfully frustrating game;

Perhaps an interlock on motor vehicle to prevent drink driving. After a few drinks there’s no way you could get the timing right. Then again, after a double espresso or two you might have problems as well.

How does it work? Consider the following:

We measure the duration of time between each press of the button (in this case – delay 1~4). These delay times are then compared against values stored in the program that controls the lock. It is also prudent to allow for some tolerance in the user’s press delay – say plus or minus ten to fifteen percent. We are not concerned with the duration of each button press, however it is certainly feasible.

To create this piece of hardware is quite easy, and once again we will use the Arduino way of doing things. For prototyping and experimenting it is simple enough to create with a typical board such as a Uno or Eleven and a solderless breadboard – however to create a final product you could minimise it by using a bare-bones solution (as described here). Now let’s get started…

For demonstration purposes we have a normally-open button connected to digital pin 2 on our Arduino-compatible board using the 10k ohm pull down resistor as such:

The next thing to do is determine our delay time values. Our example will use five presses, so we measure four delays. With the following sketch, you can generate the delay data by pushing the button yourself – the sketch will return the delay times on the serial monitor:

Arduino

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

/*

Single-button combination lock

Delay Time data generation sketch - John Boxall June 2011

http://tronixstuff.com/projects | CC by-sa-nc

*/

intcount=0;

unsignedlonga[]={0,0,0,0,0,0};

unsignedlongdel[]={0,0,0,0,0};

voidsetup()

{

pinMode(2,INPUT);

Serial.begin(115200);

Serial.println("Ready...");

}

voiddataCapture()

{

a[count]=millis();

delay(500);// for button debounce, your value may differ

count++;

}

voiddisplayData()

{

// calcualate delays between keypresses

del[0]=a[1]-a[0];

del[1]=a[2]-a[1];

del[2]=a[3]-a[2];

del[3]=a[4]-a[3];

// display delay data for use in combination lock sketch

for(inta=0;a<4;a++)

{

Serial.println();

Serial.print("Delay ");

Serial.print(a);

Serial.print(" use ");

Serial.print(del[a]);

Serial.println(" ms");

}

Serial.println("- - - - - - - - -");

count=0;

}

voidloop()

{

if(digitalRead(2)==HIGH)

{

dataCapture();

}

if(count>4)

{

displayData();

}

}

So what’s going on the this sketch? Each time the button is pressed a reading of millis() is taken and stored in an array. [More on millis() in the tutorial]. Once the button has been pressed five times, the difference in time between each press is calculated and stored in the array del[]. Note the use of a 500 ms delay in the function dataCapture(), this is to prevent the button bouncing and will need to be altered to suit your particular button. Finally the delay data is then displayed on the serial monitor. For example:

The example was an attempt to count one second between each press. This example also illustrates the need to incorporate some tolerance in the actual lock sketch. With a tolerance of +/- 10% and delay values of one second, the lock would activate. With 5% – no. Etcetera.

Now for the lock sketch. Again it measures the millis() value on each button press and after five presses calculates the duration between each press. Finally in the function checkCombination() the durations are compared against the stored delay values (generated using the first sketch) which are stored in the array del[]. In our example lock sketch we have values of one second between each button press. The tolerance is stored as a decimal fraction in the variable tolerance; for example to have a tolerance of ten percent, use 0.1:

Arduino

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

/*

Single-button combination lock - John Boxall June 2011

http://tronixstuff.wordpress.com/projects | CC by-sa-nc

combilock2.pde

*/

intcount=0;

unsignedlonga[]={0,0,0,0,0};

unsignedlongb[]={0,0,0,0,0};

unsignedlongdel[]={1000,2000,3000,4000};// these are the values obtained from running combilock1.pde

When choosing your time delays, ensure they are larger than the value used for button debounce (the delay() function call) in the dataCapture() function. Notice the two functions success() and failure() – these will contain the results of what happens when the user successfully enters the combination or does not. For a demonstration of the final product, I have connected an LCD to display the outcomes of the entry attempts. You can download the sketch from here. The key used in this example is 1,2,3,4 seconds:

Although there are four buttons on the board used in the video, only one is used. Well I hope someone out there found this interesting or slightly useful…

In the meanwhile have fun and keep checking into tronixstuff.com. Why not follow things on twitter, Google+, subscribe for email updates or RSS using the links on the right-hand column? And join our friendly 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.