Shop OBEX P1 Docs P2 Docs Learn Events
Debounce problem — Parallax Forums

Debounce problem

LeonLeon Posts: 7,620
edited 2009-10-21 20:39 in Propeller 1
Has anyone been able to get this debounce code (obex.parallax.com/objects/489/) to work properly? I'm trying to debounce five buttons on a membrane keypad, but get multiple closures even with a 100 ms delay.

Leon

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Amateur radio callsign: G1HSM
Suzuki SV1000S motorcycle

Comments

  • James LongJames Long Posts: 1,181
    edited 2009-10-21 15:35
    Leon,

    I have never used a time delay to prevent bounce. I always use an OR to prevent bounce. With the OR scenario, the program will always need to make at least two loops to see the input (button down), and will release after two successful loops without the button pressed. It takes a little more to do it that way, but does free up a cog.

    With the OR method....you must program to toggle only when the OR'd input changes to 1, not every time the input is one.

    I think you will have more luck with the OR method.

    James L

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    James L
    Partner/Designer

    Lil Brother SMT Assembly Services

    Please note: Due to economic conditions the light at the end of the tunnel will be turned off until further notice. Thanks for your understanding.
  • JackBakJackBak Posts: 45
    edited 2009-10-21 16:25
    For some nasty switch bounce environments I've been known to take James' OR loop and change it to a majority voting loop.
    That is you have to see the button down 2 out of 3 times through the loop.

    I too think the OR loop method is better.

    Jack
  • James LongJames Long Posts: 1,181
    edited 2009-10-21 16:38
    JackBak said...
    For some nasty switch bounce environments I've been known to take James' OR loop and change it to a majority voting loop.
    That is you have to see the button down 2 out of 3 times through the loop.

    I too think the OR loop method is better.

    Jack

    Jack,

    I have done that too, but wanted to get the simple across first, then if there were problems to put the majority loop in.

    James L

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    James L
    Partner/Designer

    Lil Brother SMT Assembly Services

    Please note: Due to economic conditions the light at the end of the tunnel will be turned off until further notice. Thanks for your understanding.
  • JonnyMacJonnyMac Posts: 9,202
    edited 2009-10-21 17:23
    @Leon: That's a dirt-simple object and I'm surprised (and disappointed) that you're having trouble. Can you post you code so I can see it in context? I tested the object pretty thoroughly but, as ever, reserve the right to be human and make mistakes. My programs work fine -- I'd like to see your code and if it reveals an issue with my debounce object.

    [noparse][[/noparse]Edit] Just a thought: If your debounce timing is 100ms but you accessing the debounced result more frequently than that you could be seeing false positives (from the previous scan). Perhaps what you need to do is clear the result after reading it.

    I just added this method to the version on my computer:

    pub clearbits(mask)
    
    '' Clears bits from previous scan
    '' -- uses mask to select desired bit(s)
    
      dbBits &= !mask
    

    Post Edited (JonnyMac) : 10/21/2009 5:36:25 PM GMT
  • LeonLeon Posts: 7,620
    edited 2009-10-21 17:53
    Thanks, JM. Clearing those bits fixed it! I still get some bounce with 20 ms, but it's OK with 50 ms.

    Here's my test code:

    con
    
      _clkmode = xtal1 + pll16x
      _xinfreq = 5_000_000 
    
    
      PB0   = %000001                                      
      PB1   = %000010
      PB2   = %000100
      PB3   = %001000
      PB4   = %010000
    
      MASK = PB0 | PB1 | PB2 | PB3 | PB4
    
      ACT_HI   = 1
      ACT_LO   = 0
      
      LED0  = 8
      LED1  = 9   
    
    
    obj
    
      btns          : "jm_debounce"
      debug         : "SimpleDebug"
      
    
    var
      long count
    
    pub main | b
    
      DirA[noparse][[/noparse]LED0]                    := %1
      DirA[noparse][[/noparse]LED1]                    := %1
    
      debug.start(9600)
     
      Count := 0  
      btns.init(MASK, 100, ACT_LO)
      Repeat 
        b := btns.getbits(MASK)
        btns.clearbits(MASK)
        case b
          PB0 : Count++ 
          PB1 : Count--
        waitcnt(clkfreq / 10 + cnt)
        debug.dec(Count)
        debug.putc($20)
    
    



    I need to stop it repeating if the key is held down, but that should be easy.

    Leon

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Amateur radio callsign: G1HSM
    Suzuki SV1000S motorcycle

    Post Edited (Leon) : 10/21/2009 6:11:56 PM GMT
  • JonnyMacJonnyMac Posts: 9,202
    edited 2009-10-21 18:13
    Glad things are better, but I'd still like to see how you're getting bounce. The trouble, perhaps, is that the debounce window is not synchronized with anything else. If you don't need "background" debouncing you could always do the process in a simple loop. Assuming active-high inputs, something like this should work:

    pub getbuttons(mask) | gbresult
    
      gbresult := mask
      repeat 25
        gbresult &= ina
        waitcnt(clkfreq / 1_000 + cnt)
    
      return gbresult
    


    Add ! in front of ina for active-low inputs -- result is still expressed as 1 = button pressed.
  • JonnyMacJonnyMac Posts: 9,202
    edited 2009-10-21 18:49
    Okay, if you want to see a stream of numbers on the terminal, but only one inc/dec action per button press (and hold), you can do it like this:

    pub main | bnew, bprev
    
      term.init(30, 115_200)
      waitcnt(clkfreq / 10 + cnt)
      term.tx(CLS)
    
      repeat
        bnew := getbuttons(MASK)
        case bnew
          PB0 : if (bprev <> PB0)
                  count++
          PB1 : if (bprev <> PB1)
                  count--
        bprev := bnew
        waitcnt(clkfreq / 10 + cnt)
        term.dec(count)
        term.tx(" ")
    
    
    pub getbuttons(m) | gbresult
    
      gbresult := m
      repeat 25
        gbresult &= !ina
        waitcnt(clkfreq / 1_000 + cnt)
    
      return gbresult
    


    The key is to check to see if the new key press is the same as the previous; if yes, don't do anything.
  • Cluso99Cluso99 Posts: 18,069
    edited 2009-10-21 18:52
    Leon, yes you need quite a hefty time for each press to settle, meaning both when pressed there is debounce, and when released there is debounce. That is why the PC keyboard typically used 15 keys/second repeat. You need to restart your debounce time each time you get a false transient. (I didnt look at any code above)

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Links to other interesting threads:

    · Home of the MultiBladeProps: TriBlade,·RamBlade,·SixBlade, website
    · Single Board Computer:·3 Propeller ICs·and a·TriBladeProp board (ZiCog Z80 Emulator)
    · Prop Tools under Development or Completed (Index)
    · Emulators: CPUs Z80 etc; Micros Altair etc;· Terminals·VT100 etc; (Index) ZiCog (Z80) , MoCog (6809)
    · Search the Propeller forums·(uses advanced Google search)
    My cruising website is: ·www.bluemagic.biz·· MultiBladeProp is: www.bluemagic.biz/cluso.htm
  • LeonLeon Posts: 7,620
    edited 2009-10-21 20:39
    Thanks, JM; that does just what we need.

    Leon

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Amateur radio callsign: G1HSM
    Suzuki SV1000S motorcycle
Sign In or Register to comment.