Shop OBEX P1 Docs P2 Docs Learn Events
Debouncing the SX/B Example of Keypad in the help file? — Parallax Forums

Debouncing the SX/B Example of Keypad in the help file?

Brian CarpenterBrian Carpenter Posts: 728
edited 2006-11-08 03:59 in General Discussion
Can anyone point me in the right direction for debouncing the kepad example in the SX/B help file

GET_KEY:
  tmpB1 = 0                                     ' reset keyboard value
  Keys = %0000_0111                             ' activate first row
  TRIS_Keys = %1111_0000                        ' refresh IO state
  PLP_Keys = %0000_1111                         ' pull-up input pins

  FOR tmpB2 = 1 TO 4                            ' scan four rows
    IF Col1 = Yes THEN EXIT                     ' check buttons on column
    INC tmpB1                                   ' update key value
    IF Col2 = Yes THEN EXIT
    INC tmpB1
    IF Col3 = Yes THEN EXIT
    INC tmpB1
    IF Col4 = Yes THEN EXIT
    INC tmpB1
    Keys = Keys >> 1                            ' select next row
    Keys = Keys | %0000_1000                    ' clear previous row
  NEXT
  RETURN tmpB1

This is the pertinate code snippet i believe.· I know that i need to sample the value and make sure that i get the same value for atleast a 2 cycles.·

Any body done this before?

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔


It's Only A Stupid Question If You Have Not Googled It First!!

