PIR motion sensor with password system

I'm a newbie in using arduino and now I'm trying to make a security system with PIR motion sensor and password system. I wrote a new codes for this project and it seems like the PIr sensor just won't go off even tho there is no motion anymore. I would appreciate your help because I had been trying to figure this out for quite a long while already and still can't seem to find the problem. I'm sorry if i chose the wrong forum section because I'm not so sure where should i post this.

Here is the code(UPDATED):

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

/*------------------------------PIR------------------------------------------*/
int i;
int led = 10;
int sensor = 11;
int state = LOW;
int val = 0;
int speaker = 12;

/*-------------------------------KEYPAD---------------------------------------*/
const byte numRows= 4; //number of rows on the keypad
const byte numCols= 4; //number of columns on the keypad
char keypressed;
char keymap[numRows][numCols]=
{
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};

byte rowPins[numRows] = {5 ,4 ,3 ,2 }; //2=r1,3=r2 ( from left to right = decrease )
byte colPins[numCols] = {9 ,8 ,7 ,6 }; //9=c1,8=c2 ( from left to right = increase )
    
Keypad myKeypad= Keypad(makeKeymap(keymap), rowPins, colPins, numRows, numCols);

/*-------------------------------CONSTANTS------------------------------------*/
LiquidCrystal_I2C lcd(0x27,16,2);  //LCD

/*-------------------------------VARIABLES------------------------------------*/
String password="2580"; //Variable to store the current password
String tempPassword=""; //Variable to store the input password
int doublecheck;    //Check twice the new passoword
boolean armed = false;  //Variable for system state (armed:true / unarmed:false)
boolean input_pass;   //Variable for input password (correct:true / wrong:false)
boolean storedPassword = true;
boolean changedPassword = false;
boolean checkPassword = false;
int j = 1; //variable to index an array
/*----------------------------------------------------------------------------*/

void setup(){
  lcd.init(); //Setup the LCD's number of columns and rows 
  //Print welcome message...
  lcd.backlight();
  lcd.setCursor(0,0);
  lcd.print("Arduino Security");
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print(" opener system  ");
  lcd.setCursor(0,1);
  lcd.print(" with password  ");
  delay(1000);
  lcd.clear();
  pinMode(led, OUTPUT);
  pinMode(sensor, INPUT);
  Serial.begin(9600);
}

void loop() { //Main loop
  val = digitalRead(sensor);
  if (val == HIGH) {
      Serial.println("a");
    digitalWrite(led, HIGH);
    delay(200);
    for (double i=0; i<0.92; i+=0.01) {
      tone(speaker,sinh(i+8.294),10);
      delay(1);
    }
    
    if (state == LOW) {
      Serial.println("ALERT");
      state = HIGH;
    }
  }
  
  else {
    digitalWrite(led,LOW);
    digitalWrite(speaker,LOW);

    if (state == HIGH) {
      Serial.println("ESCAPED");
      state = LOW;
    }
  }
  unlock();
}
/********************************FUNCTIONS*************************************/
void unlock(){
  Serial.println("Check1");
  tempPassword="";
  lcd.clear();
  j=6;
  while(!checkPassword){
    lcd.setCursor(0,0);
    lcd.print("Open the door:  ");
    lcd.setCursor(0,1);
    lcd.print("PASS>");
    keypressed = myKeypad.getKey();   //Read pressed keys
    if (keypressed != NO_KEY){    //Accept only numbers and * from keypad
      if (keypressed == '0' || keypressed == '1' || keypressed == '2' || keypressed == '3' ||
      keypressed == '4' || keypressed == '5' || keypressed == '6' || keypressed == '7' ||
      keypressed == '8' || keypressed == '9' ){
        tempPassword += keypressed;
        lcd.setCursor(j,1);
        lcd.print("*");       //Put * on lcd
        j++;
        Serial.println("LockAgain");
      }
      else if (keypressed == 'A'){
        changePassword();
        Serial.println("A Pressed");
      }
      else if (keypressed=='#'){
        lcd.setCursor(0,1);
        lcd.clear();
        Serial.println("# pressed");
      }
      else if (keypressed == '*'){  //Check for password
        if (password==tempPassword){//If it's correct...
          lcd.clear();      
          lcd.setCursor(0,0);
          lcd.print("Correct password");
          lcd.setCursor(0,1);
          lcd.print("Door is unlocked");
          digitalWrite(led, LOW);
          digitalWrite(speaker,LOW);
          delay(5000);
          Serial.println("* pressed");
        }
        else{           //if it's false, retry
          tempPassword="";
          tone(speaker,500,200);
          delay(300);
          tone(speaker,500,200);
          delay(300);
          Serial.println("false");
        }        
      }
    }
  }
}


