Arduino Ladder · Bozoma Innovation Hub

Band 3  ·  Combination Lock

Swap  The keypad lock

A four-digit code on a real keypad. Sixteen buttons on eight wires, and the trick that makes that possible.

Time
100 min
You need
4×4 keypad, 2 LEDs, 2 resistors, buzzer, 15 jumper wires
At once
One per keypad module
Before this
Finish Band 3 up to Part 10. This replaces the four-button lock in Part 11. Test with b3_07_keypad_test.ino before you load the lock.

Sketches for this project

Every file opens with a plain-English header saying what it does and how to wire it, hole by hole.

Why

Sixteen buttons on eight wires

The four-button lock in Band 3 uses four buttons on four pins. One each. That does not scale, and a keypad is where it stops working.

Sixteen keys, one pin each, would be sixteen pins. An UNO has eighteen usable. You would have a keypad and nothing else.

So a keypad does something cleverer, and it is the same trick that is hiding inside every multi-digit display in the drawer, including the one in Band 7. It is worth understanding rather than accepting.

How it works, in one paragraph

The keys are in a grid: four rows of four. Every key sits where one row wire crosses one column wire, and pressing it joins that row to that column.

So the board switches on one row at a time and looks at all four columns. If column 3 answers while row 2 is switched on, the key at row 2 column 3 is down. It does that about a hundred times a second, and to you it looks instant.

Four rows plus four columns is eight wires for sixteen keys. Add a row and a column and you get twenty-five keys on ten wires. That is what makes it worth the cleverness.

You already know this shape. It is Band 3's loop over four buttons, done in two directions at once.

Build

Wire it

40 min
+ − − + j i h g f e d c b a 1 5 10 15 20 25 30 35 40 45 USB ARDUINO UNO 4x4 keypad 4x4 keypad + + 220 220 + + 220 220 + + buzzer buzzer a1 a1 a20 a20 a21 a21 a22 a22 a23 a23 a24 a24 a25 a25 a26 a26 a27 a27 a3 a3 a4 a4 a40 a40 a42 a42 a5 a5 a7 a7 a8 a8 b1 b1 b20 b20 b21 b21 b22 b22 b23 b23 b24 b24 b25 b25 b26 b26 b27 b27 b3 b3 b4 b4 b40 b40 b42 b42 b5 b5 b7 b7 b8 b8 SCL SCL SDA SDA AREF AREF GND GND 13 13 12 12 11 11 10 10 9 9 8 8 7 7 6 6 5 5 4 4 3 3 2 2 1 1 0 0 IOR IOR RST RST 3V3 3V3 5V 5V GND GND GND GND VIN VIN A0 A0 A1 A1 A2 A2 A3 A3 A4 A4 A5 A5
Sixteen buttons on eight wires. The keypad's own pins fill row a, so every jumper goes into row b.
Which rail pairYour board has two + rails and two − rails, one pair along each long edge, and on most boards the two pairs are not joined to each other. On this page, “the rail” always means the pair along the bottom edge, nearest row a, the same pair Band 3 uses, and the one your parts sit next to. Put every rail wire on that pair and it works; split them across both and nothing lights, with nothing visibly wrong.
Before you startUSB unplugged, and strip the board right back to bare. The four buttons, both lights, the buzzer and every single wire come off. When you have finished, nothing at all is in Arduino pins 2 to 12.

This is not tidiness. The keypad needs eight pins in a row, and Band 3's lock had its green light on pin 8, its red on pin 9 and its buzzer on pin 10, which is exactly where three of the keypad's eight wires are going. Leave them and you have two wires in one pin three times over, which the course forbids for good reason: the two fight each other and neither works. The table below rebuilds the lights and the buzzer in new holes on new pins.

The keypad

Eight pins along one edge. Hold it with the buttons facing you and the right way up, so 1 2 3 A is the top row. The pins are then, reading left to right:

First, how the eight pins actually reach the ArduinoThe keypad's pins are a male header, and so are both ends of an ordinary jumper wire, so they will not join to each other. Two ways round it, and both work.

If you have female-to-male wires (a socket at one end, a pin at the other): push the socket end onto the keypad pin and the pin end into the Arduino. Eight wires, done.

