Issue using a Keypad(4X4) to reset a password.

I have been working on fixing this issue for a while but no luck. I am doing this project with Arduino Mega 2560 and a keypad 4X4 where you have already a password exist in the system, the password as it seen below is ABC, and then I thought of adding a feature where a user can create his/her own password. I approach it by first asking to type the original password that has been written already, ABC, and then if a user presses a '*' and release his finger of the button it goes to another function where it asks to reset the password and create a new one. So if the user presses '1' it do something and if '0' do another thing. The thing is that it does not print out on serial monitor the key that has been pressed. It acts so weird maybe not maybe I am missing a fundamental basis. I even I asked a friend who is a computer engineering and only found that the key that I pressed translated into a space in other words in no key is pressed.

I know that there is a password library exists which really cool but I am trying to do same basic coding so I learn by myself how to code.

Q) After looking at my code, did I miss something might be necessary I should have included ? if it is not, then what is it

here is my code:

//Backspace code:
//else if(key == 'D') {
//      --k;
//      UL[k] = 0;
//      Serial.print(UL[k]);
//     
//      }
// There are also PRESS,HOLD and RELEASE functions
//===================================

#include <Keypad.h>

unsigned long t_hold;
const byte ROWS = 4; //four rows
const byte COLS = 4; //four columns
int k = 0;
int l = 0;
int c = 0;
int b = 0;
char UL[3];
char passWord[4] ={'A','B','C'};
char chanPass[4];


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

//Columns
//The first 4 pins from the left are columns: Col1,Col2,Col3 and Col4.
//col1 is connected to 9,col2 is 8, col3 is 7 and col4 is 6 in the Arduino.

//Rows
//The rest of the four pins are rows:row1,row2, row3 and row4.
//row1 is 5, row2 is 4, row3 is 3 and row4 is 2.

//Keypad
//   1    2    3    A
//   4    5    6    B
//   7    8    9    C
//   *    0    #    D
// Keypad         :header1  header2  header3  header4  header5  header6  header7  header8 
// confiugration  :column1  column2  column3  column4  row1     row2     row3     row4
// Ardunio        :pin 9    pin 8    pin 7    pin 6    pin 5    pin 4    pin 3    pin 2 

byte rowPins[ROWS] = {5, 4, 3, 2}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {9, 8, 7, 6}; //connect to the column pinouts of the keypad

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

void setup(){
  Serial.begin(9600);
  //Serial.println("=================================");
  //Serial.println("Use three * to change password");
  //Serial.println("=================================");
  Serial.println("Please enter password: ");
  keypad.addEventListener(keypadEvent); //add an event listener for this keypad
  keypad.setHoldTime(2000); //hold time the default is one second
}

void changPass(){
  
  char key = keypad.getKey();
  
  Serial.println(" ");
  Serial.println("Changing password?");
  Serial.println("Please type '1' for Yes or '0' for No to continue");
  while (1){
      if (key != NO_KEY){
          Serial.println("I'm here men");
          chanPass[b] = key;
          b++;
          Serial.println(key);
       
          if (chanPass[b] == '0'){
             Serial.println("Don't worry! you will get back to password mode in bit");
             delay(1000);
             loop();
           }
          else if (chanPass[b] == '1'){
                Serial.println("Tyep your new password:");
                Serial.println(" ");
         
                
                 chanPass[c] = key;
                 c++;
                 if (c == 3){
                    Serial.println(" You just changed your password");
                    Serial.println("Are you stasified with the new password");
                    Serial.println("'1' for yes and '0'for no?");
                    if (key == '0'){
                      Serial.println("ok! lets' start over!");
                      changPass();
                    }
                      
                     else if (key == '1'){
                        Serial.println("Give me a minute to save the new password");
                        for(c=0; c<= 3; c++){
                          UL[c] = chanPass[c];
                        }
                        Serial.println("Done! Your new password is:");
                        Serial.print( UL[0] );
                        Serial.print( UL[1] );
                        Serial.print( UL[2] );
                    }
                  
                }
        }
      }
   }
}

