Arduino Security [I know there are lots of them]

I am using a mashup of parts though. Have a 4x4 keypad, LCD screen that runs on just 2 wires for signal, 4 relay board and an Uno.

Its works, once. I can't get it to reset for the next password. I was thinking of using a sensor that says the door has been opened to reset it or set off the alarm if the password was not used.

I am looking for just a little guidance. I need to finish out the build and the code. The LCD has an RGB LED in it and I want to use that to indicate some of the status. I only have 2 digital pins left and all the analog. With the door senor on those last two digital pins I'm not sure how to do the RGB LED but I am thinking the analog can run it.

Right now, can anyone help with the reset for the next password?

#include <Password.h>
#include <Keypad.h> 
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

Password password = Password( "1234" );
unsigned char WrongAttempts = 0; //global variable to keep the number of wrong attempts done at the code. 

const byte ROWS = 4; //four rows
const byte COLS = 4; //three columns
char keys[ROWS][COLS] = {
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
};
byte rowPins[ROWS] = {6, 7, 8, 9}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {10, 11, 12, 13}; //connect to the column pinouts of the keypad
LiquidCrystal_I2C lcd(0x27,16,2); // set the LCD address to 0x27
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );


//PIN assignments

int r1 = 2; //alarm
int r2 = 3;  //green light
int r3 = 4;  //Red light
int r4 = 5;  //Nothing?


void setup(){

Serial.begin(9600);
keypad.addEventListener(keypadEvent); //add an event listener for this keypad
  lcd.init(); // initialize the lcd
  lcd.backlight();
  // Print a message to the LCD.
  //lcd.setCursor(0, 1);
  lcd.print("Security Status");
pinMode(r1, OUTPUT);
pinMode(r2, OUTPUT);
pinMode(r3, OUTPUT);
pinMode(r4, OUTPUT);

}

void loop()
{
keypad.getKey();
}



void keypadEvent(KeypadEvent eKey){
switch (keypad.getState()){
case PRESSED:
lcd.setCursor(0, 1);
lcd.print("Pressed: ");
lcd.println(eKey);
switch (eKey){
case '*': checkPassword(); break;
case '#': password.reset(); break;
default: password.append(eKey);
}
}
}

void checkPassword(){
if (password.evaluate()){
  lcd.clear();
lcd.println("Success!");
lcd.println("Disarmed!");
digitalWrite(r1, LOW); //DISCONNETC THE SIREN IF THE PASSWORD IS CORRECT
digitalWrite(r2, HIGH);
delay(2000); 

digitalWrite(r3, HIGH);
delay(100);
}else{
    lcd.clear();
lcd.println("Wrong");
delay(1000);
lcd.clear();
WrongAttempts++;  

if (WrongAttempts >= 3) { //UPS.... 
digitalWrite(r1, HIGH); //START THE SIREN
digitalWrite(r3, HIGH); //START THE REDNESS
lcd.clear();
lcd.print("Alarm Activated");
}


}

digitalWrite(r2, HIGH);
delay(100);
digitalWrite(r2, HIGH);
delay(100);
 
}

It would help to understand your code if you gave the pins meaningful names.

Why do you need to know whether the door has opened ? You already know that a correct password has been entered and if so, pins 'r2' and 'r3' are set high, presumably they are something to do with releasing the door (see what I mean about using meaningful names ?)

If the password is correct then release the door, give the user a few seconds to open the door, lock the door again and reset the password. If the user did not open the door in the time allowed then, tough, they will need to enter the password again

I suppose Io could explain that.

r 1-4 are the relays. I didn't bother with meaningful names because I'm not used to working like that.

Relay 1 is alarm
Relay 2 is a big red bulb
Relay 3 is a big green bulb
Relay 4 is nothing but defined because it's there.

This isn't for anything serious, I was going to install it on the bathroom door.

The alarm is an old school bell.

morganlowe:
r 1-4 are the relays. I didn't bother with meaningful names because I'm not used to working like that.

It would be a good idea to get into the habit