If you do not: push the keypad's eight pins into the breadboard, into row a, one pin per column: a20, a21, a22, a23, a24, a25, a26, a27, with the leftmost pin in a20. Then run an ordinary jumper from the row b hole in each of those columns up to the Arduino pin the table names: b20, b21, b22, b23, b24, b25, b26, b27. Eight columns, eight wires, in that order. That is eight wires as well, and it holds the keypad steady while you press it, which is worth something.
PositionWhat it isArduino pin
1st, leftmostRow 1 — the 1 2 3 A row9
2ndRow 2 — the 4 5 6 B row8
3rdRow 3 — the 7 8 9 C row7
4thRow 4 — the * 0 # D row6
5thColumn 1 — the 1 4 7 * column5
6thColumn 2 — the 2 5 8 0 column4
7thColumn 3 — the 3 6 9 # column3
8th, rightmostColumn 4 — the A B C D column2
No resistors, no power wiresA keypad is nothing but switches. It has no VCC and no GND pin, and if you go looking for one you will waste ten minutes. The Arduino's internal pull-ups do the rest, exactly as they did for the four buttons.

The rest

PartHolesWiring
Green lightlong b3, short b4Resistor a3 to a1; wire b1 to pin 10; wire a4 to − rail
Red lightlong b7, short b8Resistor a7 to a5; wire b5 to pin 11; wire a8 to − rail
Buzzerlong b40, short b42Wire a40 to pin 12; wire a42 to − rail. No resistor.
If the buzzer's legs are set too far apart to reach b40 and b42, use b40 and b43 instead and move the − rail wire to a43. Buzzers are made to two different leg spacings and both are common. Do not force the legs; they snap.
Ground—One wire from the − rail to a GND pin

The pin wires go in b1 and b5, not a1 and a5, because the resistor legs are already in those holes and a hole takes one leg only. Same column, same connection.

If your buzzer is the active kindThe sketch uses tone, which an active buzzer cannot follow. It will still beep, at its own single note, and the lock works perfectly. If you would rather it were exact, replace each tone(buzzerPin, ...) with digitalWrite(buzzerPin, HIGH) and each noTone(buzzerPin) with digitalWrite(buzzerPin, LOW). Run id_01_which_buzzer.ino if you are not sure which you have.

Install one library, then test in two stages

Install the Keypad library. Tools, then Manage Libraries, search for Keypad, and install the one by Mark Stanley and Alexander Brevig. Once, on one machine.

You should seeThe word INSTALLED next to it in the list.
If that computer has no internetLibrary Manager will simply find nothing, and the sketch will refuse to compile with a message ending No such file or directory. Nothing is broken. On any machine that does have a connection, search for the library, download it as a .zip, and carry it here on a phone or a USB stick. Then use Sketch, then Include Library, then Add .ZIP Library, and point it at the file. If your kit came with a folder of libraries on a stick or a disc, it is already in there. Do this before you wire anything, because without the library nothing you build can be tested.

Stage one: prove every key works, before the lock is anywhere near it. Upload b3_07_keypad_test.ino, which does nothing at all but print, and open the serial monitor at 9600. Press every one of the sixteen keys in turn, reading along the rows.

Why a separate sketch, and not just the lockThe lock makes a decision after every four keys. Test sixteen keys on it and every fourth press sets off a wrong-code buzz, and the third of those locks you out for ten seconds. You would come away certain that three of your keys were dead. Test one thing at a time is not a slogan; this is what it buys you.
You should seekey 1, key 2, key 3, key A, and so on, matching what is printed on the key you pressed. All sixteen.
If whole rows or columns are deadA row or column wire is in the wrong place, and this is the usual fault. Count the pins from the left again, with the keypad the right way up. Rows first, then columns.
If the wrong character prints, but consistentlyTwo of your eight wires are swapped. Same fix: count from the left.
If nothing prints at allCheck the serial monitor is at 9600 and the library installed. A keypad needs no power, so there is nothing else to check.

Stage two: use the lock. The secret is 1 9 4 2. Type it.

You should seeGreen light for two seconds, with a beep. Two rising notes if your buzzer is the passive kind, or one note twice if it is the active kind Band 3's parts list named, because an active buzzer only knows one note. Now type something wrong: red light and two low buzzes. Do that three times in a row and the red light flashes for ten seconds and nothing you press does anything.
If it unlocks on the wrong codeLook at matchesSecret. It compares with !=, meaning “is different from”, and it returns false the moment it finds one digit that does not match. If you have edited that function, check you have not turned != into = by accident: = is an instruction to change the value, not a question about it, and the compiler will accept it without a word. That is exactly the trap Band 3 Part 7 set for you.
Look closer

Watch the scanning happen

25 min

The library hides the row-and-column trick. Here is how to see it.

