This is a project Ive just completed, that was requested by my parents. Back home, we have a shop that we like to keep locked. The keys are on certain keyrings though, and there are lots of people around that need to go in and out. Hence this keyless entry kind of system was born.
It features a 16x2 white-on-blue LCD, 4x3 keypad, and an electric door strike to “unlock” the door, along with a custom PCB. When the correct passcode is entered, it powers the door strike for 5 seconds, then goes back to being locked. The power-off state of the strike is locked, and we have a key as a fail-safe.
Ive also added a timeout feature, so if input isnt received for five seconds, the display shuts off. It turns back on on the next keypress. Hopefully this will prolong the life of the little display.
Now all Ive got to do is figure out a nice mounting box. Something weatherproof would be nice. Anyone know of a good way to weatherproof the standard 4x3 SparkFun keypads?
Anyway, picture time:
Front of PCB (power supply section in the bottom right has been reworked - bottom header is for the keypad, top-left header is for the LCD):
Demo video (sorry it’s sideways, facebook tells me I have no permission to rotate my video…):
Unfortunately my Eagle files are still at school so I will post them when I am there tomorrow morning.
Here is the code:
/*
Alarm System v1.0
by J Skoba
parkinglotlust@gmail.com
=======================================================
Some internal comments, because CTRL+T messes up arrays
byte rowPins[ROWS] = {3, 8, 7, 5};
byte colPins[COLS] = {4, 2, 6};
char keys[ROWS][COLS] =
{
{'1','2','3'},
{'4','5','6'},
{'7','8','9'},
{'*','0','#'}
};
// passcode vars
byte passcode[] = { 1, 2, 3, 4 }; // the passcode
byte enteredPasscode[] = { 0, 0, 0, 0 }; // an empty array to hold the entered passcode
*/
#include <Keypad.h>
#include <ShiftRegLCD.h>
// keypad vars
byte rowPins[ROWS] = {3, 8, 7, 5};
byte colPins[COLS] = {4, 2, 6};
char keys[ROWS][COLS] =
{
{'1','2','3'},
{'4','5','6'},
{'7','8','9'},
{'*','0','#'}
};
// passcode vars
byte passcode[] = { 1, 2, 3, 4 }; // the passcode
byte enteredPasscode[] = { 0, 0, 0, 0 }; // an empty array to hold the entered passcode
// lcd vars
long timeoutInterval = 5000; // length of lcd timeout in mS
long previousMillis = 0;
// character-hiding vars
bool hidePrevious = false; // whether or not to hide the previous value
int timeAtSend; // timer value when call to hide a character was made
double hideInterval = 700; // length of pause until previous password digit is hidden in mS
// unlock time vars
float unlockTime = 5; // time to keep the door unlocked for (in seconds)
float downStep = 0.5; // seconds per tick for ^^
// declarations
ShiftRegLCD lcd(9, 10, 11, 2);
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
// pin assignments
int relayPin = 12; // pin output relay is connected to (permanent)
int backlightPin = 13; // pin lcd backlight is connected to (permanent)
void setup()
{
pinMode(relayPin, OUTPUT);
pinMode(backlightPin, OUTPUT);
initialize();
}
void loop()
{
waitForPasscode();
validatePasscode();
}
void initialize()
{
digitalWrite(backlightPin, LOW);
aboutScreen();
delay(1000);
digitalWrite(backlightPin, HIGH);
delay(4000);
}
void waitForPasscode()
{
lcd.noBlink();
lcd.clear();
lcd.print("Please enter the");
lcd.setCursor(0,1);
lcd.print("passcode:");
lcd.setCursor(10,1);
lcd.blink();
// 10 is first dash coord
for (int i = 0; i < 4; i++)
{
char key = keypad.getKey();
previousMillis = millis();
while (key == NO_KEY)
{
key = keypad.getKey();
if (i > 0)
hidePreviousDigit(i);
if (millis() - previousMillis > timeoutInterval)
timeout();
}
lcd.setCursor((i + 10),1);
lcd.print(key);
lcd.setCursor((i + 11),1);
timeAtSend = millis();
hidePrevious = true;
lcd.setCursor((i + 11),1);
enteredPasscode[i] = key - 48;
delay(200);
}
lcd.noBlink();
}
void timeout()
{
digitalWrite(backlightPin, LOW);
lcd.noDisplay();
char temp = keypad.getKey();
while (temp == NO_KEY)
temp = keypad.getKey();
digitalWrite(backlightPin, HIGH);
lcd.display();
previousMillis = millis();
}
void hidePreviousDigit(int i)
{
if ((millis() - timeAtSend > hideInterval) && hidePrevious)
{
lcd.noBlink();
lcd.setCursor((i + 9),1);
lcd.print("*");
lcd.setCursor((i + 10),1);
hidePrevious = false;
lcd.blink();
}
}
void validatePasscode()
{
int times = 0;
for (int i = 0; i < 4; i++)
{
if (enteredPasscode[i] == passcode[i])
times++;
}
if (times == 4) // passed
{
lcd.clear();
lcd.home();
lcd.print(" Passcode");
lcd.setCursor(0,1);
lcd.print(" accepted!");
delay(1500);
digitalWrite(relayPin, HIGH);
delay(500);
lcd.clear();
lcd.home();
lcd.print(" You have");
lcd.setCursor(0,1);
lcd.print("seconds to enter");
lcd.setCursor(10,0);
float time = unlockTime;
lcd.print(time);
delay(750);
while (time >= downStep)
{
time -= downStep;
lcd.setCursor(10,0);
lcd.print(time);
delay(downStep * 1000);
}
digitalWrite(relayPin, LOW);
delay(1000);
}
else // failed
{
lcd.clear();
lcd.print(" Incorrect");
lcd.setCursor(0,1);
lcd.print(" passcode!");
delay(2000);
}
}
void aboutScreen()
{
lcd.clear();
lcd.print("Alarm System 1.0");
lcd.setCursor(3,1);
lcd.print("By J Skoba");
}