Your comments indicate what the pins are used for but you cannot tell when reading the code.

How about

int alarm = 2; //alarm
int green_light = 3;  //green light
int red_light = 4;  //Red light
int nothing_yet = 5;  //Nothing?

I must admit to being amused by the fact that your explanation of what the pins are used for does not match your comments, which I think proves the point about using meaningful names.

Relay 1 is alarm
Relay 2 is a big red bulb
Relay 3 is a big green bulb
Relay 4 is nothing but defined because it's there.

Alright, I'll change it, but that's not why I posted it here.

Thanks for the tip though!

How do we make it reset after a successful entry or after a set period of time when the alarm goes off.

One possibility is having a sensor for door open that resets it, but I don't think that would be the best overall solution. I am thinking something time based.

I think either option would be viable. Making the system rearm itself after a delay (ten seconds would be enough?) would be easiest since it does not require any extra hardware.

My question is how to implement it. I tried setting it in the code and I broke the whole thing. I'm a N00b, any thoughts? Tips?

What do you do when the user enters '#' ?
Can't you do the same after a delay when they enter a correct password and you have flashed lights or whatever ?

morganlowe:
My question is how to implement it. I tried setting it in the code and I broke the whole thing. I'm a N00b, any thoughts? Tips?

I would just add a fixed delay after the code that prints "Success!", and follow that by code to print out "Armed!" and reconnect the siren and do whatever you want to happen to the lamps. (Which, by the way, doesn't currently seem very sensible - the red and green lamps don't seem to be turned off in any coherent way. I suggest you decide what you want each lamp to represent, and then define when it needs to be turned on and off in terms of events within your sketch.)

Alright, I made some changes. I think it's much better but still incomplete. I picked a hellova project for my introduction to this.

#include <Password.h>
#include <Keypad.h> 
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

Password password = Password( "1234" );
unsigned char WrongAttempts = 0; //global variable to keep the number of wrong attempts done at the code. 

const byte ROWS = 4; //four rows
const byte COLS = 4; //four columns
char keys[ROWS][COLS] = {
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
};
byte rowPins[ROWS] = {6, 7, 8, 9}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {10, 11, 12, 13}; //connect to the column pinouts of the keypad
LiquidCrystal_I2C lcd(0x27,16,2); // set the LCD address to 0x27
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );



/*-----( Declare Constants )-----*/
#define RELAY_ON 0
#define RELAY_OFF 1
/*-----( Declare objects )-----*/
/*-----( Declare Variables )-----*/
#define Relay_1  2  // Bell
#define Relay_2  3  // Green Lamp - ready
#define Relay_3  4  // Red Lamp - ALERT!
#define Relay_4  5  // Door actuator - not finished yet

void setup(){
  
  //-------( Initialize Pins so relays are inactive at reset)----
  digitalWrite(Relay_1, RELAY_OFF);
  digitalWrite(Relay_2, RELAY_OFF);
  digitalWrite(Relay_3, RELAY_OFF);
  digitalWrite(Relay_4, RELAY_OFF);  
  
//---( THEN set pins as outputs )----  
  pinMode(Relay_1, OUTPUT);   
  pinMode(Relay_2, OUTPUT);  
  pinMode(Relay_3, OUTPUT);  
  pinMode(Relay_4, OUTPUT);    
  delay(4000); //Check that all relays are inactive at Reset


Serial.begin(9600);
keypad.addEventListener(keypadEvent); //add an event listener for this keypad
  lcd.init(); // initialize the lcd
  lcd.backlight();
  // Print a message to the LCD.
  //lcd.setCursor(0, 1);
  lcd.clear();
  lcd.print("Security Status");

}

void loop()
{
keypad.getKey();
}



void keypadEvent(KeypadEvent eKey){
switch (keypad.getState()){
case PRESSED:
lcd.setCursor(0, 1);
lcd.print("Pressed: ");
lcd.println(eKey);
switch (eKey){
case '*': checkPassword(); break;
case '#': password.reset(); break;
default: password.append(eKey);
}
}
}