Take one wire out
  1. Upload b3_07_keypad_test.ino again first. You are about to press twelve keys in a row, and on the lock that is three wrong codes, so the third one would lock you out for ten seconds in the middle of the experiment.
  2. Unplug the USB. Take the row 1 wire out of pin 9. Leave everything else exactly as it is.
  3. Plug back in and try every key.
You should see1, 2, 3 and A are dead. The other twelve keys work perfectly. One wire, one whole row.
  1. Put row 1 back. Now take the column 1 wire out of pin 5.
You should see1, 4, 7 and * are dead. A different four, in a line the other way.

Only 1 was dead both times, because 1 is where row 1 crosses column 1. That is the grid, and you have just proved it exists without opening anything.

The guard you have seen before

if (pressCount < 4) {
  entered[pressCount] = key;
  pressCount = pressCount + 1;
}

This is the same guard as Band 3 Part 11, for the same reason. entered holds four things, so its positions are 0, 1, 2 and 3. Without the check, a fifth key would be written to entered[4], which is outside the list, and the lock would jam permanently.

Two questions for your log
  1. The * key clears what you have typed. Find the two lines that do it, and say why startAgain sets every position back to 0 rather than only resetting pressCount.
  2. The four-button lock had to do edge detection: notice the moment a button goes down, not that it is down. This sketch has no edge detection anywhere. Why not?
Check your answers

1. Strictly, only pressCount has to change, because nothing reads past it. Clearing the rest is a habit worth having: it means that if you ever add code that does look at the whole list, it cannot find yesterday's leftovers there. The same reason Band 1 writes all three lights in every state.

2. Because pad.getKey() already does it. It hands back a key once, at the moment it goes down, and then NO_KEY until something changes. The library is doing the edge detection and the debouncing for you. Worth knowing, because when you meet an input without a library you will have to do both yourself, and now you know what “both” means.

Change it

Make it yours

35 min
Bronze
Change the secret, and change its length from four digits to six. Count how many places you had to edit. If it was more than two, look for the number 4 written somewhere it should have been a name.
Silver
Let the user set their own code: press # twice in a row, then type four keys, and that becomes the new secret until the power goes off. Then say in one sentence what happens to it when the power goes off, and why. (If you would rather it were a two-second hold, you cannot do it with getKey, because that only ever tells you the moment a key goes down. The library has setHoldTime and getState for exactly this, and its own CustomKeypad example, installed on your machine alongside it, shows them working. That is a real piece of research and it is worth the hour.)
Gold
Make the lockout get longer each time: ten seconds, then thirty, then two minutes. Do it without ever using delay, so that keys pressed during a lockout can still be seen and ignored deliberately rather than missed. This is Band 5 arriving early, and it is the honest way to write a lockout.
A hint for BronzeThere are six: the size of secret, the size of entered, the loop that compares them, the loop that clears them, the guard that stops a fifth key being stored, and the test that decides the entry is finished. Find all six before you change any of them. A single const int CODE_LENGTH = 4; at the top fixes all six at once, and that is Band 1's variables lesson paying off two bands later.
Done

You still owe Band 3 the same evidence

This Swap replaces the four-button lock. To claim Band 3 you still need:

  • A video of a correct entry, a wrong entry, and the lockout
  • Your build log, including which wires the row-and-column ordering caught you on
  • Your answers to the two questions above, and your list of hesitations: the places where somebody using it stopped, guessed, or pressed the wrong thing. Watch another person if there is one. If you are on your own, film yourself using it while thinking aloud, then watch it back tomorrow, when you have forgotten what you meant. Both work. Building it and never watching anybody use it is the only option that does not.
  • Your completed edge-detection table from Part 12a, and your number from Bronze
  • The sentence “not pressed is 1, pressed is 0” in your glossary
  • Five or six correct answers in Part 15, the Check yourself questions, including question 6

The Check yourself questions are about INPUT_PULLUP, edge detection, debounce and the one-equals-sign trap, and this build hides the first three of those behind a library. Answer them anyway. If you can, you have understood the band; if you cannot, go back and wire two loose buttons for twenty minutes, because the library will not always be there.

Ship it

One video under sixty seconds, and one post of five lines. You built something different from the person next to you, so your video is the one nobody else in the room can post. Say in the post which build you chose and why — that choice is itself worth a line.

The four shots: three seconds of the thing still, fifteen of you doing something to it, fifteen of it responding all the way to the end, and ten of your measurement or the thing that went wrong first.

Show your work has the template and the three checks to make before anything goes public. Tag it #BozomaBuilds.