Hi!
This is my first post here, but I've read a lot on this forum and leard a LOT!
I know there are similar projects out there, but I wanted to try this by my self since this was my first project.
Features:
- RFID reader (125 kHz)
- A button to open the door from inside
- The button can also be used to keep the door open
- LEDs to indicate status (green = open, red = access denied, blue (not in use in the video) = power on)
The code is based on these sites:
http://www.arduino.cc/playground/Learning/PRFID
http://www.arduino.cc/playground/Code/ID12
Source code:
#include <Servo.h>
#define RFIDResetPin 2
#define buttonPin 3
// #define buzzerPin 7
#define servoPin 9
#define redLedPin 12
#define greenLedPin 13
#define blueLedPin 11
#define servoOpen 28
#define servoClose 85
Servo myservo;
boolean match = false;
void setup() {
Serial.begin(9600); // connect to the serial port
pinMode(buttonPin, INPUT);
pinMode(RFIDResetPin, OUTPUT);
digitalWrite(RFIDResetPin, HIGH);
// pinMode(buzzerPin, OUTPUT);
pinMode(blueLedPin, OUTPUT);
pinMode(greenLedPin, OUTPUT);
pinMode(redLedPin, OUTPUT);
myservo.attach(servoPin);
myservo.write(servoClose);
}
void loop () {
/*
Variables we need to the RFID reader
*/
byte i = 0;
byte val = 0;
byte code[6];
byte checksum = 0;
byte bytesread = 0;
byte tempbyte = 0;
/*
If the button is pushed we openes the door
*/
if(digitalRead(buttonPin))
{
openDoor();
}
else
{
if(Serial.available() > 0) {
if((val = Serial.read()) == 2) { // check for header
bytesread = 0;
while (bytesread < 12) { // read 10 digit code + 2 digit checksum
if( Serial.available() > 0) {
val = Serial.read();
if((val == 0x0D)||(val == 0x0A)||(val == 0x03)||(val == 0x02)) { // if header or stop bytes before the 10 digit reading
break; // stop reading
}
// Do Ascii/Hex conversion:
if ((val >= '0') && (val <= '9')) {
val = val - '0';
} else if ((val >= 'A') && (val <= 'F')) {
val = 10 + val - 'A';
}
// Every two hex-digits, add byte to code:
if (bytesread & 1 == 1) {
// make some space for this hex-digit by
// shifting the previous hex-digit with 4 bits to the left:
code[bytesread >> 1] = (val | (tempbyte << 4));
if (bytesread >> 1 != 5) { // If we're at the checksum byte,
checksum ^= code[bytesread >> 1]; // Calculate the checksum... (XOR)
};
} else {
tempbyte = val; // Store the first hex digit first...
};
bytesread++; // ready to read next digit
}
}
// Output to Serial:
if (bytesread == 12) { // if 12 digit read is complete
Serial.print("5-byte code: ");
for (i=0; i<5; i++) {
if (code[i] < 16) Serial.print("0");
Serial.print(code[i], HEX);
Serial.print(" ");
}
Serial.println();
Serial.print("Checksum: ");
Serial.print(code[5], HEX);
Serial.println(code[5] == checksum ? " <- passed." : " <- error.");
Serial.println();
/*
Check if the user has access and the checksum is correct
*/
if(accessCheck(code) == true && code[5] == checksum) {
Serial.println("Door unlocked!");
openDoor();
} else {
Serial.println("Access denied!");
accessDenied();
}
}
bytesread = 0;
}
}
}
}
boolean accessCheck(byte test[])
{
byte rfidTags = 4;
byte tags[30] = {
'0','0','0','0','0','0','0','0','0','0', // Card 1
'0','0','0','0','0','0','0','0','0','0', // Card 2
'0','0','0','0','0','0','0','0','0','0', // Card 3
'0','0','0','0','0','0','0','0','0','0' // Card 4
};
for(int numCards=0; numCards<rfidTags; numCards++)
{
byte bytesread = 0;
byte i = 0; // Example card, replace with one of yours you want to be the master
// byte val[10] = {'4','5','0','0','B','8','9','7','E','6'};
byte val[10];
for(byte q=0; q<10; q++)
{
val[q] = tags[numCards*10+q];
}
byte master[6];
byte checksum = 0;
byte tempbyte = 0;
bytesread = 0;
for ( i = 0; i < 10; i++ ) // First we need to convert the array above into a 5 HEX BYTE array
{
if ( (val[i] >= '0' ) && ( val[i] <= '9' ) ) // Convert one char to HEX
{
val[i] = val[i] - '0';
}
else if ( (val[i] >= 'A' ) && ( val[i] <= 'F' ) )
{
val[i] = 10 + val[i] - 'A';
}
if (bytesread & 1 == 1) // Every two hex-digits, add byte to code:
{
// make some space for this hex-digit by
// shifting the previous hex-digit with 4 bits to the left:
master[bytesread >> 1] = (val[i] | (tempbyte << 4));
if (bytesread >> 1 != 5) // If we're at the checksum byte,
{
checksum ^= master[bytesread >> 1]; // Calculate the checksum... (XOR)
};
}
else
{
tempbyte = val[i]; // Store the first hex digit first...
};
bytesread++;
}
if ( checkTwo( test, master ) ) // Check to see if the master = the test ID
return true;
}
return false;
}
// Check two arrays of bytes to see if they are exact matches
boolean checkTwo ( byte a[], byte b[] )
{
if ( a[0] != NULL ) // Make sure there is something in the array first
match = true; // Assume they match at first
for ( int k = 0; k < 5; k++ ) // Loop 5 times
{
// Serial.print("[");
// Serial.print(k);
// Serial.print("] ReadCard [");
// Serial.print(a[k], HEX);
// Serial.print("] StoredCard [");
// Serial.print(b[k], HEX);
// Serial.print("] \n");
if (a[k] != b[k]) // IF a != b then set match = false, one fails, all fail
{
match = false;
}
}
if ( match ) // Check to see if if match is still true
{
//Serial.print("Strings Match! \n");
return true; // Return true
}
else {
//Serial.print("Strings do not match \n");
return false; // Return false
}
}
/*
Open the door.
- Open servo
- Green LED blinking
If the button is pushed after 4000ms the keepDoorOpen function is called
*/
void openDoor()
{
// Move servo to open position
myservo.write(servoOpen);
// digitalWrite(buzzerPin, HIGH);
digitalWrite(greenLedPin, HIGH);
delay(4000); // The time the door needs to be open
digitalWrite(greenLedPin, LOW);
// digitalWrite(buzzerPin, LOW);
if(digitalRead(buttonPin))
{
// When the button is pushed the keepDoorOpen function is activated
keepDoorOpen();
// Recursive call to this function to run it again
openDoor();
}
// Move servo to lock position
myservo.write(servoClose);
}
/*
Keeping the door open until you push the button again.
Stays open for at least 10 * 200ms before you can push the button to lock it
## TODO ##
rewrite the buttonState counter. Do not need to count to 20, just check if the
buttonState==LOW and then HIGH. Then we do not need the 20*200ms delay
*/
void keepDoorOpen()
{
Serial.println("Keeping the door open.");
int buttonState = 1;
while(buttonState>0)
{
digitalWrite(greenLedPin, HIGH);
delay(100);
digitalWrite(greenLedPin, LOW);
delay(100);
if(buttonState<=10) buttonState++;
if(digitalRead(buttonPin)==HIGH && buttonState>=10) break;
}
/*
Flashes the red and green LED to indicate that this mode is about to quit
*/
for(int i=0; i<4; i++)
{
digitalWrite(redLedPin, HIGH);
delay(100);
digitalWrite(redLedPin, LOW);
digitalWrite(greenLedPin, HIGH);
delay(100);
digitalWrite(greenLedPin, LOW);
}
}
/*
Access denied!
Flashes the red LED
*/
void accessDenied()
{
for(int i=0; i<5; i++) {
digitalWrite(redLedPin, HIGH);
delay(100);
digitalWrite(redLedPin, LOW);
delay(100);
}
}
I'm not 100% satisfied yet.
Todo:
- A master key (to add/delete cards)
Pictures are comming later!
I hope my English is understandable!
Regards an IT student from Norway