]> git.piffa.net Git - arduino/blob - books/pdummies/APFD_Web_Extras_Part_3/APFD_Web_Extras_Part_3.ino
first commit
[arduino] / books / pdummies / APFD_Web_Extras_Part_3 / APFD_Web_Extras_Part_3.ino
1 /* Arduino Projects for Dummies
2  * by Brock Craft 
3  *
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
8  *
9  * v0.1 05.05.2013
10  * Adapted from keypad reading technique by Michael Margolis
11 */
12
13 #include <SPI.h>
14
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
20
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
24
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.)
29
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
33 // etc. for more tags
34
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
37
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
40
41 // The keyMap defines the character returned when the corresponding key is pressed
42 const char keyMap[numRows][numCols] = {
43   { '1', '2', '3' },
44   { '4', '5', '6' },
45   { '7', '8', '9' },
46   { '*', '0', '#' }
47 };
48
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
53
54 void setup()
55 {
56   if (DEBUG){Serial.begin(9600);} // If in DEBUG mode, start the serial port
57
58   // Prepare the MAX72xx to display 7-segment data (see datasheet)
59   // Format: sendCommand(command, value)
60   
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 
68
69   // Prepare the I/O pins for the keypad and the relay
70   pinMode(strikePin,OUTPUT);
71   
72   for (int row = 0; row < numRows; row++)
73   {
74     pinMode(rowPins[row],INPUT);       // Set row pins as input
75     digitalWrite(rowPins[row],HIGH);   // Turn on pull-up resistors on the processor
76   }
77   for (int column = 0; column < numCols; column++)
78   {
79     pinMode(colPins[column],OUTPUT);     // Set column pins as outputs for writing
80     digitalWrite(colPins[column],HIGH);  // Make all columns inactive
81   }
82   
83   // Clear the display (helps when debugging)
84   clearDisplay();
85   
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.  
90 }
91
92 void loop()
93 {
94
95   char key = getKey();  // See if a key has been pressed 
96   codeBuffer[keypressCount]=key; // Add the key just pressed to the code Buffer
97
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: ");
105       Serial.println(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]);
116     }
117  
118     keypressCount++;   // Incrmement the number of keys that have been pressed
119  
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
125       } 
126       clearDisplay(); // Now clear the display
127       memset(codeBuffer, 0, 4); // Explicitly clear out the code buffer array
128       keypressCount=0;
129     }
130   }
131   
132   // NOW SEE IF THE RFID READER HAS DETECTED A TAG
133   
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
138
139   while(Serial.available()){  // If there is a serial connection...
140
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
144     
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){
147      
148       tagString[index] = readByte;  // Store the tag at the index point
149       index ++;                     // increment where we are in the storage array
150     }
151   }
152
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
156 }
157
158 // Returns the key pressed, or 0 if no key is pressed
159 char getKey()
160 {
161   char key = 0;                                  // 0 indicates no key pressed
162   for(int column = 0; column < numCols; column++)
163   {
164     digitalWrite(colPins[column],LOW);            // Activate the current column
165     for(int row = 0; row < numRows; row++)        // Scan all rows for a key press
166     {
167       if(digitalRead(rowPins[row]) == LOW)        // If a key is pressed...
168       {
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
172       }
173     }
174     digitalWrite(colPins[column],HIGH);           // De-activate the current column
175   }
176   return key;  // Return the key that pressed (or 0 if none)
177 }
178
179
180 void sendCommand(int command, unsigned char value)
181 {
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
186 }  
187
188 void clearDisplay(){
189   sendCommand(1, '_'); // Clears out all the digits. You can also use underscore 'o'
190   sendCommand(2, '_'); 
191   sendCommand(3, '_');
192   sendCommand(4, '_'); 
193 }
194
195 void unlock(){  
196   if(DEBUG){Serial.println("Unlocking Door.");}
197
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)
207 }
208
209 void checkTag(char tag[]){
210
211   // Compare this tag to the stored tags
212   if(strlen(tag) == 0) return; // If there's nothing here, do nothing
213
214   if(compareTag(tag, tag1)){   // If read tag matches tag1, do this
215     unlock();
216   }
217   else if(compareTag(tag, tag2)){ // If read tag matches tag2, do this
218     unlock();
219   }
220   else if(compareTag(tag, tag3)){ // If read tag matches tag3, do this
221     unlock();
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
226   }
227
228 }
229
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
233   
234   if(strlen(one) == 0) return false; // If there's nothing here, do nothing
235
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
238   }
239   Serial.println("Valid tag found!");
240   return true; // Otherwise, return that there is a match!
241 }
242
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++){
247     one[i] = 0; 
248   }
249
250   
251 void resetReader(){
252   // Toggle the reset pin so the RFID reader will read again
253   digitalWrite(RFIDResetPin, LOW);
254   digitalWrite(RFIDResetPin, HIGH);
255   delay(150);
256 }
257
258