Cyber-Lock Challenge

12-21-2017 11-50-10 AM.gif

 

I challenged Mason with the task of building a “cyber lock” using an Arduino, Keypad and a Servo Motor to represent the lock. First we mocked it up on Circuits.io (now part of Tinkercad) and then we constructed the actual circuit using similar parts. The complete “specifications” we came up with for the project along with the accompanying code are available below.

 

 

Cyber-Lock Specifications

Version 1 – Last update: Nov 11, 2017

Use a Hex Keypad, LCD, Red & Green LED, and a Servo, along with an Arduino to create a “Cypher” lock.

Components:

  • Arduino Nano (Micro / whatever)
  • 16-Key Keypad
  • LCD Display
  • Red LED
  • Green LED
  • (2x) 220 Ohm Resistors
  • Other assorted items as required

Goal:

Create a “Cypher” lock using the above components that will “unlock a door” (turn the servo) when the correct code is entered at the Keypad.

Requirements:

  • The code shall consist of any 4 symbols except “*” and “#” which appear on the keypad. So “1234”, “ABCD”, “12AB”, etc. are all legitimate codes. “123#” is not.
  • The “#” symbol shall be interpreted as “Enter”, such that codes are entered followed by “#” to enact. Example: “1234#” would instruct the program to try the code “1234”.
  • When the “door” is “unlocked”, the servo shall rotate to the “unlocked” position and then the RED LED shall turn off and the Green LED shall turn on.
  • When the door is “locked”, the servo shall rotate to the “locked” position and then the Green LED shall turn off and the Red LED shall turn on.
  • The “” symbol on the keypad shall be used to signal the program to “Lock” the door if the door is unlocked. If the door is already unlocked then the “” symbol shall have no effect.
    The program shall only accept four symbols, not including either the “*” and the “#”. If additional symbols are pressed, the display shall “wrap around” and start again at the beginning. Only a maximum of four symbols shall be shown on the LCD display.
  • When the “*” symbol is entered, the four symbols shown beside the ‘Code:’ prompt shall be used to try the lock. If successful the lock shall open. If unsuccessful the display shall clear and be reset for a new attempt.

Notes:

This simulated version of the lock is a bit sluggish in responding compared to a real world version. Sometimes keys pressed on the keypad do not register (appear on the screen) as they should. We have never seen this issue with the same components in our real world version. However, it is not a serious problem, simply press the key again until it registers. Everything else seems to work the same way as the “real” version.

 

Source Code

(For Arduino “Nano” Controller)

//--------------------------------------------------------------
// MASON & DADDY'S CYPHER LOCK CODE
// 2016-OCT-20
//--------------------------------------------------------------

// include libraries to support our components
#include <Keypad.h>
#include <LiquidCrystal.h>
#include <Servo.h>
#include <string.h>

//--------------------------------------------------------------
// set up our indicator leds
const int LED_UNLOCK = A4;
const int LED_LOCK = A5;

int state = 0; // 0 = unlocked, 1 = locked;
int i = 0;

//--------------------------------------------------------------
// Setup our Keypad
const byte ROWS = 4; // Four rows
const byte COLS = 4; // Four columns

// Define the Keymap
char keys[ROWS][COLS] = {
 {'1','4','7', '*'},
 {'2','5','8', '0'},
 {'3','6','9', '#'},
 {'A','B','C', 'D'}
};

// Connect keypad ROW0, ROW1, ROW2 and ROW3 to these Arduino pins.
byte rowPins[ROWS] = { 8, 7, 6, 5 };

// Connect keypad COL0, COL1 and COL2 to these Arduino pins.
byte colPins[COLS] = { 12, 11, 10, 9 };

// Create the Keypad
Keypad kpd = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

//--------------------------------------------------------------
// setup positions for our servo for door locked and unlocked
const word POS_UNLOCK = 1500;
const word POS_LOCK = 0;
int servo_delay = 500;
//--------------------------------------------------------------

const int SERVO_PIN = 13;

// create servo object to control a servo
Servo myservo;

// Connect the LCD to these interface pins (RS, E, D4, D5, D6, D7)
LiquidCrystal lcd(3, 4, A0, A1, A2, A3);

// define our password
char pword[] = "ABCD";
char buf[5];

//--------------------------------------------------------------
// the setup routine runs once when you press reset:
void setup() {
 // set our indicator led pins to output mode
 pinMode(LED_UNLOCK, OUTPUT);
 pinMode(LED_LOCK, OUTPUT);
 // pinMode(A1, OUTPUT);
 // pinMode(A2, OUTPUT);
 // pinMode(A3, OUTPUT);
 pinMode(A4, OUTPUT);
 pinMode(A5, OUTPUT);

// turn off both leds
 digitalWrite(LED_UNLOCK, LOW);
 digitalWrite(LED_LOCK, LOW);
 
 // attaches the pin to the servo object
 myservo.attach(SERVO_PIN);

// set up the LCD's number of columns and rows:
 lcd.begin(16, 2);
 lock();
}

//--------------------------------------------------------------
// the loop routine runs over and over again forever:
void loop() { 
 // handle the keypad
 char key = kpd.getKey();
 
 if(key) { // Check for a valid key.
 switch (key) {
 case '*':
 lock();
 break;
 case '#':
 if (strcmp(buf, pword) == 0) {
 unlock();
 }
 else {
 show_state();
 }
 break;
 default:
 buf[i] = key;
 lcd.setCursor(i + 6, 0);
 lcd.print(key);
 i++;
 if (i >= 4) {
 i = 0;
 }
 break;
 }
 }
}

void show_state() {
 lcd.clear();
 lcd.setCursor(0, 0);
 lcd.print("CODE: ");
 lcd.setCursor(0, 1);
 if (state) {
 digitalWrite(LED_UNLOCK, LOW);
 digitalWrite(LED_LOCK, HIGH);
 lcd.print("-LOCKED-");
 }
 else {
 digitalWrite(LED_LOCK, LOW);
 digitalWrite(LED_UNLOCK, HIGH);
 lcd.print("-UNLOCKED-");
 }
}

void show_change_state() {
 lcd.clear();
 lcd.setCursor(0, 1);
 if (state) {
 digitalWrite(LED_UNLOCK, LOW);
 digitalWrite(LED_LOCK, HIGH);
 lcd.print("-UNLOCKING-");
 }
 else {
 digitalWrite(LED_LOCK, LOW);
 digitalWrite(LED_UNLOCK, HIGH);
 lcd.print("-LOCKING-");
 }
}

void lock() {
 show_change_state();
 memset(buf,0,sizeof(buf));
 myservo.write(POS_LOCK);
 delay(servo_delay);
 state = 1;
 show_state();
}

void unlock() {
 show_change_state();
 memset(buf,0,sizeof(buf));
 myservo.write(POS_UNLOCK);
 delay(servo_delay);
 state = 0;
 show_state();
}

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s