Keypad password: need help calling function

Hello all… I found a password keypad code somewhere in the Arduino playground, but I’m having some trouble modifying it.

I can get the code to work with the initial code (set at 1-2-3-4, using a 4x3 keypad from Sparkfun). For a project of mine, I would like to be able to reset that code, to a different number, with using just the keypad and some extra code.

According the the password.h file and the password code in the Arduino playground, there should be a password.set() function, I just don’t know how to call it correctly. I believe that this will solve my issue, but I’m not entirely sure.

Lastly, I suck at code in general, and am new to the Arduino. If you can help, please explain the concept I am lacking in.

This is the error that I am getting:

keypad_1234_set.cpp: In function 'void setPassword()':
keypad_1234_set:68: error: no matching function for call to 'Password::set()'
C:\Users\Robert\Desktop\arduino-1.0.1\libraries\Password/Password.h:53: note: candidates are: void Password::set(char*)

I am working with a Uno and the Arduino 1.0.1 environment.

This is the code I modified. The modified portions would be the switch case for the ‘*’ button and the setPassword(). Without that part of the code it will work, but not the way I want it to.

#include <Password.h>

#include <Keypad.h>

Password password = Password( "1234" );

const byte ROWS = 4; // Four rows
const byte COLS = 3; // Three columns
// Define the Keymap
char keys[ROWS][COLS] = {
  {'1','2','3',},
  {'4','5','6',},
  {'7','8','9',},
  {'*','0','#',}
};
// Connect keypad ROW0, ROW1, ROW2 and ROW3 to these Arduino pins.
byte rowPins[ROWS] = {5, 4, 3, 2}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {8, 7, 6}; //connect to the column pinouts of the keypad


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

#define ledPin 13

void setup(){

  digitalWrite(ledPin, OUTPUT);   // sets the LED on
  Serial.begin(9600);
  keypad.addEventListener(keypadEvent); //add an event listener for this keypad
  keypad.setDebounceTime(100);
  
}

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

//take care of some special events
void keypadEvent(KeypadEvent eKey){
  switch (keypad.getState()){
    case PRESSED:
      Serial.print("Pressed: ");
      Serial.println(eKey);
      switch (eKey){
        case '#': guessPassword(); break;  //go to guess password function\
        case '*': setPassword(); break;
         default:
               password.append(eKey);
  }
}}

void guessPassword(){
     Serial.print("Guessing password... ");
     if (password.evaluate()){
           digitalWrite(ledPin,HIGH); //activates garaged door relay
             delay(500);                
             digitalWrite(ledPin,LOW); //turns off door relay after .5 sec
           Serial.println("VALID PASSWORD "); //
              password.reset(); //resets password after correct entry
     }else{
           digitalWrite(ledPin,LOW);
           Serial.println("INVALID PASSWORD ");
              password.reset(); //resets password after INCORRECT entry
     }
} 
void setPassword(){
     Serial.print("Resetting password... ");
     if (password.set()){
           digitalWrite(ledPin,HIGH); //activates garaged door relay
             delay(500);                
             digitalWrite(ledPin,LOW); //turns off door relay after .5 sec
           Serial.println("VALID PASSWORD "); //
              password.reset(); //resets password after correct entry
     }else{
           digitalWrite(ledPin,LOW);
           Serial.println("INVALID PASSWORD ");
              password.reset(); //resets password after INCORRECT entry
     }
}

This is the password.h file I found:

#else
#include "WProgram.h"
#endif

#define MAX_PASSWORD_LENGTH 20

#define STRING_TERMINATOR '\0'

class Password {
public:
	Password(char* pass);
	
	void set(char* pass);
	bool is(char* pass);
	bool append(char character);
	void reset();
	bool evaluate();
	
	//char* getPassword();
	//char* getGuess();
	
	//operators
	Password &operator=(char* pass);
	bool operator==(char* pass);
	bool operator!=(char* pass);
	Password &operator<<(char character);
	
private:
	char* target;
	char guess[ MAX_PASSWORD_LENGTH ];
	byte currentIndex;
};

#endif

/*
|| @changelog
|| | 1.1 2009-06-17 - Alexander Brevig : Added assignment operator =, equality operators == != and insertion operator <<
|| | 1.0 2009-06-17 - Alexander Brevig : Initial Release
|| #
*/

Sorry if the post is long, but I need help.

See point 2 here - http://arduino.cc/forum/index.php/topic,97455.0.html

This is the password.h file I found:

What you posted doesn't compile (a couple of lines are missing at the beginning). Also, you need Password.cpp too.

See http://arduino.cc/en/Hacking/LibraryTutorial

keypad_1234_set.cpp: In function 'void setPassword()': keypad_1234_set:68: error: no matching function for call to 'Password::set()' C:\Users\Robert\Desktop\arduino-1.0.1\libraries\Password/Password.h:53: note: candidates are: void Password::set(char*)