//Change current password
void changePassword(){
    Serial.println("check2");
  retry: //label for goto
  tempPassword="";
  lcd.clear();
  j=1;
  while(!changedPassword){        //Waiting for current password
    keypressed = myKeypad.getKey();   //Read pressed keys
    lcd.setCursor(0,0);
    lcd.print("CURRENT PASSWORD");
    lcd.setCursor(0,1);
    lcd.print(">");
    if (keypressed != NO_KEY){
      if (keypressed == '0' || keypressed == '1' || keypressed == '2' || keypressed == '3' ||
      keypressed == '4' || keypressed == '5' || keypressed == '6' || keypressed == '7' ||
      keypressed == '8' || keypressed == '9' ){
        tempPassword += keypressed;
        lcd.setCursor(j,1);
        lcd.print("*");
        j++; 
        Serial.println("changePassword");    
      }
      else if (keypressed=='#'){
        break;
        Serial.println("CP#");
      }
      else if (keypressed == '*'){
        j=1;
        if (password==tempPassword){
          storedPassword=false;
          newPassword();          //Password is corrent, so call the newPassword function
          break;
          Serial.println("CP*");
        }
        else{               //Try again
          tempPassword="";
          Serial.println("REtry");
          goto retry;
        }
      }
    }
  }
}
String firstpass; 


//Setup new password
void newPassword(){
  Serial.println("check3");
  tempPassword="";
  changedPassword=false;
  lcd.clear();
  j=1;
  while(!storedPassword){
    keypressed = myKeypad.getKey();   //Read pressed keys
    if (doublecheck==0){
      lcd.setCursor(0,0);
      lcd.print("SET NEW PASSWORD");
      lcd.setCursor(0,1);
      lcd.print(">");
      Serial.println("NewPAss");
    }
    else{
      lcd.setCursor(0,0);
      lcd.print("One more time...");
      lcd.setCursor(0,1);
      lcd.print(">");
      Serial.println("LCD");
    }
    if (keypressed != NO_KEY){
      if (keypressed == '0' || keypressed == '1' || keypressed == '2' || keypressed == '3' ||
      keypressed == '4' || keypressed == '5' || keypressed == '6' || keypressed == '7' ||
      keypressed == '8' || keypressed == '9' ){
        tempPassword += keypressed;
        lcd.setCursor(j,1);
        lcd.print("*");
        j++;
        Serial.println("check");
      }
      else if (keypressed=='#'){
        break;
        Serial.println("NP#");
      }
      else if (keypressed == '*'){
        if (doublecheck == 0){
          firstpass=tempPassword;
          doublecheck=1;
          newPassword();
          Serial.println("NP*");
        }
        if (doublecheck==1){
          doublecheck=0;
          if (firstpass==tempPassword){
            j=1;
            firstpass="";
            password = tempPassword; // New password saved
            tempPassword="";//erase temp password
            lcd.setCursor(0,0);
            lcd.print("PASSWORD CHANGED");
            lcd.setCursor(0,1);
            lcd.print("----------------");
              storedPassword=true;
              delay(2000);
              lcd.clear();
              break;
              Serial.println("doublecheck");
          }
          else{
            firstpass="";
            newPassword();
            Serial.println("retry");
          }
        }
      } 
    }
  }
}

better_password.ino (7.04 KB)

Too bad you failed to read the sticky to learn how to properly post code...

Then: I see "goto" statements, that's a recipe for problems and makes for seriously unreadable code. I see "delay" statements, that's a recipe for unresponsive code.

Why do you think that whatever the actual problem is it's caused by the PIR "not going off"? Why don't you put some Serial.print()s in to see exactly where the code is getting to? One immediately after the PIR read would be a good start.

