1 /* Arduino Projects for Dummies
4 * Chapter 8: Building a Keypad Entry System + RFID
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
15 const int numberOfDigits = 4; // The number of digits in the 7-segment display
16 const int numRows = 4; // Number of rows in the keypad
17 const int numCols = 3; // Number of columns in the keypad
18 const int debounceTime = 20; // Number of milliseconds for switch to become stable
19 const int doorOpenTime = 5000; // How long you want the door strike to remain open
21 const int strikePin = 9; // The pin that actuates the relay for the door strike
22 const int slaveSelect = 10; // Pin used to enable the slave pin on the MAX72xx
23 const int RFIDResetPin = 12; // This pin tells the reader to read again
25 // Make a list of your RFID tags here.
26 // If you don't know them, leave at least one in place as starter
27 // a starter ID and delete it later. Otherwise the code will break.
28 // (You always have to have something to compare the read tags to.)
30 char tag1[13] = "4B00DDBF9FB6"; // Your scanned tag ID goes here
31 char tag2[13] = "010203AABBCC"; // these are example Iag IDs only
32 char tag3[13] = "010203AABBDD"; // these are example Iag IDs only
35 char code[4]= {'1','2','3','4'}; // Set your code here
36 char codeBuffer[4]; // A buffer to store the code that is being entered
38 boolean DEBUG=true; // Set thus to true to pring out status messages to the serial port
39 int keypressCount=0; // A variable to count how many times a key has been pressed
41 // The keyMap defines the character returned when the corresponding key is pressed
42 const char keyMap[numRows][numCols] = {
49 // This array defines the Arduino Digital pins used for rows and columns
50 // for the keypad from Sparkfun (US) and Rapid (UK)
51 const int rowPins[numRows] = { 7, 2, 3, 5 }; // Digital Pins for Keypad Rows 0 through 3
52 const int colPins[numCols] = { 6, 8 ,4 }; // Digital Pins for Keypad Columns 0 through 2
56 if (DEBUG){Serial.begin(9600);} // If in DEBUG mode, start the serial port
58 // Prepare the MAX72xx to display 7-segment data (see datasheet)
59 // Format: sendCommand(command, value)
61 SPI.begin(); // initialize SPI interface to talk to the MAX72xx
62 pinMode(slaveSelect, OUTPUT); // Set the SPI slave pin for output
63 sendCommand(12,1); // Set to normal mode (default is shutdown mode);
64 sendCommand(15,0); // Display test off
65 sendCommand(10,8); // Set to medium brightness (range is 0-15)
66 sendCommand(11, numberOfDigits); // 7221 digit scan limit command
67 sendCommand(9,255); // Set "Decode mode" true. Provides digits: 0-9, H, E, L, P, -, blank
69 // Prepare the I/O pins for the keypad and the relay
70 pinMode(strikePin,OUTPUT);
72 for (int row = 0; row < numRows; row++)
74 pinMode(rowPins[row],INPUT); // Set row pins as input
75 digitalWrite(rowPins[row],HIGH); // Turn on pull-up resistors on the processor
77 for (int column = 0; column < numCols; column++)
79 pinMode(colPins[column],OUTPUT); // Set column pins as outputs for writing
80 digitalWrite(colPins[column],HIGH); // Make all columns inactive
83 // Clear the display (helps when debugging)
86 // Set up the RFID reader
87 pinMode(RFIDResetPin, OUTPUT); // Tells the reader to start again
88 digitalWrite(RFIDResetPin, HIGH); // Make it ready to read
89 Serial.println("Ready."); // Advise the consoe we are ready.
95 char key = getKey(); // See if a key has been pressed
96 codeBuffer[keypressCount]=key; // Add the key just pressed to the code Buffer
98 if( key != 0) { // if the character is not 0 then
99 sendCommand(keypressCount+1, key); // Sends the character to the display
100 // it's a valid key press
101 if (DEBUG){ // Used to print values for testing and debugging
102 Serial.print("Digit ");
103 Serial.println(keypressCount);
104 Serial.print("Got key: ");
106 Serial.print("Buffer: ");
107 Serial.print(codeBuffer[0]); // Print the contents of the code buffer
108 Serial.print(codeBuffer[1]);
109 Serial.print(codeBuffer[2]);
110 Serial.println(codeBuffer[3]);
111 Serial.print("Code: "); // Print the contents of the code array
112 Serial.print(code[0]);
113 Serial.print(code[1]);
114 Serial.print(code[2]);
115 Serial.println(code[3]);
118 keypressCount++; // Incrmement the number of keys that have been pressed
120 if (keypressCount==4){ // If four keys have been pressed, test whether code matches
121 delay(500); // wait a moment so that the forth digit can be seen on the display
122 if (memcmp(codeBuffer, code,4)==0) { // Compare to see if there is a match
123 if(DEBUG){Serial.println("MATCH!");} // If in DEBUG mode, report this
124 unlock(); // If there is a match, unlock
126 clearDisplay(); // Now clear the display
127 memset(codeBuffer, 0, 4); // Explicitly clear out the code buffer array
132 // NOW SEE IF THE RFID READER HAS DETECTED A TAG
134 Serial.println("Looking for a tag..."); // Say what we are currently doing
135 char tagString[13]; // Create an array to hold the tag we are reading
136 int index = 0; // A utility counter to track where we are in tagstring[]
137 boolean reading = false; // Stores whether we have a reading
139 while(Serial.available()){ // If there is a serial connection...
141 int readByte = Serial.read(); // Read next available byte
142 if(readByte == 2) reading = true; // 2 indicates the begining ofa tag
143 if(readByte == 3) reading = false; // 3 indicates the end of tag
145 // If there is a reading and it's not the beginning or end, store it
146 if(reading && readByte != 2 && readByte != 10 && readByte != 13){
148 tagString[index] = readByte; // Store the tag at the index point
149 index ++; // increment where we are in the storage array
153 checkTag(tagString); // Check if it is a match
154 clearTag(tagString); // Clear the char array of all values
155 resetReader(); // Reset the RFID reader
158 // Returns the key pressed, or 0 if no key is pressed
161 char key = 0; // 0 indicates no key pressed
162 for(int column = 0; column < numCols; column++)
164 digitalWrite(colPins[column],LOW); // Activate the current column
165 for(int row = 0; row < numRows; row++) // Scan all rows for a key press
167 if(digitalRead(rowPins[row]) == LOW) // If a key is pressed...
169 delay(debounceTime); // Debounce
170 while(digitalRead(rowPins[row]) == LOW) ; // Wait for key to be released
171 key = keyMap[row][column]; // Store which key was pressed
174 digitalWrite(colPins[column],HIGH); // De-activate the current column
176 return key; // Return the key that pressed (or 0 if none)
180 void sendCommand(int command, unsigned char value)
182 digitalWrite(slaveSelect,LOW); // Chip select is active when pin is LOW
183 SPI.transfer(command); // Send the First byte of data to the MAX72xx
184 SPI.transfer(value); // Send the Second byte of data
185 digitalWrite(slaveSelect,HIGH); // Release the chip - signals end of data transfer
189 sendCommand(1, '_'); // Clears out all the digits. You can also use underscore 'o'
196 if(DEBUG){Serial.println("Unlocking Door.");}
198 // Display welcome message "HI"
199 // Other characters available are: j,k,l,m,n,o = -,e,h,l,p,blank
200 sendCommand(1, 'o'); // Blank
201 sendCommand(2, 'l'); // Letter H
202 sendCommand(3, '1'); // Letter I
203 sendCommand(4, 'o'); // Blank
204 digitalWrite(strikePin,HIGH); // Activate the relay (unlock the door strike)
205 delay(doorOpenTime); // Gives you time to open up the door
206 digitalWrite(strikePin,LOW); // Deactivate the relay (and lock door again)
209 void checkTag(char tag[]){
211 // Compare this tag to the stored tags
212 if(strlen(tag) == 0) return; // If there's nothing here, do nothing
214 if(compareTag(tag, tag1)){ // If read tag matches tag1, do this
217 else if(compareTag(tag, tag2)){ // If read tag matches tag2, do this
220 else if(compareTag(tag, tag3)){ // If read tag matches tag3, do this
222 } else { // If it doesn't match the list of tags...
223 Serial.println("New tag found: ");
224 Serial.println(tag); // Print the tag number of this new tag
225 delay(5000); // Wait 5 seconds, so we can make note of it
230 boolean compareTag(char one[], char two[]){
231 // Compare our two chars to see whether the tag
232 // we just read is the same as the stored tag
234 if(strlen(one) == 0) return false; // If there's nothing here, do nothing
236 for(int i = 0; i < 12; i++){
237 if(one[i] != two[i]) return false; // If the two tags are are not the same, return no match
239 Serial.println("Valid tag found!");
240 return true; // Otherwise, return that there is a match!
243 void clearTag(char one[]){
244 // Clear the tag reading char array by filling it with ASCII 0
245 // If not null, it could indicate another tag read
246 for(int i = 0; i < strlen(one); i++){
252 // Toggle the reset pin so the RFID reader will read again
253 digitalWrite(RFIDResetPin, LOW);
254 digitalWrite(RFIDResetPin, HIGH);