void loop(){
  char key = keypad.getKey();
  
  if (key != NO_KEY ){
    
    UL[k] = key; 
    key = '*';
    Serial.print(key); 
    k++;
    
   // compare the pass word and string of UL[]
   if (k == 3 && UL[0] == passWord[0] && UL[1] == passWord[1] && UL[2] == passWord[2]){
      k =0;
     Serial.println(" ");
     Serial.println("Password is correct!");
     Serial.println("********************");
     Serial.println("Please enter password: ");
  }
     if(k == 3){
     k =0;
     Serial.println(" ");
     Serial.println("password is wrong!");
     Serial.println("********************");
     Serial.println("Please enter password:");
     }
    

      }

     } 

//take care of some special events
void keypadEvent(KeypadEvent key){
  switch (keypad.getState()){
    case PRESSED:
//      switch (key){
//        case '#':  break;
//        case '*':  
      
        break;
    case RELEASED:
     switch (key){
       case '*':  changPass();
        break;
     }
    case HOLD:
    
    //  switch (key){
      //  case '*': 
       
      //  break;
      //}
    break;
  }
}

while(1) never exits

Hey ieee488, I did that but it does not print out the character that I pressed.

Ahmadiah:
Hey ieee488, I did that but it does not print out the character that I pressed.

You should consider taking a programming class.

In changPass you read a key and store it in chanPass[b]. Next you increment b and start checking chanPass[b] which is the next location in chanPass where you did NOT store the key :wink:

Note that you also only ever get one keypress in changPass():