What PIR are you using and how is it connected. Any pull-up or pull-down resistor fitted?

Steve

slipstick:
Why do you think that whatever the actual problem is it's caused by the PIR "not going off"? Why don't you put some Serial.print()s in to see exactly where the code is getting to? One immediately after the PIR read would be a good start.

What PIR are you using and how is it connected. Any pull-up or pull-down resistor fitted?

Steve

I did put Serial.println() in the codes before but it just print once when it detects motion and afterwards it does't print another line for it when it stop detecting motion.

HC-SR501 sensor is the one i used and no resistors fitted since while i was testing it out , it doesnt work any resistors and it still works properly.

wvmarle:
Too bad you failed to read the sticky to learn how to properly post code...

Then: I see "goto" statements, that's a recipe for problems and makes for seriously unreadable code. I see "delay" statements, that's a recipe for unresponsive code.

Im new to this forum and I'm sorry for your inconvenience.

The "goto" statements should let the codes start over again from the labels on the statements. Which "delay statements to be precise? Because most of it has its own function except for the void loop() section line 6, i removed the delay afterwards.

It sounds like it's stuck somewhere in unlockTheDoor() and doesn't complete the loop(). So it only ever reads the PIR once and never sees the 'off'.

Unfortunately life is far too short to try to decipher code full of gotos. I stopped using them a good 30 years ago. So I'll have to leave you to work out where exactly it sticks. A load more Serial.prints should do the job.

Steve

HC-SR501 sensors have a pot to adjust the PIR's 'on' time.

You must turn the 'on time' pot fully anticlockwise if you want the Arduino to be in control of timing.
Even with the pot fully anticlockwise, there is still a delay of a few seconds.

Leave the 'sensitivity' pot in the middle. It does NOT adjust senstivity, but a lockout time for false triggers.
Leo..

slipstick:
It sounds like it's stuck somewhere in unlockTheDoor() and doesn't complete the loop(). So it only ever reads the PIR once and never sees the 'off'.

Unfortunately life is far too short to try to decipher code full of gotos. I stopped using them a good 30 years ago. So I'll have to leave you to work out where exactly it sticks. A load more Serial.prints should do the job.

Steve

To be honest here, I'm quite guideless now and I had been thinking about and trying to solve this problem for almost a week already. If I can't really sort this out , can you teach me how to do it properly. Thank you very much.

slipstick:
It sounds like it's stuck somewhere in unlockTheDoor() and doesn't complete the loop(). So it only ever reads the PIR once and never sees the 'off'.

Unfortunately life is far too short to try to decipher code full of gotos. I stopped using them a good 30 years ago. So I'll have to leave you to work out where exactly it sticks. A load more Serial.prints should do the job.

Steve

It seems like that it doesn't read the "else" at the void loop() section, any suggestions or any ideas why? Even if I set a delay for it to not go and read the void unlockTheDoor() first, it just seems like the "else" function are not read.

Wawa:
HC-SR501 sensors have a pot to adjust the PIR's 'on' time.

You must turn the 'on time' pot fully anticlockwise if you want the Arduino to be in control of timing.
Even with the pot fully anticlockwise, there is still a delay of a few seconds.

Leave the 'sensitivity' pot in the middle. It does NOT adjust senstivity, but a lockout time for false triggers.
Leo..

It was set like that when it first delivered to my house.

If you have a multimeter it would be a good idea to check if the PIR output ever does go low. You can also put Serial.print() immediately after the digitalRead() to do the same thing.

That Serial.print() would also let you see how long it takes to complete a loop. It may be that with all the delays in your program it's just very slow to respond to changes. Perhaps even so slow that it misses the OFF periods.

Steve

slipstick:
If you have a multimeter it would be a good idea to check if the PIR output ever does go low. You can also put Serial.print() immediately after the digitalRead() to do the same thing.

That Serial.print() would also let you see how long it takes to complete a loop. It may be that with all the delays in your program it's just very slow to respond to changes. Perhaps even so slow that it misses the OFF periods.

Steve

I don't have a multimeter and the loop complete instantly when I uploaded the code by checking the serial.println(). I removed every delay in the void loop() and changed the delay value at the void setup(). Imma try to add Serial.print() after digitalRead() now.

