]> git.piffa.net Git - arduino/blob - books/pdummies/APFD_Chapter8_Keypad_Entry_System/APFD_Chapter8_Keypad_Entry_System.ino
first commit
[arduino] / books / pdummies / APFD_Chapter8_Keypad_Entry_System / APFD_Chapter8_Keypad_Entry_System.ino
1 /* Arduino Projects for Dummies
2  * by Brock Craft 
3  *
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
8  *
9  * v0.1 30.04.2013
10  * Adapted from keypad reading technique by Michael Margolis
11 */
12
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
18
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
21
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
24
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
27
28 // The keyMap defines the character returned when the corresponding key is pressed
29 const char keyMap[numRows][numCols] = {
30   { '1', '2', '3' },
31   { '4', '5', '6' },
32   { '7', '8', '9' },
33   { '*', '0', '#' }
34 };
35
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
40
41 void setup()
42 {
43   if (DEBUG){Serial.begin(9600);} // If in DEBUG mode, start the serial port
44
45   // Prepare the MAX72xx to display 7-segment data (see datasheet)
46   // Format: sendCommand(command, value)
47   
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 
55
56   // Prepare the I/O pins for the keypad and the relay
57   pinMode(strikePin,OUTPUT);
58   
59   for (int row = 0; row < numRows; row++)
60   {
61     pinMode(rowPins[row],INPUT);       // Set row pins as input
62     digitalWrite(rowPins[row],HIGH);   // Turn on pull-up resistors on the processor
63   }
64   for (int column = 0; column < numCols; column++)
65   {
66     pinMode(colPins[column],OUTPUT);     // Set column pins as outputs for writing
67     digitalWrite(colPins[column],HIGH);  // Make all columns inactive
68   }
69   
70   // Clear the display (helps when debugging)
71   clearDisplay();                        
72 }
73
74 void loop()
75 {
76
77   char key = getKey();  // See if a key has been pressed 
78   codeBuffer[keypressCount]=key; // Add the key just pressed to the code Buffer
79
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: ");
87       Serial.println(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]);
98     }
99  
100     keypressCount++;   // Incrmement the number of keys that have been pressed
101  
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
107       } 
108       clearDisplay(); // Now clear the display
109       memset(codeBuffer, 0, 4); // Explicitly clear out the code buffer array
110       keypressCount=0;
111     }
112   }
113 }
114
115 // Returns the key pressed, or 0 if no key is pressed
116 char getKey()
117 {
118   char key = 0;                                  // 0 indicates no key pressed
119   for(int column = 0; column < numCols; column++)
120   {
121     digitalWrite(colPins[column],LOW);            // Activate the current column
122     for(int row = 0; row < numRows; row++)        // Scan all rows for a key press
123     {
124       if(digitalRead(rowPins[row]) == LOW)        // If a key is pressed...
125       {
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
129       }
130     }
131     digitalWrite(colPins[column],HIGH);           // De-activate the current column
132   }
133   return key;  // Return the key that pressed (or 0 if none)
134 }
135
136
137 void sendCommand(int command, unsigned char value)
138 {
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
143 }  
144
145 void clearDisplay(){
146   sendCommand(1, '_'); // Clears out all the digits. You can also use underscore 'o'
147   sendCommand(2, '_'); 
148   sendCommand(3, '_');
149   sendCommand(4, '_'); 
150 }
151
152 void unlock(){  
153   if(DEBUG){Serial.println("Unlocking Door.");}
154
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)
164 }