void changPass(){
  char key = keypad.getKey();

That one key can't possibly answer all the questions. Each time you want to read a key, try:

while((key = keypad.getKey()) != NO_KEY) ;

That will wait until a key is pressed and return the value.

ieee488:
You should consider taking a programming class.

Could you please give more detail or an example ?
Thank you ieee 488

sterretje:
In changPass you read a key and store it in chanPass[b]. Next you increment b and start checking chanPass[b] which is the next location in chanPass where you did NOT store the key :wink:

How do I check it btw ? I am a bit beginner and if you could show me code would really help.
Thanks sterretje.

johnwasser I will do what you said and update you guys on it soon!
Thank johnwasser!

I tried what you suggest johnwasser still acts as same... It exits from chanPass() function and goes to the loop() function.

Any idea ?

I think it does not even capture a pressed key in other words the interval is too short, and it goes to the loop function straight. So I typed "while(1)" before

while((key = keypad.getKey()) != NO_KEY) ;

which will loop for ever until a key is pressed and it did catch the key!

I am just cruise how come it does not work in chanPass() and works perfect in loop function?

OOPS! My mistake! That should be:

while((key = keypad.getKey()) == NO_KEY) ;

With EQUALS, not NOT EQUALS. You want to loop as long as the getKey() keeps returning NO_KEY.

My apologies for the mistake.

So far I get most of important code working, hopefully nothing goes wrong. After I am done with a specific code and I call 'loop()' function it does not run 'loop()', is it the way loop function built up and can not be called? or is it something related with 'while(1)' which will run the code for ever? I tried using 'break;' but still did not exit from while(1).

here is my code

#include <Keypad.h>

unsigned long t_hold;
const byte ROWS = 4; //four rows
const byte COLS = 4; //four columns
int k = 0;
int l = 0;
int c = 0;
int b = 0;
int a =0;
char UL[3];
char passWord[4] ={'A','B','C'};
char chanPass[8];


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

//Columns
//The first 4 pins from the left are columns: Col1,Col2,Col3 and Col4.
//col1 is connected to 9,col2 is 8, col3 is 7 and col4 is 6 in the Arduino.

//Rows
//The rest of the four pins are rows:row1,row2, row3 and row4.
//row1 is 5, row2 is 4, row3 is 3 and row4 is 2.

//Keypad
//   1    2    3    A
//   4    5    6    B
//   7    8    9    C
//   *    0    #    D
// Keypad         :header1  header2  header3  header4  header5  header6  header7  header8 
// confiugration  :column1  column2  column3  column4  row1     row2     row3     row4
// Ardunio        :pin 9    pin 8    pin 7    pin 6    pin 5    pin 4    pin 3    pin 2 

byte rowPins[ROWS] = {5, 4, 3, 2}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {9, 8, 7, 6}; //connect to the column pinouts of the keypad

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

void setup(){
  Serial.begin(9600);
  //Serial.println("=================================");
  //Serial.println("Use three * to change password");
  //Serial.println("=================================");
  Serial.println("Please enter password: ");
  keypad.addEventListener(keypadEvent); //add an event listener for this keypad
  keypad.setHoldTime(2000); //hold time the default is one second
}


void loop(){
   
        char key = keypad.getKey();
        
        if (key != NO_KEY ){
          
          UL[k] = key; 
          key = '*';
          Serial.print(key); 
          k++;
          
               // compare the pass word and string of UL[]
               if (k == 3 && UL[0] == passWord[0] && UL[1] == passWord[1] && UL[2] == passWord[2]){
                  k =0;
                 Serial.println(" ");
                 Serial.println("Password is correct!");
                 Serial.println("********************");
                 Serial.println("Please enter password: ");
              }
                 if(k == 3){
                 k =0;
                 Serial.println(" ");
                 Serial.println("password is wrong!");
                 Serial.println("********************");
                 Serial.println("Please enter password:");
                 }
          
      
            }

     
}
//take care of some special events
void keypadEvent(KeypadEvent key){
  switch (keypad.getState()){
    case PRESSED:
//      switch (key){
//        case '#':  break;
//        case '*':  
      
        break;
    case RELEASED:
     switch (key){
       case '*':  changPass();
       k =0;
        break;
     }
    case HOLD:
    
    //  switch (key){
      //  case '*': 
       
      //  break;
      //}
    break;
  }
}

void changPass(){
   c = 0;
   a = 0;
  char key = keypad.getKey();
  
  Serial.println(" ");
  delay(500);
  Serial.println("Changing password?");
  delay(500);
  Serial.println("Please type '1' for Yes or '0' for No to continue");
  while (1){
      
      while((key = keypad.getKey()) != NO_KEY){
         
              Serial.println("I'm here man");
              Serial.println(key);
              
//             chanPass[a] = key;
//             a++;

              if (key != '0' && key != '1'){
                  Serial.println("Please press '1' for yes or '0' for no");
                
              }
              
              else if (key == '0'){
                 Serial.println("Don't worry! you will get back to password mode in bit");
                  
                 //loop();
                 
               }
              else if (key == '1'){
                    delay(1000);
                    Serial.println("Tyep your new password:");
                    Serial.println(" ");
                    while(a !=3 ){
                          while((key = keypad.getKey()) != NO_KEY) {
                          chanPass[a] = key;
                          Serial.print(key);
                          a++;
                          }
                    }
              }
                     if ( a >= 3){
                        Serial.println(" ");
                        Serial.println(" You just changed your password!");
                        delay(1000);
                        Serial.println("Are you stasified with the new password");
                        delay(1000);
                        Serial.println("'1' for yes and '0'for no?");
                        while(c != 1){
                                while((key = keypad.getKey()) != NO_KEY){
                                      if (key == '0'){
                                        delay(1000);
                                        Serial.println("ok! lets' start over!");
                                        changPass();
                                       }
                                       else if (key == '1'){
                                              Serial.println("Give me a minute to save the new password");
                                              delay(1000);
                                              Serial.print(".");
                                              delay(1000);
                                              Serial.print(".");
                                              delay(1000);
                                              Serial.print(".");
                                              delay(1000);
                                              Serial.print(".");
                                              for(a=0; a<= 3; a++){
                                                UL[a] = chanPass[a];
                                              }
                                              Serial.println(" ");
                                              Serial.println("Done! Your new password is:");
                                              Serial.print( UL[0] );
                                              Serial.print( UL[1] );
                                              Serial.print( UL[2] );
                                              loop();
                                        }
                                      
                                      c++;
                                }
                                
                         }
                     } 
                        
                      
                    
                  
            }
            
        
       }
  
  }

I think I found some old post in the forum...It seems that I can call loop() but it is not the appropriate way to do it. May be I will call a function, let's call it 'fa()', in loop() and from this I can call fa() which already exits in loop().

Never call a function from within a function if you don't know what you're doing; and no offense intended but you don't know what your doing. It's called recursive calls and you can run out of memory in no time.

void fa()
{
  fa();
}

Each call to fa() will place (this action is called push) at least two bytes on the stack (part of SRAM); when fa() is finished, those two bytes are removed (this action is called pop). If you however call fa() from inside fa(), it will keep on pushing 2 bytes on the stack till the last fa() returns back to the previous one.

There are situations where recursive calls are needed but this is absolutely not one of them !!

Thanks for that! I read last night...what I meant I will solve it by doing the following:

void fa(){

somecode; 
ca();

}

void ca(){

somecode;

fa();

}

void loop(){
 
fa();

}

do you think there is something wrong with this way ? if there is, could you please show me another way?

I really appreciate your replay sterretje.

Yes, some problem. fa() calls ca() calls fa() calls ca() calls fa() and so on.

Even if the call get triggered by pressing a key in keypad ? do you have a better solution for this?
All I am trying to do is if a key is pressed go to ca() and if a certain key is pressed inside ca() go to fa().

Thank you again

I don't have a keypad so can't test.

Below a revised version of your changPass function; note that this is just a rework of that function; if it will work or not I can't say.

void changPass() {
  static byte count = 0;
  char key;
  bool fPasswordSet = false;

  Serial.println(" ");
  Serial.println("Changing password?");
  Serial.println("Please type '1' for Yes or '0' for No to continue");

  // wait for user to conform or opt out
  while (1)
  {
    key = keypad.getKey();
    if (key == NO_KEY)
      continue;

    Serial.println("I'm here men");
    Serial.println(key);

    if (key == '0')
    {
      Serial.println("Don't worry! you will get back to password mode in bit");
      delay(1000);

      // user opted out; nothing else to do
      return;
    }
    else if (key == '1')
    {
      Serial.println("Tyep your new password:");
      Serial.println(" ");

      // user confirmed, break from while loop
      break;
    }
  }

  while (fPasswordSet == false)
  {
    // get new password
    while (count != 3)
    {
      key = keypad.getKey();
      if (key != NO_KEY)
      {
        chanPass[count++] = key;
      }
    }

    // reset count for next time that we want to change password
    count = 0;

    Serial.println(" You just changed your password");
    Serial.println("Are you stasified with the new password");
    Serial.println("'1' for yes and '0'for no?");

    // wait for user to confirm new password or to opt for retry
    while (1)
    {
      key = keypad.getKey();
      if (key == NO_KEY)
        continue;

      if (key == '0')
      {
        Serial.println("ok! lets' start over!");
      }

      else if (key == '1')
      {
        Serial.println("Give me a minute to save the new password");
        for (count = 0; count <= 3; count++)
        {
          UL[count] = chanPass[count];
        }
        count = 0;

        Serial.println("Done! Your new password is:");
        Serial.print( UL[0] );
        Serial.print( UL[1] );
        Serial.print( UL[2] );

        fPasswordSet = true;
      }
    }
  }
}

Thanks man ! that's exactly what I end up doing. I had to break the condition for "while" and "if" by incrementing a variable. It did work perfect for me yesterday!

right know I am trying to do something extra resetting a password by holding "" for two seconds and will take me to a new setup. Every thing works except inside the setup routine when I includes/presses "" it starts the setup routine again which really weird because to trigger the setup routine you need to hold "*" for two seconds.

here is the setup routine:

void changPass(){
   c = 0;  //an option if the user want to keep the new password or not. 
   a = 0;  //for typing new password.
   b = 0;  //to break out from the first loop of changPass in case the desired work is done.
   k = 0;  //this is to make sure the k counting start from zero whenever enters in changPass().
  char key = keypad.getKey();
  
  Serial.println(" ");
  delay(500);
  Serial.println("Changing password?");
  delay(500);
  Serial.println("Please type '1' for Yes or '0' for No to continue");
  while (b != 1){
       
       while((key = keypad.getKey()) != NO_KEY){
              c = 0;
              //Serial.println(key);
              
              if (key != '0' && key != '1'){
                  Serial.println("Undefined key");
                  delay(500);
                  Serial.println("Please press '1' for yes or '0' for no");
                
              }
              
              else if (key == '0'){
                 Serial.println("NO");
                 Serial.println("Don't worry! you will get back to password mode in a bit");
                 delay(1000);
                 Serial.print(".");
                 delay(1000);
                 Serial.print(".");
                 delay(1000);
                 Serial.print(".");
                 delay(1000);
                 Serial.println(".");
                 b++;
                 Serial.println("********************");
                 Serial.println("Please enter password: ");
                 
                  
               }
              else if (key == '1'){
                    Serial.println("YES");
                    delay(1000);
                    Serial.println("Tyep your new password (three characters):");
                    
                    while(a !=3 ){
                          while((key = keypad.getKey()) != NO_KEY) {
                          chanPass[a] = key;
                          Serial.print(key);
                          a++;
                          }
                    }
              }
                     if ( a >= 3 && c ==0){
                        Serial.println(" ");
                        Serial.println("You just changed your password!");
                        delay(1000);
                        Serial.println("Are you stasified with the new password");
                        delay(1000);
                        Serial.println("'1' for yes and '0'for no?");
                        
                        while(c < 1){
                                while((key = keypad.getKey()) != NO_KEY){
                                      if (key == '0'){
                                         Serial.println("NO");
                                         //Serial.println(key);
                                         delay(1000);
                                         Serial.println("ok! lets' start over!");
                                         c++;
                                         a = 0;
                                         Serial.println(" ");
                                         delay(500);
                                         Serial.println("Changing password?");
                                         delay(500);
                                         Serial.println("Please type '1' for Yes or '0' for No to continue");
                                         
                                      
                                       }
                                       else if (key == '1'){
                                              Serial.println("YES");
                                              delay(500);
                                              Serial.println("Give me a minute to save the new password");
                                              delay(1000);
                                              Serial.print(".");
                                              delay(1000);
                                              Serial.print(".");
                                              delay(1000);
                                              Serial.print(".");
                                              delay(1000);
                                              Serial.print(".");
                                              for(a=0; a<= 3; a++){
                                                passWord[a] = chanPass[a];
                                              }
                                              Serial.println(" ");
                                              Serial.println("Done! Your new password is:");
                                              Serial.print( passWord[0] );
                                              Serial.print( passWord[1] );
                                              Serial.println( passWord[2] );
                                              b++;
                                              Serial.println("********************");
                                              Serial.println("Please enter password: ");
                                             
                                        }
                                   
                                       c++;
                                     
                                }
                                
                         }
                     } 
                        
            }
  
       }
  }

I might not be so weird because I suspect the that event handler catching it when you release the '*' (even after a hold).

You will have to write a simple test sketch to so how the event handler behaves; you can leave loop empty

all your current declarations

void setup()
{
  all your current setup stuff
}

void loop()
{
}

//take care of some special events
void keypadEvent(KeypadEvent key) {
  switch (keypad.getState()) {
    case PRESSED:
      Serial.print(key); Serial.println(" pressed");
      break;
    case RELEASED:
      Serial.print(key); Serial.println(" released");
      }
    case HOLD:
      Serial.print(key); Serial.println(" held");
      break;
  }
}

That way you should be able to see what happens. I suspect that what you will see is (for a long press of '*')

* pressed
* held
* released

I did solve it by doing the same as before.

my next question, is it possible to do backspace and show it on serial monitor NOT LCD?

Thank you!