void checkPassword(){
if (password.evaluate()){
  lcd.clear();
lcd.println("Success!");
lcd.setCursor(0, 1);
lcd.println("Disarmed!");
digitalWrite(Relay_1, RELAY_OFF); //DISCONNETC THE SIREN IF THE PASSWORD IS CORRECT
digitalWrite(Relay_2, RELAY_ON);
digitalWrite(Relay_4, RELAY_ON);
delay(2000); 

digitalWrite(Relay_4, RELAY_OFF);

delay(100);
}else{
    lcd.clear();
lcd.println("Wrong");
delay(1000);
lcd.clear();
WrongAttempts++;  

if (WrongAttempts >= 3) { //UPS.... 
digitalWrite(Relay_1, RELAY_ON); //START THE SIREN
digitalWrite(Relay_3, RELAY_ON); //START THE REDNESS
lcd.clear();
lcd.print("Alarm Activated");
}


}

digitalWrite(Relay_2, RELAY_ON);
delay(100);
digitalWrite(Relay_2, RELAY_ON);
delay(100);
 
}

Why issue commands to set the relay pins low then define them as outputs ?

Much better with the meaningful names though.

Oops, forgot to take that out. Thanks for reminding me!

So umm... Any ideas on how to reset it?

morganlowe:
So umm... Any ideas on how to reset it?

You mean - any other ideas?

Leave the pinMode and digitalWrite commands in there but do them in the reverse order.

You have had my idea on how to reset the password when the user has been successful. You do it when the user presses the '#' key
case '#': password.reset(); so why not when they get it right and the light show is triggered ?

OK, It's about done... I need to get rid of the funky weirdness on the display, maybe you guys could help with that?

I made a video of the pile of parts in action. I am still working on the door it's self, more to come later.

Here's the code again! I am using an RGB backlit display with a 2 wire I2C interface, a 4x4 Keypad and a 4 relay board. I have a fire alarm from a school that will be the siren and red and green 120v bulbs in cages for the indicator lights. Somewhere in my junk I have a magnetic door latch too.

Oh! Almost forgot.

      //-------( Initialize Pins so relays are inactive at reset)----
  digitalWrite(Relay_1, RELAY_OFF);
  digitalWrite(Relay_2, RELAY_ON);
  digitalWrite(Relay_3, RELAY_OFF);
  digitalWrite(Relay_4, RELAY_OFF);

Must come before

//---( THEN set pins as outputs )----  
  pinMode(Relay_1, OUTPUT);   
  pinMode(Relay_2, OUTPUT);  
  pinMode(Relay_3, OUTPUT);  
  pinMode(Relay_4, OUTPUT);    
  delay(4000); //Check that all relays are inactive at Reset

Or when it boots everything is turned on and that's a mess.

To do list:

  1. Make the alarm only sound for 5 minutes. Just in case I put this to real use.
  2. Make an enclosure and cable system so the board and relays can be inside the locked room with only the keypad and display outside. 8 wires for keypad, 6 for display with RGB LED. Thinking a couple of Cat5e cables.
  3. Redundant Power Supply.
  4. Weird things on display.

Here's the code right now, the green light shuts off when the red comes on!

#include <Password.h>
#include <Keypad.h> 
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

//  Credit goes to Arduino and it's wonderful community and morganlowe for the code and setup.
//  Digital Pins 2=relay 1; 3 = relay 2; 4 = relay 3; 5 = relay 4; 6-13 = keypad; SDA & SDL = corrosponding inputs for LCD
//  Analog Pins A2 and A3 Green and Blue for LCD

Password password = Password( "5466" );
unsigned char WrongAttempts = 0; //global variable to keep the number of wrong attempts done at the code. 

const byte ROWS = 4; //four rows
const byte COLS = 4; //four columns
char keys[ROWS][COLS] = {
  {'1','2','3','A'},
  {'4','5','6','B'},
  {'7','8','9','C'},
  {'*','0','#','D'}
};
byte rowPins[ROWS] = {6, 7, 8, 9}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {10, 11, 12, 13}; //connect to the column pinouts of the keypad
LiquidCrystal_I2C lcd(0x27,16,2);  // set the LCD address to 0x27 for a 16 chars and 2 line display
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );



/*-----( Declare Constants )-----*/
#define RELAY_ON 0
#define RELAY_OFF 1
/*-----( Declare objects )-----*/
/*-----( Declare Variables )-----*/
#define Relay_1  2  // Bell
#define Relay_2  3  // Green Lamp - ready
#define Relay_3  4  // Red Lamp - ALERT!
#define Relay_4  5  // Door actuator - not finished yet

void setup(){
  
      //-------( Initialize Pins so relays are inactive at reset)----
  digitalWrite(Relay_1, RELAY_OFF);
  digitalWrite(Relay_2, RELAY_ON);
  digitalWrite(Relay_3, RELAY_OFF);
  digitalWrite(Relay_4, RELAY_OFF); 

//---( THEN set pins as outputs )----  
  pinMode(Relay_1, OUTPUT);   
  pinMode(Relay_2, OUTPUT);  
  pinMode(Relay_3, OUTPUT);  
  pinMode(Relay_4, OUTPUT);    
  delay(4000); //Check that all relays are inactive at Reset
  
 
  
  pinMode(A2, OUTPUT);
  pinMode(A3, OUTPUT);
  


Serial.begin(9600);
keypad.addEventListener(keypadEvent); //add an event listener for this keypad
  lcd.init(); // initialize the lcd
  lcd.backlight();
 
  // Print a message to the LCD.
  //lcd.setCursor(0, 1);
  lcd.clear();
lcd.println("Enter Password:");
  digitalWrite(A3, HIGH);
  digitalWrite(A2, LOW);
 lcd.noBacklight(); // turn off red channel

}

void loop()
{
keypad.getKey();
}



void keypadEvent(KeypadEvent eKey){
switch (keypad.getState()){
  
case PRESSED:
lcd.setCursor(0, 1);
lcd.print("Pressed: ");
lcd.blink();
lcd.println(eKey);
switch (eKey){
case '*': checkPassword(); break;
case '#': password.reset(); break;
default: password.append(eKey);
}
}
}

void checkPassword(){
if (password.evaluate()){
  lcd.clear();
    digitalWrite(A3, LOW);
  digitalWrite(A2, HIGH);
  lcd.backlight();
lcd.println("Success!");
lcd.blink();
lcd.setCursor(0, 1);
lcd.println("Disarmed!");
lcd.blink();
digitalWrite(Relay_1, RELAY_OFF); //DISCONNETC THE SIREN IF THE PASSWORD IS CORRECT
digitalWrite(Relay_2, RELAY_ON);
digitalWrite(Relay_3, RELAY_ON);
digitalWrite(Relay_4, RELAY_ON);
password.reset();  //Reset Password
WrongAttempts = 0;  //Reset how many times it got screwed up
delay(5000);
password.reset();  //Reset Password
WrongAttempts = 0;  //Reset how many times it got screwed up

digitalWrite(Relay_1, RELAY_OFF);
digitalWrite(Relay_2, RELAY_ON);
digitalWrite(Relay_3, RELAY_OFF);
digitalWrite(Relay_4, RELAY_OFF);
lcd.clear();
lcd.backlight();
lcd.println("Armed!");
delay(3000);
lcd.clear();
lcd.println("Enter Password:");
  digitalWrite(A3, HIGH);
  digitalWrite(A2, LOW);
 lcd.noBacklight(); // turn off red channel
lcd.blink();
delay(100);
}else{
    lcd.clear();
      digitalWrite(A3, LOW);
  digitalWrite(A2, HIGH);
  lcd.backlight();
lcd.println("Wrong");
lcd.blink();
delay(1000);
lcd.clear();
lcd.backlight();
lcd.println("Armed!");
lcd.setCursor(0, 1);
lcd.println("Enter Password:");
  digitalWrite(A3, HIGH);
  digitalWrite(A2, LOW);
 lcd.noBacklight(); // turn off red channel
  password.reset();
WrongAttempts++;  



if (WrongAttempts >= 3) { //Trouble counter
digitalWrite(Relay_1, RELAY_ON); //START THE SIREN
digitalWrite(Relay_3, RELAY_ON); //START THE REDNESS
lcd.clear();
lcd.backlight();
lcd.print("Alarm Activated");
  digitalWrite(A3, HIGH);
  digitalWrite(A2, HIGH);
  password.reset();
  digitalWrite(Relay_2, RELAY_OFF); //turn off the good lamp
  password.reset();  //Reset Password
WrongAttempts = 0;  //Reset how many times it got screwed up


}


}




}
    password.reset();  //Reset Password
    WrongAttempts = 0;  //Reset how many times it got screwed up
    delay(5000);
    password.reset();  //Reset Password
    WrongAttempts = 0;  //Reset how many times it got screwed up

