Go Down

Topic: [FEEDBACK?] Button based secret security code (Read 968 times) previous topic - next topic

MakerSelf

Dec 14, 2014, 03:19 am Last Edit: Dec 16, 2014, 04:55 pm by MakerSelf Reason: more accurate title
For a project I am working on, I need to have a button based security code.  When I searched the forum for ideas, most used keypads, but I wanted mine to be a simple, 4-button interface as the way to input the security code.

My implementation is below, and I commented it extensively to help with understanding what I am doing.  I designed it so that the number of buttons, the number of digits in the secret code, and the numerical value of each button (for the code) can be defined independently (in my example, this is 4 buttons with buttons having the values 1, 2, 3, 4, and the secret code is 7 digits long:  1234321.

While in the project I am working on, the sketch will take a set of actions when the secret code is entered correctly, I thought I would keep it simple for this sketch and the only action that is taken is that the on-board pin 13 LED is turned off when the secret code is entered correctly (it is turned on during set up).

The sketch also prints the code that has been entered so far to the serial monitor (once a second), along with if it has been matched.  There is no need for resetting the code entered periodically as the code entered is simply made up of the last X number of digits that had been entered (X depends on the length of the secret code, and in the example implementation, 7 digits).  


First, I wanted to share, should anyone else want something like this and need it.

Second, I am curious if anyone has any feedback / advice on the implementation.  


I realize there are a few inefficiencies (some things I could make variables within the functions / loops, but I wanted all the constants and variables that could be changed upfront) and also I made the boolean comparisons explicit (to enhance understanding).  Are there any bugs that I just haven't reached the case of yet? Any suggestions or improvements?

Many thanks!


Code: [Select]
/* ButtonBasedSecretCode.ino

 Implements a security code using buttons as the way to input the code.
 Number of buttons, the number of digits in the secret code, and the
 numerical value of each button (for the code) can be defined independently.

 This code can be used to take any action when the secret code is entered
 correctly.  In this example, the on board LED is on while the secret code
 has not been correctly entered, and then is turned off when the secret
 code is entered correctly.

 The sketch also prints the code that has been entered so far to the serial
 monitor, along with if it has been matched (only when matched).
 
 There is no need for resetting the code entered periodically as the code
 entered is simply made up of the last X number of digits that had been
 entered (X depends on the length of the secret code).  
 
 The circuit:
 * If no LED on the board that is attached to pin 13, attach an LED from
 pin 13 to ground (note:  this is optional, but just because this sketch uses
 the pin 13 LED as the thing in the real world to modify when the secret
 code is successfully entered)
 * For each button you choose to have for inputs into the entered code
 (in this sketch there are four buttons, but you can change that):
  -- Use a normally open button (i.e. only on when you press it, then it pops up)
  -- Connect from one side of the button to ground through a resistor
     (A decent size, in this example 1k resistors were used but you can use 10k
     or similar larger value.)
  -- Connect from the other side of the button to a digital I/O pin on the
     arduino board. (in this sketch, button 1 was connected to pin 8,
     button 2 to pin 9, button 3 to pin 10, button 4 to pin 11, but you can
     change that as long as you change it in the sketch (noted where you do
     that).
 
 Created December 2014
 by MakerSelf (makerself.wordpress.com)
 Please use, modify and be merry!

*/

//========================================

// --------CONSTANTS---------------
const int secretCodeLength = 7;
const int secretCode[secretCodeLength] = {1, 2, 3, 4, 3, 2, 1};
const int codeEnteredInitializedValue = 0;

const int numberOfButtons = 4;
const int buttonPins[numberOfButtons] = {8, 9, 10, 11};    //put your pins here
const int buttonValues[numberOfButtons] = {1, 2, 3, 4};    //put the values of the button you want to use here
const int buttonInterval = 300;                            //this is the sensitivity of the button (i.e. how quickly can you double press the button)
const byte buttonPressedState = HIGH;
const byte buttonNotPressedState = LOW;

//------------ VARIABLES---------------------
int codeEntered[secretCodeLength];                       //this gets initilized
byte buttonStates[numberOfButtons];                      //this gets initilized
unsigned long previousButtonMillis[numberOfButtons];     //this gets initilized

unsigned long previousSerialMillis;                      //for debugging or printing to the serial if that is the objective.  Gets initialized to zero when begin Serial Communication.


// ==================================================================================

// --------MAIN PROGRAM---------------
void setup() {
  //initialize and do the things you want to do normally (when the secret code
  //has not yet been pressed)
  pinMode(13, OUTPUT);                                                                       // initialize digital pin 13 as output to use the onboard LED
  digitalWrite(13, HIGH);                                                                    // Turn the onboard LED on (will stay on until the secret code is correctly entered
  
  //initialize codeEntered and Buttons
  initializeCodeEntered();                                                                   //makes the code entered be all zeros (or whatever value you define)
  initializeButtons();                                                                       //make the buttons ready to be pressed
  
  //to communicate and debug
  Serial.begin(9600);                                                                        //for debugging, to be removed in final version if you do not plan to use the serial monitor in your project.
  previousSerialMillis = 0;                                                                  //for debugging, to be removed in final version if you do not plan to use the serial monitor in your project.
} //end setup

void loop() {
  //--------REAL WORLD---------------
  readButtonsAndShiftEnteredCode();                                                           //read the buttons and add them to the entered code if a button has been pressed
  boolean isMatched = doesCodeEnteredMatchSecretCode();                                       //check to see if the code matches

  if (isMatched == true) {                                                                    //if the entered code matches the secret code, take some action
    digitalWrite(13, LOW);                                                                    //NOTE: insert the things that you want to do when there is matched code here
  }
  // NOTE: you can put an else in here if there are actions to be taken repeatedly
  // while code is not matched.  However, this will get done extremely rapidly
  // unless you put in another millis checker (i.e. only do when a certain number
  // of millis has gone by)
  //---------------------------------
  
  //--------SERIAL COMMUNICATIONS-------------                                                 //This section is unnecessary if you do not plan to use the serial monitor in your project.

  //print out the entered code and if matched.                                                
  if ((millis() - previousSerialMillis) > 1000) {                                              //only print every so often, eg. every 1 second
    for (int x = 0; x < secretCodeLength; x++){                                                //print the secretCode
       Serial.print(codeEntered[x]);  
    } //end for
    if (isMatched == true) {                                                                   //print if it matches
       Serial.print("   Matched!");
    } //end if
   Serial.println();                                                                           //make new line
   previousSerialMillis = millis();                                                            //record when you did the last print
  } //end serial printing if
  //-------------------------------------------
  
} //end loop

//



Note:  I had to snip the code because of posting maximums.  I have attached the .ino file for ease of reading it

MakerSelf

The rest of the code:

Code: [Select]
==================================================================================

// --------FUNCTIONS---------------

void readButtonsAndShiftEnteredCode() {                                                         //PURPOSE:  read the buttons and then call shiftCodeEntered if a button has been are pressed
  for (int x = 0; x < numberOfButtons; x++) {                                                   //step through all buttons
    unsigned long currentMillis = millis();
    if ((currentMillis - previousButtonMillis[x]) > buttonInterval) {                           //check to see if enough time has passed since last press
      int newButtonState = digitalRead(buttonPins[x]);                                          //if enough time has passed, read the buttons
      if (newButtonState == buttonPressedState && buttonStates[x] == buttonNotPressedState) {   //only add to the code entered if it has from NotPressed to Pressed (i.e pressing and holding does not give more than one press)
          shiftCodeEntered(buttonValues[x]);                                                    //if button was pressed, add its value to code array
          previousButtonMillis[x] = currentMillis;                                              //reset button time
      } //end button state check if
      buttonStates[x] = newButtonState;                                                         //update the button state
    } //end millis if
  } //end of number of buttons for loop
} //end readButtons

void shiftCodeEntered(int buttonValue) {                                                        //PURPOSE: shifts the code one to the left, and then adds the value of the most recent pressed button on the right
  for (int x = 0; x < secretCodeLength; x++) {                                                  //step through the code
    codeEntered[x] = codeEntered[x+1];                                                          //for each code spot, shift it to the left.  the first digit gets lost.
    if (x == (secretCodeLength-1)) {                                                            //if the last spot, add the new digit from the button press
      codeEntered[x] = buttonValue;
    } //if
  }//for
} //end shiftCodeEntered

void initializeCodeEntered() {                                                                  //PURPOSE:  initializes all spots in the code entered at the initization value, which is typically zero.  This is so you dont get an error and should be a different set of characters than is on the buttons (i.e. if the buttons are of value 1 - 4, make initilization 0) or ensure that this code will not be the secret code (i.e. can have any code except for all zeros)  
  //make each of the codes equal to the initial value it is to be assigned (typically 0)
  for (int x = 0; x < secretCodeLength; x++) {                                                  //step through the code entered
    codeEntered[x] = codeEnteredInitializedValue;                                               //for each digit, get it to the initilized value (typically zero)
  }// end for
} //end resetCodeEntered

void initializeButtons() {                                                                      //PURPOSE:  initilizes all the buttons as inputs, as not pressed, and waiting for a press
  for (int x = 0; x < numberOfButtons; x++) {                                                   //step through the buttons
    pinMode(buttonPins[x], INPUT);                                                              //for each button, make that buttons pin an input
    buttonStates[x] = buttonNotPressedState;                                                    //for each button, intialize each button as not pressed
    previousButtonMillis[x] = 0;                                                                //for each button, intialize when it was last pressed at zero (so can record future presses correctly)
  }  
 } //end initializeButtons

boolean doesCodeEnteredMatchSecretCode() {                                                      //PURPOSE:  check each digit of the entered code and the secret code against each other to see if they match
  boolean isMatched = true;                                                                     //assume the code is matched, and then make it not matched as soon as there is one different
  for (int x = 0; x < secretCodeLength; x++) {                                                  //step through the code entered
    if (isMatched == false || codeEntered[x] != secretCode[x]) {                                //if the code entered digit at that code spot does not equal the secret code digit at the code spot, or do not match in any previous checks, then make it false  
      isMatched = false;                                                                       //for each digit, get it to the initilized value (typically zero)
    } //end if
  } // end for
  return isMatched;                                                                            //return this to main program, to tell it if the code was matched or not
} //end doesCodeEnteredMatchSecretCode

Go Up