Menu

Help with keypad lock code

Help
Pete Ross
2020-11-25
2020-12-03
  • Pete Ross

    Pete Ross - 2020-11-25

    Hello all.
    I began working on a system that involves me using a keypad. I need to be able to set a 4-digit password, save it and be able to enter it to activate a relay.

    I thought the way to go would be arrays as also shown in the demo code for keypads.
    I have understood the code and tweaked it a tiny lot but modifying it to create a password (this would be in its own subroutine) and using that pre-set code instead of hard-coding the password into the program is the issue here.

    Also I want to display this password as it is being entered on an LCD screen. Would I use a for loop for this or what?

    Here's the little I've tweaked the code variables.

     
  • mmotte

    mmotte - 2020-11-25

    I put your logic /code into a flow chart. attached
    So a couple of observations.

    1) Your passwd variable is not an array. password as an array would be Dim'med ,Dim passwd(4).
    2) In the main do loop you do 2 checks for numbers (1 and 2) that you would normally save for the password key code. You should use a key that you normally would not use (#,,A...) . Really you only need to check for one branch of making a new key and saving it.
    3) When you shutoff power or do a reset you will lose the new key. A key should be store in more permanent memory like EEprom, HEF, program memory.
    4) Once you branch, you will need to get a new pressed button otherwise you will only have 1 or 2 as key chars.
    5) Maybe you need a subroutine to get a key pressed , that would loop and wait for the button, wait for the button not to be pressed and then return the new keypress?

    That's all for now.

    73's
    Mike w9ys

     
  • Pete Ross

    Pete Ross - 2020-11-26

    Thank you so much for responding, Mike.

    I created the "getkey" subroutine but I'm not sure how to connect it with either the "create password" sub or the subs to check password.

    Here's how the subroutine looks.

     Sub getkey
    
        Do
          pressedkey = KeypadData
    
          If pressedkey <> 255 Then
            Wait 40 ms
    
            If pressedkey = 255 Then
              Exit Do
            End If
    
          End If
    
        Loop
    
      End Sub
    
     

    Last edit: Pete Ross 2020-11-26
  • Pete Ross

    Pete Ross - 2020-11-26

    Next, I did this using the flowchart as guide for the "createpassword" sub.
    But it seems to me like it has to be in a loop of some sort so that the keys pressed can be entered and saved in order.
    I also added EPRead to get the password from EEPROM and use to check.
    I haven't run this yet because it's still a bit hazy.

    Attached are the lines of the subs and the gcb file.

      Sub checkcode
    
        EPRead 1, password(1)
        EPRead 2, password(2)
        EPRead 3, password(3)
        EPRead 4, password(4)
    
        If keys(1) = password(1) Then
          If keys(2) = password(2) Then
            If keys(3) = password(3) Then
              If keys(4) = password(4) Then
    
                cls
                Print "Correct"
    
                Wait 1 s
    
    
    
                Exit Sub
    
    
              End If
            End If
          End If
        End If
    
        cls
        Print "Try again!"
        Wait 1 s
    
        End Sub
    
    
    'I'm trying to create the password here by fitting the pressed keys into an array
      Sub createpassword (In passwd)
    
        passwd = password(1)
        EPWrite 1, pressedkey
        Print pressedkey
    
        passwd = password(2)
        EPWrite 2, pressedkey
        Print pressedkey
    
        passwd = password(3)
        EPWrite 3, pressedkey
        Print pressedkey
    
        passwd = password(4)
        EPWrite 4, pressedkey
        Print pressedkey
    
        wait 1500 ms
        Cls
    
      End Sub
    
     
  • mmotte

    mmotte - 2020-11-26

    Your getkey subroutine will not work. Look at the old Main Do Loop. There is an elegant "wait" that loops until satisfied.

    Wait Until KeypadData = 255
    

    So the second not working if is replaced with this and it guards the "Exit do" (next statement until it is time to return with the keypressed value.

    Now that you have a "getkey" sub ,the main Do Loop will change

    Do
    getkey
    Check for odd key(star,hash,A...) with an if calling the Create new password
    storekey (pressedkey)
    checkcode
    loop

    Create new password does 3 things 4 times ,

    getkey
    store key in eeprom
    prints on display

    In the end it should clr the screen so I don't know the new password.

    When learning to code, step through your code with normal data that you would expect and then with extreme data that you would not expect. This hand execution will help understand the statements.

     
  • mmotte

    mmotte - 2020-11-29
    sub GetKey
      do forever
        PressedKey = KeypadData
        If PressedKey <> 255 Then
           Wait Until KeypadData = 255 'If a key is pressed, wait until it is released
          Exit do
        end if
    
      loop
    
    end sub
    
     
    • Judah Ben

      Judah Ben - 2020-11-30

      Hi, I'm working on a similar project and I'm stuck too.
      Seems like there aren't many user projects that have Keypads and LCD's used.

       

      Last edit: Judah Ben 2020-11-30
  • stan cartwright

    stan cartwright - 2020-11-29

    Where is debounce code for get key? not familiar with keyboard but you're right about eeprom
    password storage. Why does what seems simple be a headache.
    I don't like using wait.

     
  • mmotte

    mmotte - 2020-11-29

    Stan,
    That is the debounce code.
    This very simple code implementing a keylock like a door entry. It uses the gcb 'KeypadData' routine which reads a 3x4 or 4x4 keypad , cols and rows. It is not doing your usual "chase sprites around on a screen", so it has time to wait for the next keypress.

     
    • stan cartwright

      stan cartwright - 2020-11-30

      @mmotte It's just me and think wait is a waste of time :)
      I may add a numeric keypad to a glcd now there's a gcb touch function for it
      and it would maybe the same idea but with the glcd and code determining the area touched as a button.
      OK I like graphics but in demos that needed buttons, I never debounce checked them then.
      I personally think interrupts are not used enough instead of wait. Not ranting,just thoughts.
      It's like using eeprom. I tried a demo and it worked but never thought about how useful eeprom could be. The 328p I like has 1Kb eeprom! .... and I never use it :(
      Uses for eeprom is a subject but lots of pics people use have little eeprom...or ram.
      If you only use a 328 all the time. then you think it's "normal" spec when really it's quite high.
      I'll try to send a message to you.

       
  • Pete Ross

    Pete Ross - 2020-11-30

    Hello, thanks a lot for the responses. Over the past few days, I have been trying to put something together using the first tips you gave. I hadn't responded because I was still trying them out.

    Let me ask, does the program get to loop in this "getkey" sub or in the main (since it should always lookout for a key-press)?
    As my code was before, when a key is pressed, it goes into the routine for that key but at the same time records that key as the first key press which is undesirable.
    It seems to repeat still.

    Lastly, are the subs "storekey" and createpassword" going to be placed in this "getkey" sub or in the main?

    Here's how I've tried to structure the main....

    Main:
    
      do
         getkey
    
         Select case KeypadData
            Case 10
            createpassword(KeypadData)
           Case 11
            storekey(KeypadData)
            checkcode
    
         End Select
    
      loop
    
    End
    
     
  • mmotte

    mmotte - 2020-11-30

    KeypadData is the subroutine that returns which key is pressed or not pressed.

    getkey is the subroutine that returns a key press. If no key is pressed , then it waits in an infinite doLoop for a key to be pressed. The subroutine returns the key pressed in the variable , PressedKey.

    This is a simple key lock.
    I f a person wants entry to the door then he/she presses the correct 4 numbers in and the lock opens. He/she could press 1,2,3 numbers and the door won't open. He/she could press 5,6,7...many numbers in but as long as the last 4 numbers are the correct code then the lock will open. The was all implemented in the original demo code in gcb/demos/keypad solutions.

    You wanted to be able to put a new key code in. To do that you do what is called "driving a wedge" into the code that is looping in main. Your wedge is a if statement.

    If PressedKey = 10 Then CreatePassword
    

    PressedKey is the variable containing the key pressed using the getkey subroutine.
    10 is the secret button that you have chosen to start creating a new key code
    so your main will look like this in pseudo code.
    Do
    getkey
    If ..... CreatePassword ' This is the wedge or branch
    storekey (pressedkey)
    checkcode
    loop

    Notice without the wedge your Main looks almost like the original demo code.

    'I'm trying to create the password here by fitting the pressed keys into an array
      Sub createpassword (In passwd)
    
        passwd = password(1)
        EPWrite 1, pressedkey
        Print pressedkey
    
        passwd = password(2)
        EPWrite 2, pressedkey
        Print pressedkey
    
        passwd = password(3)
        EPWrite 3, pressedkey
        Print pressedkey
    
        passwd = password(4)
        EPWrite 4, pressedkey
        Print pressedkey
    
        wait 1500 ms
        Cls
    

    Here is your code for creating password. There is 2 things wrong.
    1) you are not passing a variable passwd to the routine and why put it in every position of the keycode?
    2) You are going to use getkey and get the 4 numbers and put them into their respective spots.

    ie.

        getkey
        EPWrite 1, pressedkey
        Print pressedkey
    

    Now the new keycode should be in eeprom.

    See if you can achieve this much.

     
  • stan cartwright

    stan cartwright - 2020-11-30

    Before you can change the pass key then the original pass key needs input and checking
    for being valid or no point so
    1:- a prog to to create a 4 number passcode and store in eeprom.
    2:_ a prog that inputs pass code and checks against eeprom...
    then the option to change pass code and store in eeprom
    or maybe all in one go with an eeprom byte that says first try and after it checks that and doesn't give the option to change unless valid pass code...yawn

     
  • Geoffrey Younger

    Look at the gcb demo code on github under keypad solutions, you might find something there !

     
    • stan cartwright

      stan cartwright - 2020-11-30

      yes.github is latest demos for gcb. It should be mentioned somewhere.
      I don't have this keyboard but looks better than other keypad options
      ie less wires.

       
    • Pete Ross

      Pete Ross - 2020-12-01

      Yes, I have looked through there to seek solutions before I came to the forum.
      The demos there are exactly the ones in the GCB Demos folder with some few additions.

       
  • mmotte

    mmotte - 2020-12-01

    Yes, the keylock demo code works and it exists there in the demos.

    What we are adding is the ability to change the keylock codekey. Yes, key is used in too many ways.

    What Stan thinks is that we should verify that we know the old key before putting in a new key. this the way we are used to passwords being changed on the web. Since we are "developing" the keylock program that seems like a whole step by it's self. We do have a "checkcode" subroutine but hidden in it , it also opens the lock. So now that would need to be refined and perhaps split into two sub routines, "checkcode" and "openLock".

    Meanwhile we are still learning to enter a new keycode and save it in non volatile memory. Maybe we should stick to that developement for a bit more time.

    Also ,Stan, how would you start the program the first time? What keycode would would you use? Now do we need a more general "checkcode" subroutine whether it is in eeprom or program memory ?

    OR
    We could just make it a dedicated secret path to or through "CreatePassword" subroutine.

    Stan, which ever way you choose, that is your way. That is why programming is creative and artsy.

     
  • Pete Ross

    Pete Ross - 2020-12-01

    Yes, adding a means to check if the old code is known would definitely be a plus.
    I'd have to add that at the later stages of this.

    Currently, I have modified the code this way.

    Sub createpassword
        cls
    
        getkey
        EPWrite 1, pressedkey
        Print pressedkey
    
        getkey
        EPWrite 2, pressedkey
        Print pressedkey
    
        getkey
        EPWrite 3, pressedkey
        Print pressedkey
    
        getkey
        EPWrite 4, pressedkey
        Print pressedkey
    
        Print "Done"
        wait 1500 ms
        Cls
    
      End Sub
    

    I have that print to hint me when it has gotten there.
    But what I get on the LCD is this "10101010Done".
    It runs everything at once (and even the 10 seen is the key pressed to enter this sub).

    Something similar happens for the storekey and checkcode sub. It does not wait for keys to be entered. It straight up returns "Try again!". I did many checks and improvisations but sadly nothing yet to show. It seemed simple but is giving me some real trouble. I'm still hopeful though.
    While thinking about what is going to act as a "stopper" for each keypress, FOR loops came to my mind, say having an end point of 4.

     
  • mmotte

    mmotte - 2020-12-01

    are you using the getkey subroutine I posted 3 days ago?

    Please attach your whole gcb file so I can see where you are.

     
    • Pete Ross

      Pete Ross - 2020-12-03

      Yes, I'm using that routine.
      Attached is the gcb file please.

       
  • mmotte

    mmotte - 2020-12-03

    I give.
    This program i used a TM1638 to display the numbers , so you will need to change these to the LCD you have.
    Yes, the sourceforge won't let me attach a file this morning. I don't know why?

    This does work.

    '''A demonstration program for GCGB and GCB.
    '''--------------------------------------------------------------------------------------------------------------------------------
    '''This program reads a 4 * $ keypad to create a combination lock demonstration using the keypad.
    '''The solution will stay locked until pre-programmed 4 digit code is entered.
    ''':
    '''Port c.4 switched on when locked, c.5 is switched on when unlocked
    ''':
    '''The rows of the keypad are connected to portb.3 to portb.0.
    '''The columns of the keypad are connected to c.0 to c.3
    '''The column pins must also be pulled up (high) to 5v through 10k Resistors.
    ''':
    '''PortC.4 and PortC.5 have LEDs connected via suitable resistors.
    ''':
    '''@author  Mike Otte & EvanV based on works of HughC
    '''@licence GPL
    '''@version 1.0a
    '''@date    11.30.2020
    '''********************************************************************************
    
    ; ----- Configuration
    #chip 16F886,8
    #include <TM1638c.h>
    #define TM1638_STB PortC.2
    #define TM1638_CLK PortC.1
    #define TM1638_DIO PortC.0
    
    #define KeypadPort PORTA
    
    ; ----- Constants
     ' #define KEYPAD_ROW_1 portb.3
      '#define KEYPAD_ROW_2 portb.2
      '#define KEYPAD_ROW_3 portb.1
      '#define KEYPAD_ROW_4 portb.0
      '#define KEYPAD_COL_1 portc.0
      '#define KEYPAD_COL_2 portc.1
      '#define KEYPAD_COL_3 portc.2
      '#define KEYPAD_COL_4 portc.3
    
      #define LOCKED PORTB.0
      #define UNLOCKED PORTB.1
    
    ; ----- Define Hardware settings
      'Set to locked initially
      Set LOCKED On
    
    ; ----- Variables
      Dim PressedKey As byte
      Dim KeyBuffer(4)
      Dim RESETBUFFER as Byte
    
    TM_reset
    'put in default CodeKey
    EPWrite 1, 4
    EPWrite 2, 2
    EPWrite 3, 4
    EPWrite 4, 2
    
    
    ; ----- Main body of program commences here.
      Do Forever
    
              GetKey
    
              If PressedKey =14 then      'this is the '*' on my keypad
                StoreNewCodeKey
              End if
    
    
              'Store the pressed key in a list of pressed keys
              StoreKey PressedKey
    
              'Check the list of pressed keys
              CheckCode
    
    
      Loop
    
      end
    
    ; ----- Support methods.  Subroutines and Functions
    sub GetKey
      do forever
        PressedKey = KeypadData
        If PressedKey <> 255 Then
           Wait Until KeypadData = 255 'If a key is pressed, wait until it is released
          Exit do
        end if
    
      loop
        pulseoutInv (LOCKED, 50 ms)
    end sub
    
    ''' Store a new code
    sub StoreNewCodeKey
      GetKey
      If PressedKey = 13 then     'this is the '#' on my keypad
          GetKey
          TMdec PressedKey
          EPWrite 1,PressedKey
          GetKey
          TMdec PressedKey
          EPWrite 2, PressedKey
          GetKey
          TMdec PressedKey
          EPWrite 3, PressedKey
          GetKey
          TMdec PressedKey
          EPWrite 4, PressedKey
    
       end if
          WriteChar (0 , "N")
          WriteChar (1 , "E")
          WriteChar (2 , "W")
          WriteChar (3 , " ")
          wait 2 s
    
    end sub
    '''Store a pressed key
    '''@param NewKey Key to store
      Sub StoreKey (In NewKey)
        'Move the last 3 keys along in the array
        KeyBuffer(1) = KeyBuffer(2)
        KeyBuffer(2) = KeyBuffer(3)
        KeyBuffer(3) = KeyBuffer(4)
    
        'Store the most recently pressed key at the end of the array
        KeyBuffer(4) = NewKey
        TMdec NewKey
      End Sub
    
    '''Check entered code
      Sub CheckCode
        'Check each of the last 4 pressed keys to see if it matches the correct sequence.
        'The sequence is 4242, and can be changed by editing the If commands
        EPRead 1, keydig1
        EPRead 2, keydig2
        EPRead 3, keydig3
        EPRead 4, keydig4
        If KeyBuffer(1) = keydig1 Then
          If KeyBuffer(2) = keydig2 Then
            If KeyBuffer(3) = keydig3 Then
              If KeyBuffer(4) = keydig4 Then
    
                'If the correct sequence was entered, turn off the LOCKED output, and turn on the UNLOCKED output
                Set LOCKED Off
                Set UNLOCKED On
                for ResetBuffer = 1 to 4
                    KeyBuffer(ResetBuffer) = 255
                next
                wait 3 s
                'Then, exit from the subroutine to avoid the locking code below
                'this way it stays unlocked until you press anykey
                'Exit Sub
              End If
            End If
          End If
        End If
    
    
    
        'If the program gets to this point, then the code was incorrect. Lock again!
        Set LOCKED On
        Set UNLOCKED Off
      End Sub
    
     
  • mmotte

    mmotte - 2020-12-03

    I give.
    This program i used a TM1638 to display the numbers , so you will need to change these to the LCD you have.
    Yes, the sourceforge won't let me attach a file this morning. I don't know why?

    This does work.

    '''A demonstration program for GCGB and GCB.
    '''--------------------------------------------------------------------------------------------------------------------------------
    '''This program reads a 4 * $ keypad to create a combination lock demonstration using the keypad.
    '''The solution will stay locked until pre-programmed 4 digit code is entered.
    ''':
    '''Port c.4 switched on when locked, c.5 is switched on when unlocked
    ''':
    '''The rows of the keypad are connected to portb.3 to portb.0.
    '''The columns of the keypad are connected to c.0 to c.3
    '''The column pins must also be pulled up (high) to 5v through 10k Resistors.
    ''':
    '''PortC.4 and PortC.5 have LEDs connected via suitable resistors.
    ''':
    '''@author  Mike Otte & EvanV based on works of HughC
    '''@licence GPL
    '''@version 1.0a
    '''@date    11.30.2020
    '''********************************************************************************
    
    ; ----- Configuration
    #chip 16F886,8
    #include <TM1638c.h>
    #define TM1638_STB PortC.2
    #define TM1638_CLK PortC.1
    #define TM1638_DIO PortC.0
    
    #define KeypadPort PORTA
    
    ; ----- Constants
     ' #define KEYPAD_ROW_1 portb.3
      '#define KEYPAD_ROW_2 portb.2
      '#define KEYPAD_ROW_3 portb.1
      '#define KEYPAD_ROW_4 portb.0
      '#define KEYPAD_COL_1 portc.0
      '#define KEYPAD_COL_2 portc.1
      '#define KEYPAD_COL_3 portc.2
      '#define KEYPAD_COL_4 portc.3
    
      #define LOCKED PORTB.0
      #define UNLOCKED PORTB.1
    
    ; ----- Define Hardware settings
      'Set to locked initially
      Set LOCKED On
    
    ; ----- Variables
      Dim PressedKey As byte
      Dim KeyBuffer(4)
      Dim RESETBUFFER as Byte
    
    TM_reset
    'put in default CodeKey
    EPWrite 1, 4
    EPWrite 2, 2
    EPWrite 3, 4
    EPWrite 4, 2
    
    
    ; ----- Main body of program commences here.
      Do Forever
    
              GetKey
    
              If PressedKey =14 then      'this is the '*' on my keypad
                StoreNewCodeKey
              End if
    
    
              'Store the pressed key in a list of pressed keys
              StoreKey PressedKey
    
              'Check the list of pressed keys
              CheckCode
    
    
      Loop
    
      end
    
    ; ----- Support methods.  Subroutines and Functions
    sub GetKey
      do forever
        PressedKey = KeypadData
        If PressedKey <> 255 Then
           Wait Until KeypadData = 255 'If a key is pressed, wait until it is released
          Exit do
        end if
    
      loop
        pulseoutInv (LOCKED, 50 ms)
    end sub
    
    ''' Store a new code
    sub StoreNewCodeKey
      GetKey
      If PressedKey = 13 then     'this is the '#' on my keypad
          GetKey
          TMdec PressedKey
          EPWrite 1,PressedKey
          GetKey
          TMdec PressedKey
          EPWrite 2, PressedKey
          GetKey
          TMdec PressedKey
          EPWrite 3, PressedKey
          GetKey
          TMdec PressedKey
          EPWrite 4, PressedKey
    
       end if
          WriteChar (0 , "N")
          WriteChar (1 , "E")
          WriteChar (2 , "W")
          WriteChar (3 , " ")
          wait 2 s
    
    end sub
    '''Store a pressed key
    '''@param NewKey Key to store
      Sub StoreKey (In NewKey)
        'Move the last 3 keys along in the array
        KeyBuffer(1) = KeyBuffer(2)
        KeyBuffer(2) = KeyBuffer(3)
        KeyBuffer(3) = KeyBuffer(4)
    
        'Store the most recently pressed key at the end of the array
        KeyBuffer(4) = NewKey
        TMdec NewKey
      End Sub
    
    '''Check entered code
      Sub CheckCode
        'Check each of the last 4 pressed keys to see if it matches the correct sequence.
        'The sequence is 4242, and can be changed by editing the If commands
        EPRead 1, keydig1
        EPRead 2, keydig2
        EPRead 3, keydig3
        EPRead 4, keydig4
        If KeyBuffer(1) = keydig1 Then
          If KeyBuffer(2) = keydig2 Then
            If KeyBuffer(3) = keydig3 Then
              If KeyBuffer(4) = keydig4 Then
    
                'If the correct sequence was entered, turn off the LOCKED output, and turn on the UNLOCKED output
                Set LOCKED Off
                Set UNLOCKED On
                for ResetBuffer = 1 to 4
                    KeyBuffer(ResetBuffer) = 255
                next
                wait 3 s
                'Then, exit from the subroutine to avoid the locking code below
                'this way it stays unlocked until you press anykey
                'Exit Sub
              End If
            End If
          End If
        End If
    
    
    
        'If the program gets to this point, then the code was incorrect. Lock again!
        Set LOCKED On
        Set UNLOCKED Off
      End Sub
    
     

Log in to post a comment.