slipstick:
If you have a multimeter it would be a good idea to check if the PIR output ever does go low. You can also put Serial.print() immediately after the digitalRead() to do the same thing.

That Serial.print() would also let you see how long it takes to complete a loop. It may be that with all the delays in your program it's just very slow to respond to changes. Perhaps even so slow that it misses the OFF periods.

Steve

OK new update, now that I had changed the delay value lower and the sensor actually do go LOW afterwards but only that it won't sensor again anymore.

Update 2#
Nevermind, it actually doesn't sensor anything anymore. Also whenever I pressed # key , it would turn on the sensor by running the loop() again. It shows the serial.print that i added after digitalRead().

Update 3#
I kind of fixed other problems but now the sensor just won't go back to "LOW" state. It only senses when the code reuploaded and never senses again, i think the loop() isnt looping. And yes, the void loop() isnt looping becuz it got lead to the void unlock(), very confused right now.

As the title said, apparently the project I had been doing met this error where the void loop() isnt looping anymore.

Here's the code from setup till loop:

void setup(){
  lcd.init(); //Setup the LCD's number of columns and rows 
  //Print welcome message...
  lcd.backlight();
  lcd.setCursor(0,0);
  lcd.print("Arduino Security");
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print(" opener system  ");
  lcd.setCursor(0,1);
  lcd.print(" with password  ");
  delay(1000);
  lcd.clear();
  pinMode(led, OUTPUT);
  pinMode(sensor, INPUT);
  pinMode(speaker,OUTPUT);
  Serial.begin(9600);
}

void loop() { //Main loop
  Serial.println("n");
  val = digitalRead(sensor);
  if (val == HIGH) {
      Serial.println("a");
    digitalWrite(led, HIGH);
    delay(200);
    for (double i=0; i<0.92; i+=0.01) {
      tone(speaker,sinh(i+8.294),10);
      delay(1);
    }
    
    if (state == LOW) {
      Serial.println("ALERT");
      state = HIGH;
    }
  }
  
  else {
    digitalWrite(led,LOW);
    digitalWrite(speaker,LOW);

    if (state == HIGH) {
      Serial.println("ESCAPED");
      state = LOW;
    }
  }
/********************************FUNCTIONS*************************************/
  Serial.println("Check1");
  tempPassword="";
  lcd.clear();
  j=6;
  while(!checkPassword){
    lcd.setCursor(0,0);
    lcd.print("Open the door:  ");
    lcd.setCursor(0,1);
    lcd.print("PASS>");
    keypressed = myKeypad.getKey();   //Read pressed keys
    if (keypressed != NO_KEY){    //Accept only numbers and * from keypad
      if (keypressed == '0' || keypressed == '1' || keypressed == '2' || keypressed == '3' ||
      keypressed == '4' || keypressed == '5' || keypressed == '6' || keypressed == '7' ||
      keypressed == '8' || keypressed == '9' ){
        tempPassword += keypressed;
        lcd.setCursor(j,1);
        lcd.print("*");       //Put * on lcd
        j++;
        Serial.println("LockAgain");
      }
      else if (keypressed == 'A'){
        changePassword();
        Serial.println("A Pressed");
      }
      else if (keypressed=='#'){
        lcd.setCursor(0,1);
        lcd.clear();
        Serial.println("# pressed");
      }
      else if (keypressed == '*'){  //Check for password
        if (password==tempPassword){//If it's correct...
          lcd.clear();      
          lcd.setCursor(0,0);
          lcd.print("Correct password");
          lcd.setCursor(0,1);
          lcd.print("Door is unlocked");
          digitalWrite(led, LOW);
          digitalWrite(speaker,LOW);
          delay(5000);
          Serial.println("* pressed");
        }
        else{           //if it's false, retry
          tempPassword="";
          tone(speaker,500,200);
          delay(300);
          tone(speaker,500,200);
          delay(300);
          Serial.println("false");
        }        
      }
    }
  }
}

Your help is really appreciated since I'm in hurry with this project and I had been trying to solve it for a long time already and still can't get any idea. According to the Serial.println() that i added, it loops for the first time and never loops again.