You liked the solution so much that you did it twice ? :slight_smile:

As to

  //-------( Initialize Pins so relays are inactive at reset)----
  digitalWrite(Relay_1, RELAY_OFF);
  digitalWrite(Relay_2, RELAY_ON);
  digitalWrite(Relay_3, RELAY_OFF);
  digitalWrite(Relay_4, RELAY_OFF); 

  //---( THEN set pins as outputs )----  
  pinMode(Relay_1, OUTPUT);   
  pinMode(Relay_2, OUTPUT);  
  pinMode(Relay_3, OUTPUT);  
  pinMode(Relay_4, OUTPUT);

I still find that strange although your capital THEN does indicate that you did it deliberately. How are your relays wired ? Does
digitalWrite(Relay_1, 1);turn the relay off ?
Can you change the wiring so that Relay_2 does not need to be on at startup, which is what is probably causing your problem.

UKHeliBob:
digitalWrite(Relay_1, 1);turn the relay off ?
Can you change the wiring so that Relay_2 does not need to be on at startup, which is what is probably causing your problem.

Relay 2 is the green light, I want it on on boot.

Do the relays have single on/off contacts or are they changeover relays ? If the latter you can change the wiring so that you don't need to hold the 'green' relay on.

Either way, you should really set the pinMode first, then the output state, not the other way round. You say that the program messes up if you do that. What happens exactly ?

UKHeliBob:
Do the relays have single on/off contacts or are they changeover relays ? If the latter you can change the wiring so that you don't need to hold the 'green' relay on.

Either way, you should really set the pinMode first, then the output state, not the other way round. You say that the program messes up if you do that. What happens exactly ?

They are SPDT so I could wire it that way but there are situations both the green and red light are on.

If you change the order when the Arduino boots ALL The relays turn on, so you get the door open, the red light, the green light and a siren, not so ideal for a security system!

The only and only issue I have with the code right now is setting a timer so the alarm doesn't go off till the end of time. I wrote it but it was past 1 am and I went to bed before I tested it any.

I'm working on casing for it in Solidworks today. Looking at keypads and a door latch on ebay. I even found the panel off an old microwave I thought about converting to use the 16x2 display and controlling the input. It has a start button! Thats all later though, and input on how to time out the alarm would be appreciated.

Your code seems to indicate that you turn on the relays by outputting a LOW signal. Setting the pinMode of a pin to OUTPUT presumably sets the output LOW, so the relays come on. As the relays are SPDT (I deliberately avoided the use of the term in case it caused confusion) why not wire them the opposite way to now so that they turn the lights etc on with a HIGH signal ? That way they will all be turned off by default at startup.

As to how to prevent the alarm sounding for ever, if you don't mind blocking the system until it times out then add delay() after the alarm has been triggered then, when the delay has finished, turn the alarm off. If you want the system to be responsive during the alarm period, perhaps to allow a master password to be entered to cancel the alarm, then you need to adopt a different approach. Look at the BlinkWithoutDelay example in teh IDE to see how to use millis() to time actions without blocking.