Shop OBEX P1 Docs P2 Docs Learn Events
How would I poll 14 inputs (p0 to p13) for a... — Parallax Forums

How would I poll 14 inputs (p0 to p13) for a...

denodeno Posts: 242
edited 2005-07-14 14:52 in BASIC Stamp
single button press and debounce that button press?· The "debounce" part is what I am really interested in.·

Right now I am using the following code, which works, but every once in a while I get a "bounce" and the routine will run twice instead of just one time.

'.........................................VARIABLES...............................................
button_command········ VAR·············· INS
'.........................................CONSTANTS.............................................
'.........................................MAIN PROGRAM.........................................
reset:···················· 'program will return here when finished with the selected routine
PAUSE 500·············· 'pause time to get finger off the button
DO
LOOP UNTIL button_command > 0
· SELECT button_command
··· CASE· 512····························· 'typed_char-for serial communication on PC
······ ....
··· CASE· 2048
····· ....
··· CASE· 4096
····· ....
··· CASE· 1024
····· ....
··· CASE· 8192
····· ....
··· CASE· 256
····· ...
··· CASE· 16
····· ....
··· CASE· 8
····· ....
··· CASE 1
····· ....
··· CASE 32
····· ....
··· CASE 128
····· ....
··· CASE 2
····· ....
··· CASE 4
····· ....
··· CASE 64
····· ....
· ENDSELECT
Is there a way I could use the BUTTON command?
Thank you for your input
Deno

Comments

  • Jon WilliamsJon Williams Posts: 6,491
    edited 2005-07-14 13:14
    No, you can't use the BUTTON command for that.· A better approach, in my opinion, is to use a loop to debounce the inputs and then alias the bits your return variable.· Something like this:

    myButtons··· VAR··· Word
    startProc····VAR··· myButtons.BIT0
    endProc····· VAR··· myButtons.BIT1
    idx··········VAR··· Nib·

    Main:
    · GOSUB Get_Buttons
    · IF (startProc = 1) THEN
    ··· ' start the process
    · ENDIF
    · IF (endProc = 1) THEN
    ··· ' end the process
    · ENDIF
    · GOTO Main

    Get_Buttons:
    · myButtons = %111111111111········ ' assume pressed
    · FOR idx = 1 TO 10·················' test 10 times
    ··· myButtons = myButtons & INS···· ' validate inputs
    ··· PAUSE 5
    · NEXT
    · RETURN

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Jon Williams
    Applications Engineer, Parallax
  • KenMKenM Posts: 657
    edited 2005-07-14 14:24
    Jon,
    Please help me to understand your custom debounce routine.
    For the moment, ignoring the overhead portion of your routing, if the input pin (myButtons.BIT0) is still low after 50 mS then indeed the button is low.
    What is the difference between waiting for the button to go low, pause 50 mS test again for low?
    It seems that your code basically will return low only if the button is low during the last iteration of the FOR NEXT loop.
    In my tiny programming mind, I don't see the difference between simply waiting 50 mS and updating every 5 mS as in your code?
    Also, since the GOSUB is constantly run, what is to prevent the button being pressed 40 mS into the FOR NEXT loop, then a 50/50 (?) chance myButtons.BIT0 is low during the last iteration?
    I'm sure there is a good reason, what am I missing?
    myButtons    VAR    Word
    startProc    VAR    myButtons.BIT0
    endProc      VAR    myButtons.BIT1
    idx          VAR    Nib  
    
    Main:
      GOSUB Get_Buttons
      IF (startProc = 1) THEN
        ' start the process
      ENDIF
      IF (endProc = 1) THEN
        ' end the process
      ENDIF
      GOTO Main
    
    Get_Buttons:
      myButtons = %111111111111         ' assume pressed
      FOR idx = 1 TO 10                 ' test 10 times 
        myButtons = myButtons & INS     ' validate inputs
        PAUSE 5
      NEXT
      RETURN
    
    
    

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Ken
  • Jon WilliamsJon Williams Posts: 6,491
    edited 2005-07-14 14:49
    You get better deboucing by doing several short checks than one long one -- my opinion and how I do it.· Yes, one could simplify by doing this:

    Get_Buttons:
    · myButtons =·%111111111111 & INS
    · PAUSE 50
    · myButtons = myButtons & INS
    · RETURN

    The *problem* (for me) is that PAUSE 50 is a long time and you can't see any contact bouncing during that period.· So, if you happen catch an input that has bounced closed during the two points you scanned, it looks like a valid input -- when it may not be.· By scanning more times you have more opportunites to detect an input that hasn't actually settled.

    In my original routine the loop will cause a 0 to be returned for any contact that bounces open at any time during the cycle.· Why?· Because anything ANDed with zero is 0 -- and that 0 will stick through the end of the loop.· If you look at it carefully, the subroutine will only return a 1 for a given input if the pin is high on entry to the subroutine and remains in that state all the way through it.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Jon Williams
    Applications Engineer, Parallax

    Post Edited (Jon Williams (Parallax)) : 7/14/2005 2:54:48 PM GMT
  • KenMKenM Posts: 657
    edited 2005-07-14 14:52
    Thank you for the explanation.



    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Ken
Sign In or Register to comment.