Which is telling you that the call to Passowrd::set () takes an argument.

     if (password.set()){

You are not supplying an argument. Are you expecting this function to randomly set a new password? You need to tell it what the new password is to be.

PaulS:

keypad_1234_set.cpp: In function ‘void setPassword()’:
keypad_1234_set:68: error: no matching function for call to ‘Password::set()’
C:\Users\Robert\Desktop\arduino-1.0.1\libraries\Password/Password.h:53: note: candidates are: void Password::set(char*)

Which is telling you that the call to Passowrd::set () takes an argument.

     if (password.set()){

You are not supplying an argument. Are you expecting this function to randomly set a new password? You need to tell it what the new password is to be.

Thanks, this led me to get my project further along, but now I have another problem in the same area.

Here is the new code. It does compile, but now the password will reset, but it seems to clear the code rather than give a new value. The original code had it so that the user will push four numbers then “#” to enter the password. Along that same process, I planned to have the user push the four numbers then “*” to change the password. As of now, the code will reset the password, but the new or old combination will not work anymore.

#include <Password.h>

#include <Keypad.h>

Password password = Password( "1234" );

const byte ROWS = 4; // Four rows
const byte COLS = 3; // Three columns
// Define the Keymap
char keys[ROWS][COLS] = {
  {'1','2','3',},
  {'4','5','6',},
  {'7','8','9',},
  {'*','0','#',}
};
// Connect keypad ROW0, ROW1, ROW2 and ROW3 to these Arduino pins.
byte rowPins[ROWS] = {5, 4, 3, 2}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {8, 7, 6}; //connect to the column pinouts of the keypad


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

#define ledPin 13

void setup(){

  digitalWrite(ledPin, LOW);   // sets the LED on
  Serial.begin(9600);
  keypad.addEventListener(keypadEvent); //add an event listener for this keypad
  keypad.setDebounceTime(100);
}

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

//take care of some special events
void keypadEvent(KeypadEvent eKey){
  switch (keypad.getState()){
    case PRESSED:
      Serial.print("Pressed: ");
      Serial.println(eKey);
      switch (eKey){
        case '#': guessPassword(); break;
        case '*': 
        {
          password.set("eKey");
          Serial.println("Password Reset... ");
          break;
        }
         default:
               password.append(eKey);
  }
}}

void guessPassword(){
     Serial.print("Guessing password... ");
     if (password.evaluate()){
           digitalWrite(ledPin,HIGH); //activates garaged door relay
             delay(500);                
             digitalWrite(ledPin,LOW); //turns off door relay after .5 sec
           Serial.println("VALID PASSWORD "); //
              password.reset(); //resets password after correct entry
     }else{
           digitalWrite(ledPin,LOW);
           Serial.println("INVALID PASSWORD ");
              password.reset(); //resets password after INCORRECT entry
     }
}

I am assuming something is wrong with

case '*': 
        {
          password.set("eKey");
          Serial.println("Password Reset... ");
          break;
        }

To reiterate, I want to have four numbers then “*” to change a password combination, but this seems to erase everything. I tried replacing “eKey” with an actual combination (“2222”) and that worked, but that is not how I’d like this portion to function. I don’t know what to put inside of the password.set function to have the keypad change the code rather than manually change it.

http://arduino.cc/playground/Code/Password - This is a link to the password library files necessary for this project

I can’t find where I originally found the keypad code I am modifying, but the keypad library files necessary can be found here:
http://www.arduino.cc/playground/Code/Keypad

I don't know what to put inside of the password.set function to have the keypad change the code rather than manually change it.

You need to store the pressed keys somewhere, so that when the user presses * you can save this sequence to EEPROM or other permanent storage. You have of course to read back the stored password at program start.

        case '#': guessPassword(); break;
        case '*': 
        {
          password.set("eKey");
          Serial.println("Password Reset... ");
          break;
        }
         default:
               password.append(eKey);

I like consistent code. This isn't. One case has all the code on one line. One case has curly braces. Once case is missing a break statement.

Once you set the new password (and stored it somewhere so the Arduino can find it after a reset, as tuxduino points out), you need to reset the password instance, so that what it contains is removed.

          password.set("eKey");
          Serial.println("Password Reset... ");

No, it wasn't. It was changed.

          password.set("eKey");
          Serial.println("Password dhanged... ");
          password.reset();
          Serial.println("Password Reset... ");

Now, it has been reset.

PaulS:

        case '#': guessPassword(); break;

case ‘*’:
        {
          password.set(“eKey”);
          Serial.println("Password Reset… ");
          break;
        }
         default:
               password.append(eKey);



I like consistent code. This isn't. One case has all the code on one line. One case has curly braces. Once case is missing a break statement.

The reason why this code isn’t consistent is because I did not write most of this code. I wanted to keep the normal format because I know that part works. This is my way of showing that I am just modifying the code (I believe the person who made the code put his name in the header files).

Once you set the new password (and stored it somewhere so the Arduino can find it after a reset, as tuxduino points out), you need to reset the password instance, so that what it contains is removed.

          password.set("eKey");

Serial.println("Password Reset… ");



No, it wasn't. It was changed.



password.set(“eKey”);
          Serial.println("Password dhanged… ");
          password.reset();
          Serial.println("Password Reset… ");



Now, it has been reset.

I tried this and I am running into the same problem as before, where the “*” case will erase the old password and not make a new one.

I did try adding an array (lock[4]) with a for() loop to store the key presses into the lock array. The code of what I changed is below:

//take care of some special events
void keypadEvent(KeypadEvent eKey){
  int i;
  int lock[] = {0,0,0,0};
  
  switch (keypad.getState()){
    case PRESSED:
      Serial.print("Pressed: ");
      Serial.println(eKey);
      switch (eKey){
        case '#': guessPassword(); break;
        case '*': 
        {
          password.set("lock[]");
          Serial.println("Password Changed... ");
          password.reset();
          Serial.println("Password Reset... ");
          break;
        }
         default:
         {
           password.append(eKey);
           for(i = 0; i < 4; i++)
           {
               lock[i] = eKey;     // pass the key press into one of the lock elements
           }
         }
  }
}}

This does compile, but the issue is still the same. The passcode will erase once the “" key is pressed and not make a new one. “1234” will work until the "” key is pressed. My thought process for this is that when a user pushes a key, that key value will be set into one of the lock array elements.

for(i = 0; i < 4; i++)
           {
               lock[i] = eKey;     // pass the key press into one of the lock elements
          }

Why do you set all of the lock elements to the same value ?
The comment contradicts what the code does.

I tried this and I am running into the same problem as before, where the "*" case will erase the old password and not make a new one.

I just actually paid attention to what you are setting as the new password.

          password.set("eKey");

Does your keypad have the ability for you to enter 'e', 'K', or 'y'? If not, why does pressing the '*' key cause the password to be changed to 'e', 'K', 'e', 'y'?

You need to extract the current value in the password instance (if there is a method to do that) or independently save the keystrokes (correctly) and used that save set of chars (not ints) as the new password.

password.set("lock[]");

What do you expect this line to do ? Hint: a literal string containing the name of a variable has nothing to do with the variable itself. :P

PaulS:           password.set("eKey");

Does your keypad have the ability for you to enter 'e', 'K', or 'y'? If not, why does pressing the '*' key cause the password to be changed to 'e', 'K', 'e', 'y'?

You need to extract the current value in the password instance (if there is a method to do that) or independently save the keystrokes (correctly) and used that save set of chars (not ints) as the new password.

I just realized what this is doing. It is literally setting it to the values "e", "K", "e", and "y." Which is nowhere near what I want.

Looking at the top of the code:

Password password = Password( "1234" );

This is initialized after the includes. I'm thinking that 'password' should go inside the password.set() function but I can't get the code to work

password.set(password);

will produce an error saying "no matching function for call to 'Password::set(Password&)' "

password.set('password');

Will produce an error saying "invalid conversion from 'int' to 'char*' " I get the feeling that this is the more correct way of what I want to implement. I just don't know how to correctly do it. I know 'Password password' is initialized to '1234' so I am assuming that 'password' needs to change. I know that when '#' is pressed it is using the numbers pushed before that and matching it with the '1234' that is stored. I am trying to make it so that when '' is pressed, whatever number(s) (there can be up to 20 as defined in the password.h file) pressed before '' will be set as the new 'password'.

I erased the 'lock[]' portion that I was trying earlier to try this new method.

void keypadEvent(KeypadEvent eKey){

  switch (keypad.getState()){
    case PRESSED:
      Serial.print("Pressed: ");
      Serial.println(eKey);
      switch (eKey){
        case '#': guessPassword(); break;
        case '*':                       
        {
          password.set('password');
          Serial.println("Password Changed... ");
          password.reset();
          Serial.println("Password Reset... ");
          break;
        }
         default:
         {
           password.append(eKey);
         }
}}}

set('password');

has two errors: first a string is enclosed in double quotes (single quotes are for char literals), second you keep mixing variables and their string representation.

tuxduino: set('password');

has two errors: first a string is enclosed in double quotes (single quotes are for char literals), second you keep mixing variables and their string representation.

I understand the first part of your statement, but aren't single quotes what I need? I don't want string (at least I don't think I want string).

What do you mean by "mixing variables and their string representation?" My thought process is that I'm trying to pass a variable into Password password. Am I putting an int variable into pass when it's expecting char*? If so, how do I determine or change (if possible) the variable to what I need? Is it something that I would have to change in the .h files?

What do you mean by "mixing variables and their string representation?" My thought process is that I'm trying to pass a variable into Password password.

Ok, back to basics.

int a = 5;
int b = 1;
int c;

int sum(int a, int b) {
    return a + b;
}

c = sum(a, b);    // A

c = sum('a', 'b');    // B

Question1: which one between (A) and (B) won't even compile ? Why ?

About single quotes vs. double quotes:

http://stackoverflow.com/questions/3683602/single-quotes-vs-double-quotes-in-c

In short: a string literal uses double quotes, like "hallo, world!"; a char literal requires single quotes, like 'a'.