Keypad and LCD share data pins...
Note, I have made corrections to this post as identified in the following discussion...
Basic system to provide security access:
- Allows three different passwords...
- Lockout if tampering (allows three attempts and then lock the keypad for X seconds)...
- Uses a piezo device to generate keyboard tone and door open tone...
- Software driven contrast (user can set level)...
- Uses shares data pin to accommodate more functionality...
Revision IV, removed the pot and replaced with code... (Contrast can changed by user)...
The source code:
/*
Connecting Keypad and LCD sharing common data pins, using keypad and lcd libraries...
Mike O'Toole 28 03 2012...
Reversion IV (08 April 2012), if you make any improvements let me know...
Many thanks to liudr, mstanley and bperrybap @ http://arduino.cc for help getting it right...
On previous versions I transposed the col/row pins in sketch and Fritzing image...
Mike
Email: o2l at eircom.net
Site: http://www.phpbbireland.com
Copyright 2012 - Under creative commons license 3.0:
*/
#include <Keypad.h>
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
const byte ROWS = 4;
const byte COLS = 4;
char keys[ROWS][COLS] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};
byte colPins[COLS] = {5, 4, 3, 2}; //connect to the column pinouts of the keypad
byte rowPins[ROWS] = {6, 7, 8, 9}; //connect to the row pinouts of the keypad
#define CONTRAST_PIN 10
#define SESSOR_PIN A0
#define LATCH_PIN A1
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS);
byte con[8] = {
0b00100,
0b01110,
0b11111,
0b00000,
0b00000,
0b11111,
0b01110,
0b00100
};
// Support three passwords //
char firstPassword[] = "123456*";
char secondPassword[] = "246855*";
char masterPassword[] = "1234567890*";
int contrast = 75;
int counter = 0;
int attempts = 0;
int attempted = 0;
int access = 0;
int xcol = 3;
int xrow = 2;
int clean = 0;
int loopCount = 0;
int aData = 0;
int repaint = 0;
char key;
unsigned int lockoutDelay = 3000;
unsigned int lockedout = 0;
unsigned int inMenu = 0;
unsigned int valid0 = 0;
unsigned int valid1 = 0;
unsigned int valid2 = 0;
unsigned long resetline;
unsigned long duration = 3000;;
unsigned long startTime;
void setup()
{
pinMode(13, OUTPUT);
// not implemented yet //
//pinMode(LATCH_PIN, OUTPUT);
pinMode(CONTRAST_PIN, OUTPUT);
analogWrite (CONTRAST_PIN, contrast);
lcd.createChar(1, con);
Serial.begin(9600);
keypad.addEventListener(keypadEvent); //add an event listener for this keypad
lcd.begin(20, 4);
lcd.setCursor(0, 0);
lcd.print(" System Armed ");
delay(500);
lcdstart();
intro();
}
void lcdstart()
{
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(" Enter Password ");
lcd.setCursor(0, 2);
lcd.setCursor(xcol, xrow);
repaint = 0;
}
void resetvars()
{
counter = 0;
attempts = 0;
valid0 = 0;
valid1 = 0;
valid2 = 0;
xcol = 3;
xrow = 2;
loopCount = 0;
if(!repaint) attempted = 0;
}
void buzzer()
{
if (startTime > 0 && (startTime + duration) > millis())
{
//digitalWrite(LATCH_PIN, HIGH);
tone(13, 240, 150); delay(550);
}
else
{
//digitalWrite(LATCH_PIN, LOW);
}
}
void soundAlarm()
{
tone(13, 243, 50); delay(40);
tone(13, 443, 50); delay(50);
tone(13, 743, 50); delay(70);
}
void intro()
{
// do something fancy here //
tone(13, 294, 250); delay(325);
}
// using the callback to better organise //
void keypadEvent(KeypadEvent key)
{
switch (keypad.getState())
{
case PRESSED:
if(key == '*' && access == 1)
{
tone(13, 870, 90);
}
else
{
tone(13, 543, 70);
access = 0;
}
break;
case RELEASED:
switch (key)
{
case '*':
if(access == 0 && inMenu == 0)
{
repaint = 1;
}
break;
case '#':
if(inMenu == 0)
{
resetvars();
lcdstart();
}
break;
default:
if(!inMenu)
{
lcd.setCursor(xcol++,xrow);
lcd.print('*');
}
break;
}
break;
case HOLD:
// print some info //
break;
default:
break;
}
}
// main loop //
void loop()
{
key = keypad.getKey();
if(key == 'D')
{
inMenu = 1;
lcd.clear();
lcd.setCursor(0,0);
lcd.print(" Set Contrast ");
lcd.setCursor(0,1);
lcd.print("Dark(2) (8)Light");
lcd.setCursor(9,1);
lcd.write(1);
lcd.setCursor(0,3);
lcd.print(" Press * to exit: ");
lcd.setCursor(17,3);
if(contrast < 99)
{
lcd.print(" ");
}
lcd.print(contrast);
while(key != '*')
{
key = keypad.getKey();
if(key == '8')
{
lcd.setCursor(17,3);
if(contrast < 99)
{
lcd.print(" ");
}
if(contrast <= 10)
contrast = 10;
lcd.print(contrast);
contrast += 5; analogWrite (CONTRAST_PIN, contrast);
//Serial.println(contrast);
}
if (key == '2')
{
lcd.setCursor(17,3);
if(contrast < 99)
{
lcd.print(" ");
}
if(contrast >= 220)
contrast = 220;
contrast -= 5; analogWrite (CONTRAST_PIN, contrast);
lcd.print(contrast);
//Serial.println(contrast);
}
}
inMenu = 0;
}
else if (key)
{
if(key == masterPassword[counter])
{
valid0++;
}
else
{
valid0 = 0;
}
if(key == firstPassword[counter])
{
valid1++;
}
else
{
valid1 = 0;
}
if(key == secondPassword[counter])
{
valid2++;
}
else
{
valid2 = 0;
}
if(key != firstPassword[counter] && key != secondPassword[counter] && key != masterPassword[counter])
{
valid0 = valid1 = valid2 = 0;
attempts++;
}
counter++;
// one of the valid passwords //
if(attempts == 0 && valid1 == strlen(firstPassword) || valid2 == strlen(secondPassword) || valid0 == strlen(masterPassword))
{
access = 1;
startTime = millis();
resetvars();
lcdstart();
}
/* Tampering > count entry attempts, if exceeds 3 force delay before next attempt */
if(attempts >= 6 || key == '*' || counter > 12)
{
attempted++;
attempts = 0;
}
if(attempted > 2)
{
repaint = 1;
lcd.clear();
lcd.setCursor(0,0);
lcd.print(" Security delay ");
lcd.setCursor(0,2);
lcd.print(" PLEASE WAIT! ");
delay(lockoutDelay);
lcdstart();
resetvars();
}
//Serial.println(key);
}
if(repaint)
{
resetvars();
lcdstart();
}
buzzer();
}
Contrast Adjustment:
To modify the contrast press the D key, followed by 2 and 8 to decrease/increase contrast... Press * when complete...
Updates:
3: Remove then need for the 10k pot by doing the contrast in code...
4: Fixed LCD issue and corrected pinouts thanks to: liudr, mstanley and bperrybap @ http://arduino.cc
Fritzing image:
Please note the power supply should be 5 Volts DC also disregard wire to A0...
Also note the LCD above does not have standard pin outs... I will replace next time...
Todo:
Turn off backlight when inactive and/or play around with sleep mode and hardware interrupts...