1 /* Arduino Projects for Dummies
4 * Chapter 8: Building a Keypad Entry System
5 * A system that uses a numeric keypad to actuate a solenoid
6 * Code is dsiplayed on a LED 7-segment common cathode display
7 * with a MAX72xx display driver IC
10 * Adapted from keypad reading technique by Michael Margolis
13 const int numberOfDigits = 4; // The number of digits in the 7-segment display
14 const int numRows = 4; // Number of rows in the keypad
15 const int numCols = 3; // Number of columns in the keypad
16 const int debounceTime = 20; // Number of milliseconds for switch to become stable
17 const int doorOpenTime = 5000; // How long you want the door strike to remain open
19 const int strikePin = 9; // The pin that actuates the relay for the door strike
20 const int slaveSelect = 10; // Pin used to enable the slave pin on the MAX72xx
22 char code[4]= {'1','2','3','4'}; // Set your code here
23 char codeBuffer[4]; // A buffer to store the code that is being entered
25 boolean DEBUG=true; // Set thus to true to pring out status messages to the serial port
26 int keypressCount=0; // A variable to count how many times a key has been pressed
28 // The keyMap defines the character returned when the corresponding key is pressed
29 const char keyMap[numRows][numCols] = {
36 // This array defines the Arduino Digital pins used for rows and columns
37 // for the keypad from Sparkfun (US) and Rapid (UK)
38 const int rowPins[numRows] = { 7, 2, 3, 5 }; // Digital Pins for Keypad Rows 0 through 3
39 const int colPins[numCols] = { 6, 8 ,4 }; // Digital Pins for Keypad Columns 0 through 2
43 if (DEBUG){Serial.begin(9600);} // If in DEBUG mode, start the serial port
45 // Prepare the MAX72xx to display 7-segment data (see datasheet)
46 // Format: sendCommand(command, value)
48 SPI.begin(); // initialize SPI interface to talk to the MAX72xx
49 pinMode(slaveSelect, OUTPUT); // Set the SPI slave pin for output
50 sendCommand(12,1); // Set to normal mode (default is shutdown mode);
51 sendCommand(15,0); // Display test off
52 sendCommand(10,8); // Set to medium brightness (range is 0-15)
53 sendCommand(11, numberOfDigits); // 7221 digit scan limit command
54 sendCommand(9,255); // Set "Decode mode" true. Provides digits: 0-9, H, E, L, P, -, blank
56 // Prepare the I/O pins for the keypad and the relay
57 pinMode(strikePin,OUTPUT);
59 for (int row = 0; row < numRows; row++)
61 pinMode(rowPins[row],INPUT); // Set row pins as input
62 digitalWrite(rowPins[row],HIGH); // Turn on pull-up resistors on the processor
64 for (int column = 0; column < numCols; column++)
66 pinMode(colPins[column],OUTPUT); // Set column pins as outputs for writing
67 digitalWrite(colPins[column],HIGH); // Make all columns inactive
70 // Clear the display (helps when debugging)
77 char key = getKey(); // See if a key has been pressed
78 codeBuffer[keypressCount]=key; // Add the key just pressed to the code Buffer
80 if( key != 0) { // if the character is not 0 then
81 sendCommand(keypressCount+1, key); // Sends the character to the display
82 // it's a valid key press
83 if (DEBUG){ // Used to print values for testing and debugging
84 Serial.print("Digit ");
85 Serial.println(keypressCount);
86 Serial.print("Got key: ");
88 Serial.print("Buffer: ");
89 Serial.print(codeBuffer[0]); // Print the contents of the code buffer
90 Serial.print(codeBuffer[1]);
91 Serial.print(codeBuffer[2]);
92 Serial.println(codeBuffer[3]);
93 Serial.print("Code: "); // Print the contents of the code array
94 Serial.print(code[0]);
95 Serial.print(code[1]);
96 Serial.print(code[2]);
97 Serial.println(code[3]);
100 keypressCount++; // Incrmement the number of keys that have been pressed
102 if (keypressCount==4){ // If four keys have been pressed, test whether code matches
103 delay(500); // wait a moment so that the forth digit can be seen on the display
104 if (memcmp(codeBuffer, code,4)==0) { // Compare to see if there is a match
105 if(DEBUG){Serial.println("MATCH!");} // If in DEBUG mode, report this
106 unlock(); // If there is a match, unlock
108 clearDisplay(); // Now clear the display
109 memset(codeBuffer, 0, 4); // Explicitly clear out the code buffer array
115 // Returns the key pressed, or 0 if no key is pressed
118 char key = 0; // 0 indicates no key pressed
119 for(int column = 0; column < numCols; column++)
121 digitalWrite(colPins[column],LOW); // Activate the current column
122 for(int row = 0; row < numRows; row++) // Scan all rows for a key press
124 if(digitalRead(rowPins[row]) == LOW) // If a key is pressed...
126 delay(debounceTime); // Debounce
127 while(digitalRead(rowPins[row]) == LOW) ; // Wait for key to be released
128 key = keyMap[row][column]; // Store which key was pressed
131 digitalWrite(colPins[column],HIGH); // De-activate the current column
133 return key; // Return the key that pressed (or 0 if none)
137 void sendCommand(int command, unsigned char value)
139 digitalWrite(slaveSelect,LOW); // Chip select is active when pin is LOW
140 SPI.transfer(command); // Send the First byte of data to the MAX72xx
141 SPI.transfer(value); // Send the Second byte of data
142 digitalWrite(slaveSelect,HIGH); // Release the chip - signals end of data transfer
146 sendCommand(1, '_'); // Clears out all the digits. You can also use underscore 'o'
153 if(DEBUG){Serial.println("Unlocking Door.");}
155 // Display welcome message "HI"
156 // Other characters available are: j,k,l,m,n,o = -,e,h,l,p,blank
157 sendCommand(1, 'o'); // Blank
158 sendCommand(2, 'l'); // Letter H
159 sendCommand(3, '1'); // Letter I
160 sendCommand(4, 'o'); // Blank
161 digitalWrite(strikePin,HIGH); // Activate the relay (unlock the door strike)
162 delay(doorOpenTime); // Gives you time to open up the door
163 digitalWrite(strikePin,LOW); // Deactivate the relay (and lock door again)