Too much missing information. E.g. you have "while (!checkPassword)" but there's nothing in that code that ever defines checkPassword or sets it to any value.

Of course there might be something in the parts of the program you didn't bother posting but I can't be bothered trying to guess what you might have done.

Steve

for (double i=0; i<0.92; i+=0.01)

Stick with integers.

Post ALL the code. Post a wiring diagram, and links to the sensors and other modules.

Note: the keyword "void" used before a function means that the function returns no value.

I'm in hurry with this project

That is part of your problem, but not our problem. You need to take some time, learn the programming language and for posting, read the "How to use this forum" sticky.

while(!checkPassword){

Was that supposed to be a function call. You know with parenthesis on the end?

Get rid of all those goto statements, and post your (now untangled and much more readable) code.

Fair chance that in the process of untangling this mess your problems disappear.

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

/*------------------------------PIR------------------------------------------*/
int i;
int led = 10;
int sensor = 11;
int state = LOW;
int val = 0;
int speaker = 12;

/*-------------------------------KEYPAD---------------------------------------*/
const byte numRows= 4; //number of rows on the keypad
const byte numCols= 4; //number of columns on the keypad
char keypressed;
char keymap[numRows][numCols]=
{
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};

byte rowPins[numRows] = {5 ,4 ,3 ,2 }; //2=r1,3=r2 ( from left to right = decrease )
byte colPins[numCols] = {9 ,8 ,7 ,6 }; //9=c1,8=c2 ( from left to right = increase )
    
Keypad myKeypad= Keypad(makeKeymap(keymap), rowPins, colPins, numRows, numCols);

/*-------------------------------CONSTANTS------------------------------------*/
LiquidCrystal_I2C lcd(0x27,16,2);  //LCD

/*-------------------------------VARIABLES------------------------------------*/
String password="2580"; //Variable to store the current password
String tempPassword=""; //Variable to store the input password
int doublecheck;    //Check twice the new passoword
boolean armed = false;  //Variable for system state (armed:true / unarmed:false)
boolean input_pass;   //Variable for input password (correct:true / wrong:false)
boolean storedPassword = true;
boolean changedPassword = false;
boolean checkPassword = false;
int j = 1; //variable to index an array
/*----------------------------------------------------------------------------*/

void setup(){
  lcd.init(); //Setup the LCD's number of columns and rows 
  //Print welcome message...
  lcd.backlight();
  lcd.setCursor(0,0);
  lcd.print("Arduino Security");
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print(" opener system  ");
  lcd.setCursor(0,1);
  lcd.print(" with password  ");
  delay(1000);
  lcd.clear();
  pinMode(led, OUTPUT);
  pinMode(sensor, INPUT);
  Serial.begin(9600);
}

void loop() { //Main loop
  val = digitalRead(sensor);
  if (val == HIGH) {
      Serial.println("a");
    digitalWrite(led, HIGH);
    delay(200);
    for (i=700; i<800; i+=2) {
      tone(speaker,i,10);
      delay(1);
    }
    
    if (state == LOW) {
      Serial.println("ALERT");
      state = HIGH;
    }
  }
  
  else {
    digitalWrite(led,LOW);
    digitalWrite(speaker,LOW);

    if (state == HIGH) {
      Serial.println("ESCAPED");
      state = LOW;
    }
  }

/********************************FUNCTIONS*************************************/
  Serial.println("Check1");
  retry:
  tempPassword="";
  lcd.clear();
  j=6;
  while(!checkPassword){
    lcd.setCursor(0,0);
    lcd.print("Open the door:  ");
    lcd.setCursor(0,1);
    lcd.print("PASS>");
    keypressed = myKeypad.getKey();   //Read pressed keys
    if (keypressed != NO_KEY){    //Accept only numbers and * from keypad
      if (keypressed == '0' || keypressed == '1' || keypressed == '2' || keypressed == '3' ||
      keypressed == '4' || keypressed == '5' || keypressed == '6' || keypressed == '7' ||
      keypressed == '8' || keypressed == '9' ){
        tempPassword += keypressed;
        lcd.setCursor(j,1);
        lcd.print("*");       //Put * on lcd
        j++;
        Serial.println("LockAgain");
      }
      else if (keypressed == 'A'){
        changePassword();
        Serial.println("A Pressed");
      }
      else if (keypressed=='#'){
        lcd.setCursor(0,1);
        lcd.clear();
        Serial.println("# pressed");
      }
      else if (keypressed == '*'){  //Check for password
        if (password==tempPassword){//If it's correct...
          lcd.clear();      
          lcd.setCursor(0,0);
          lcd.print("Correct password");
          lcd.setCursor(0,1);
          lcd.print("Door is unlocked");
          digitalWrite(led, LOW);
          digitalWrite(speaker,LOW);
          delay(5000);
          Serial.println("* pressed");
          goto retry;
          
        }
        else{           //if it's false, retry
          tempPassword="";
          tone(speaker,500,200);
          delay(300);
          tone(speaker,500,200);
          delay(300);
          Serial.println("false");
          goto retry;
        }        
      }
    }
  }
}


//Change current password
void changePassword(){
    Serial.println("check2");
  tempPassword="";
  lcd.clear();
  j=1;
  while(!changedPassword){        //Waiting for current password
    keypressed = myKeypad.getKey();   //Read pressed keys
    lcd.setCursor(0,0);
    lcd.print("CURRENT PASSWORD");
    lcd.setCursor(0,1);
    lcd.print(">");
    if (keypressed != NO_KEY){
      if (keypressed == '0' || keypressed == '1' || keypressed == '2' || keypressed == '3' ||
      keypressed == '4' || keypressed == '5' || keypressed == '6' || keypressed == '7' ||
      keypressed == '8' || keypressed == '9' ){
        tempPassword += keypressed;
        lcd.setCursor(j,1);
        lcd.print("*");
        j++; 
        Serial.println("changePassword");    
      }
      else if (keypressed=='#'){
        break;
        Serial.println("CP#");
      }
      else if (keypressed == '*'){
        j=1;
        if (password==tempPassword){
          storedPassword=false;
          newPassword();          //Password is corrent, so call the newPassword function
          break;
          Serial.println("CP*");
        }
        else{               //Try again
          tempPassword="";
          Serial.println("REtry");
        }
      }
    }
  }
}
String firstpass; 


//Setup new password
void newPassword(){
  Serial.println("check3");
  tempPassword="";
  changedPassword=false;
  lcd.clear();
  j=1;
  while(!storedPassword){
    keypressed = myKeypad.getKey();   //Read pressed keys
    if (doublecheck==0){
      lcd.setCursor(0,0);
      lcd.print("SET NEW PASSWORD");
      lcd.setCursor(0,1);
      lcd.print(">");
      Serial.println("NewPAss");
    }
    else{
      lcd.setCursor(0,0);
      lcd.print("One more time...");
      lcd.setCursor(0,1);
      lcd.print(">");
      Serial.println("LCD");
    }
    if (keypressed != NO_KEY){
      if (keypressed == '0' || keypressed == '1' || keypressed == '2' || keypressed == '3' ||
      keypressed == '4' || keypressed == '5' || keypressed == '6' || keypressed == '7' ||
      keypressed == '8' || keypressed == '9' ){
        tempPassword += keypressed;
        lcd.setCursor(j,1);
        lcd.print("*");
        j++;
        Serial.println("check");
      }
      else if (keypressed=='#'){
        break;
        Serial.println("NP#");
      }
      else if (keypressed == '*'){
        if (doublecheck == 0){
          firstpass=tempPassword;
          doublecheck=1;
          newPassword();
          Serial.println("NP*");
        }
        if (doublecheck==1){
          doublecheck=0;
          if (firstpass==tempPassword){
            j=1;
            firstpass="";
            password = tempPassword; // New password saved
            tempPassword="";//erase temp password
            lcd.setCursor(0,0);
            lcd.print("PASSWORD CHANGED");
            lcd.setCursor(0,1);
            lcd.print("----------------");
              storedPassword=true;
              delay(2000);
              lcd.clear();
              break;
              Serial.println("doublecheck");
          }
          else{
            firstpass="";
            newPassword();
            Serial.println("retry");
          }
        }
      } 
    }
  }
}

This is the full code.