Comments

  • YendorYendor Posts: 288
    edited 2006-10-24 19:25
    Have you checked out Gunther's Book? See pgs 99/100. It's in assembly but you should get the drift.

    Although not the exact subroutine he mentions, there is similar source code is in the TUT019.src file in the downloads section.

    It's basically checking the bit, delaying (typ 20-30msec), and see if it's still pressed after the delay.

    Here's an interesting link with some higher level examples.

    http://www.ganssle.com/debouncing.pdf

    ...or Google "switch debounce software" [noparse]:o[/noparse])
    Rodney
  • Sparks-R-FunSparks-R-Fun Posts: 388
    edited 2006-10-24 19:37
    Altitudeap,

    I would try something like this:
        KeyChanged = 0                        ' Initialize Key Change bit variable.
         FirstKey = GET_KEY                   ' Remember the First Key value seen.
    
        For i = 1 to 5                        ' Loop to debounce keypad inputs.
          theKey = GET_KEY                    ' Get the current keypad value.
            If theKey <> FirstKey Then        ' Detect keypad changes.
                KeyChanged = 1                ' Indicate that a key has changed.
            EndIf
        Next i                                ' Repeat
    
        If KeyChanged = 1 Then                ' Detect keypad changes and...
            theKey = 16                       ' Treat it as if no key was pressed.
        EndIf
    
    


    You will need to declare i and FirstKey as byte variables and KeyChanged as a bit variable.

    - Sparks
  • BeanBean Posts: 8,129
    edited 2006-10-24 21:28
    GET_KEY:
    
      lastKey = $FF
      DO
        tmpB1 = 0                                     ' reset keyboard value
        Keys = %0000_0111                             ' activate first row
        TRIS_Keys = %1111_0000                        ' refresh IO state
        PLP_Keys = %0000_1111                         ' pull-up input pins
    
        FOR tmpB2 = 1 TO 4                            ' scan four rows
          IF Col1 = Yes THEN EXIT                     ' check buttons on column
          INC tmpB1                                   ' update key value
          IF Col2 = Yes THEN EXIT
          INC tmpB1
          IF Col3 = Yes THEN EXIT
          INC tmpB1
          IF Col4 = Yes THEN EXIT
          INC tmpB1
          Keys = Keys >> 1                            ' select next row
          Keys = Keys | %0000_1000                    ' clear previous row
        NEXT
     
        IF tmpB1 = lastKey THEN EXIT
        PAUSE 20
        lastKey = tmpB1
      LOOP
      RETURN tmpB1
    
    

    Here is how I would do it. Adjust the PAUSE value as needed.·NOTE this is untested code [noparse];)[/noparse]

    Bean.


    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Cheap used 4-digit LED display with driver IC·www.hc4led.com

    Low power SD Data Logger www.sddatalogger.com
    SX-Video Display Modules www.sxvm.com

    "People who are willing to trade their freedom for·security deserve neither and will lose both." Benjamin Franklin
    ·
  • Brian CarpenterBrian Carpenter Posts: 728
    edited 2006-11-06 05:14
    Ok guys,· Thanks for all the help thus far.

    I have used Bean's Code and also Sparks - R - Fun



    I cant get the desired results

    What i am trying to make it do:::

    If TheKey = LastKey loop until it does not As soon as it does not.· Return the new value that does not match



    For instance.... if no key is pressed, TheKey will be 16 and will continue to be 16 while nothing is pressed.

    Now this is where it gets a little tricky

    As soon as a key is pressed. Lets say 3.··· The 'TheKey' value has changed but i dont want it to be returned until 'TheKey' = 16 again. meaning that the button was released.

    ·So once the key is released it will return '3' in the 'TheKey' value.· and then it will continue returning 16 until another key is RELEASED



    Any ideas on how this can be done?

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔


    It's Only A Stupid Question If You Have Not Googled It First!!

    Post Edited (altitudeap) : 11/6/2006 5:29:40 AM GMT
  • BeanBean Posts: 8,129
    edited 2006-11-06 13:40
    
    
    
    
     
    key VAR Byte
     
    oldKey  VAR Byte ' Temp used by GET_KEY routine
    tmpB1   VAR Byte ' Temp used by GET_KEY routine
    lastKey VAR Byte ' Used by GET_KEY routine, DO NOT USE IN MAIN CODE
    thisKey VAR Byte ' Used by GET_KEY routine, DO NOT USE IN MAIN CODE
     
    Start:
      lastKey = 16
      DO
        key = GET_KEY
        IF key <> 16 THEN
          ' Do whatever
        ENDIF
        ' Do other processing
      LOOP  
    END
     
     
    GET_KEY:
    
      oldKey = $FF
      DO
        tmpB1 = 0                                     ' reset keyboard value
        Keys = %0000_0111                             ' activate first row
        TRIS_Keys = %1111_0000                        ' refresh IO state
        PLP_Keys = %0000_1111                         ' pull-up input pins
    
        FOR tmpB2 = 1 TO 4                            ' scan four rows
          IF Col1 = Yes THEN EXIT                     ' check buttons on column
          INC tmpB1                                   ' update key value
          IF Col2 = Yes THEN EXIT
          INC tmpB1
          IF Col3 = Yes THEN EXIT
          INC tmpB1
          IF Col4 = Yes THEN EXIT
          INC tmpB1
          Keys = Keys >> 1                            ' select next row
          Keys = Keys | %0000_1000                    ' clear previous row
        NEXT
     
        IF tmpB1 = oldKey THEN EXIT
        PAUSE 20
        oldKey = tmpB1
      LOOP
    
     
      thisKey = tmpB1
     
      IF thisKey = 16 THEN
        IF lastKey <> 16 THEN
          thisKey = lastKey
          lastKey = 16
          RETURN thisKey
        ENDIF
      ENDIF
      lastKey = thisKey
      RETURN 16
    


    Try this...

    Bean.


    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Cheap used 4-digit LED display with driver IC·www.hc4led.com

    Low power SD Data Logger www.sddatalogger.com
    SX-Video Display Modules www.sxvm.com

    "People who are willing to trade their freedom for·security deserve neither and will lose both." Benjamin Franklin
    ·
  • Brian CarpenterBrian Carpenter Posts: 728
    edited 2006-11-07 04:53
    Thanks Bean


    This is what i now have.
    DEVICE          SX28, OSC4MHZ, TURBO, STACKX, OPTIONX
    FREQ            4_000_000
    
    ' -------------------------------------------------------------------------
    ' IO Pins
    ' -------------------------------------------------------------------------
    Keys            VAR     RC                      ' keyboard scan port
    TRIS_Keys       VAR     TRIS_C
    PLP_Keys        VAR     PLP_C
    Col1            VAR     Keys.7                  ' column inputs
    Col2            VAR     Keys.6
    Col3            VAR     Keys.5
    Col4            VAR     Keys.4
    Restart  Var RA.1 
    
    ' -------------------------------------------------------------------------
    ' Constants
    ' -------------------------------------------------------------------------
    Yes             CON     0                       ' active low input
    No              CON     1
    ' -------------------------------------------------------------------------
    ' Variables
    ' -------------------------------------------------------------------------
    theKey          VAR     Byte                    ' from keypad, 0 - 16
    oldKey   VAR  Byte    ' Temp used by GET_KEY routine
    row             VAR     Byte                    ' keyboard scan row
    tmpB1           VAR     Byte                    ' subroutine work vars
    tmpB2           VAR     Byte
    tmpW1           VAR     Word
    VendStatus Var Word
    VendAmm  Var byte (16)
    i  Var byte
    LastKey  VAr byte
    key   VAR  Byte
     
     
    ' =========================================================================
      PROGRAM Start
    ' =========================================================================
    ' -------------------------------------------------------------------------
    ' Subroutine Declarations
    ' -------------------------------------------------------------------------
    GET_KEY         SUB     0                       ' get key from pad
    DELAY           SUB     1, 2                    ' delay in milliseconds
    ' -------------------------------------------------------------------------
    ' Program Code
    ' -------------------------------------------------------------------------
     
    Start:
      lastKey = 16
    PUT vendAmm, 25, 25, 25, 25, 25, 25, 25, 25, 25, 20, 20, 20, 15, 15, 10, 10
      Main:
       DO
        key = GET_KEY
         IF key <> 16 THEN
             IF key < 16 THEN
          tmpB1 = 1 SHL Key
          ENDIF
       tmpW1 = 1 SHL Key
       DEC VendAmm(key)
         IF vendAmm(key) = 0 THEN
            VendStatus = VendStatus OR tmpW1
         ENDIF  
    '---------Reseting the Flags that indicate empty vend merchandise
        
         ENDIF
       Break 
     IF Restart = 0 then
      goto start 
     Endif  
      LOOP  
    END
     
     
      
       
    ' -------------------------------------------------------------------------
    ' Subroutine Code
    ' -------------------------------------------------------------------------
    ' This routine works by activating each row, then scanning each column.
    ' If a particular row/column junction is not active (pressed), the key
    ' value is incremented and the scan continues.  As soon as a key is found,
    ' the routine exits.  If no key is pressed the routine will exit with a key
    ' value of 16.
    GET_KEY:
      oldKey = $FF
      DO
        tmpB1 = 0                                     ' reset keyboard value
        Keys = %0000_0111                             ' activate first row
        TRIS_Keys = %1111_0000                        ' refresh IO state
        PLP_Keys = %0000_1111                         ' pull-up input pins
        FOR tmpB2 = 1 TO 4                            ' scan four rows
          IF Col1 = Yes THEN EXIT                     ' check buttons on column
          INC tmpB1                                   ' update key value
          IF Col2 = Yes THEN EXIT
          INC tmpB1
          IF Col3 = Yes THEN EXIT
          INC tmpB1
          IF Col4 = Yes THEN EXIT
          INC tmpB1
          Keys = Keys >> 1                            ' select next row
          Keys = Keys | %0000_1000                    ' clear previous row
        NEXT
     
        IF tmpB1 = oldKey THEN EXIT
        PAUSE 20
        oldKey = tmpB1
      LOOP
     
      thekey = tmpB1
     
      IF thekey = 16 THEN
        IF lastKey <> 16 THEN
          thekey = lastKey
          lastKey = 16
          RETURN thekey
        ENDIF
      ENDIF
      lastKey = thekey
      RETURN 16
    
     
     
    ' -------------------------------------------------------------------------
    ' Use: DELAY ms
    ' -- 'ms' is delay in milliseconds, 1 - 65535
    DELAY:
      IF __PARAMCNT = 1 THEN
        tmpW1 = __PARAM1                            ' save byte value
      ELSE
        tmpW1 = __WPARAM12                          ' save word value
      ENDIF
      PAUSE tmpW1
      RETURN
    
     
    

    Man i love the SX Debug feature.· As i press and hold the button i can see that the SX has noticed the state change of the switch and then just as i release it, it DEC the value in associated register.· What i cant seem to make it show me is the··Value for VendStatus.· Should i be able to see that in the register somewhere.· Maybe my code is not making the bit in the associated location go high.·· ie if the value in register 2 goes to 0 the Value in VendStatus should be 0000_0000_0000_0100

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔


    It's Only A Stupid Question If You Have Not Googled It First!!
  • Brian CarpenterBrian Carpenter Posts: 728
    edited 2006-11-08 03:59
    ok Great News. I used the Watch VendStatus,16,UBIN And it works. This Debug is cool

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔


    It's Only A Stupid Question If You Have Not Googled It First!!
Sign In or Register to comment.