Shop OBEX P1 Docs P2 Docs Learn Events
button that has push on/off — Parallax Forums

button that has push on/off

stilgarstilgar Posts: 47
edited 2013-01-15 12:12 in Propeller 1
I have searched, even looked at the obex. If I missed it, please point me to it.
But not found code to make a toggle method that 1 button is used to toggle a output.
Example, push it ounce and it turns on a led, push it again and it turns off the led.

thanks,
stilgar

Comments

  • Invent-O-DocInvent-O-Doc Posts: 768
    edited 2012-12-23 11:19
    Check out Learn.parallax.com for details on activating an led and reading a switch. Search debounce for good switch reading code.
  • kwinnkwinn Posts: 8,697
    edited 2012-12-23 12:11
    stilgar wrote: »
    I have searched, even looked at the obex. If I missed it, please point me to it.
    But not found code to make a toggle method that 1 button is used to toggle a output.
    Example, push it ounce and it turns on a led, push it again and it turns off the led.

    thanks,
    stilgar

    Each time the button is pressed you execute the line below.
    	!outa[0]			' toggle pin 0
    

    If the pin is high it will go low, if low it will go high
  • JonnyMacJonnyMac Posts: 9,108
    edited 2012-12-24 15:20
    Pretty easy, really, and no need for a full object. Debounce your input pin and then toggle the output. Easy peazy.
    pub debounce(pin, state, ms) | mstix, cycles, t
    
      dira[pin] := 0                                                ' force to input
    
      if (state)
        state := 1                                                  ' force to 0 or 1
    
      mstix := clkfreq / 1000
        
      cycles := 0                                                   ' clear cycles count
    
      t := cnt                                                      ' sync timing
      repeat ms
        waitcnt(t += mstix)                                         ' wait 1ms
        if (ina[pin] == state)                                      ' in active state?
          ++cycles                                                  '  yes, bump counter
        else
          cycles := 0                                               '  no, clear counter
    
      if (cycles == ms)
        return true
      else
        return false
    
    if (debounce(TRIGGER, 1, 100))
        !outa[LAMP]
        pause(150)
    
  • HarpritHarprit Posts: 539
    edited 2012-12-29 12:00
    Jon:
    I have a question for you (again). We discussed this earlier but I need more assurance.
    Does a switch not make multiple connections on both the make and break condition.
    If this is the case don't we need two delays as follows:

    detect make
    wait
    detect break
    wait

    to get it right

    I am about done with the PASM book and would like to really clarify this, for the beginners, in the book.
    Thanks
    H
    H
  • kwinnkwinn Posts: 8,697
    edited 2012-12-29 12:15
    Yes, a switch will make multiple makes/breaks each time it is pressed or released. The term is "contact bounce" and that is why you need a software routine such as your delay to ensure you are reading the switch state after it stops bouncing.

    In both Spin and PASM I use a loop that reads the state of the switch and returns the state after it has remained the same x number of times through the loop.
  • HarpritHarprit Posts: 539
    edited 2012-12-29 13:21
    The problem is that the same switch is going to turn the led on and off on alternate presses.
    I think this needs 4 total delays for one complete cycle
    Am I right?

    H
  • kwinnkwinn Posts: 8,697
    edited 2012-12-29 13:45
    Harprit wrote: »
    The problem is that the same switch is going to turn the led on and off on alternate presses.
    I think this needs 4 total delays for one complete cycle
    Am I right?

    H

    Based on your first post and this question I am assuming you have:

    - A push button on a prop pin that closes a contact when it is pressed and opens the contact when released.
    - A led on another prop pin that each time the button is pressed you turn on if it was off, or off if it was on.

    You only need to:

    detect make
    wait
    detect break
    wait
    if led is on turn it off
    else turn led on
  • HarpritHarprit Posts: 539
    edited 2012-12-29 16:31
    Now it is in my head. Solid.
    Thanks
    H
  • MicksterMickster Posts: 2,694
    edited 2012-12-29 19:41
    My personal preference is to not allow such events to halt execution of the entire loop. the countdown value of OSAD must be determined based on requirements:
    'PropBASIC code
    
    DEVICE P8X32A, XTAL1, PLL16X
    FREQ 80_000_000
    
    LED PIN 1 OUTPUT
    PB PIN 2 INPUT
    OSAD VAR LONG = 0 'One Shot And Debounce
    
    PROGRAM Start
    
    Start:
    Do
         
         If PB = 1 Then
             If OSAD = 0 Then
                Toggle LED      
             Endif
             OSAD = 1000000
         
         Else
             If OSAD >0 Then
                 Dec OSAD
             Endif
         Endif
         
     'I can keep executing other stuff because the PB doesn't hold me up    
          
    Loop
    END
    
    
    
  • teganburnsteganburns Posts: 134
    edited 2012-12-30 00:31
    Made a simple program in Spin called Push. Hope this helps! and if you are just beginning i would highly suggest the parallax official guide (http://www.parallax.com/Store/Books/Propeller/tabid/171/CategoryID/45/List/0/SortField/0/Level/a/ProductID/637/Default.aspx)
  • kwinnkwinn Posts: 8,697
    edited 2012-12-30 05:33
    Mickster wrote: »
    My personal preference is to not allow such events to halt execution of the entire loop. the countdown value of OSAD must be determined based on requirements:

    [/code]

    I agree, not usually good to halt the loop. I did not want to make the answer any more complicated than necessary.

    I have a small routine that reads in all the switches once each time through the loop, debounces them, and sets the switch variable to the proper state once they are debounced. Any routine that needs to check the switch status reads the appropriate bit of the variable for the state of that switch.
  • MicksterMickster Posts: 2,694
    edited 2012-12-30 06:32
    teganburns wrote: »
    Made a simple program in Spin called Push. Hope this helps! and if you are just beginning i would highly suggest the parallax official guide (http://www.parallax.com/Store/Books/Propeller/tabid/171/CategoryID/45/List/0/SortField/0/Level/a/ProductID/637/Default.aspx)

    Unfortunately, this doesn't accomplish what the OP wants. The LED won't latch in this case. All it does is have the output equal the state of the input.

    Mickster
  • edited 2013-01-14 18:22
    Here's some pseudo code based on the code i use to debounce normally open switches. The code for 'Button1' will toggle an output.
    This code has the debounce period at the end of the routine. Most programmers place the debounce period at the beginning of the routine. Normally open switches don't randomly push themselves down so if the button is sensed down it's because it was pressed down by the operator. The delay of 1/16 second will work for most switches and can be shortened or lengthened to suit to type of switch and your needs. Military specification switches are very reliable but they can bounce around for what seems like ages before finally settling down.
    start         read system clock frequency
    
    Button1       test for Button1 down
                  if not down jump to Button2
                  Output1 := not Output1
                  debounce by waiting 1/16 of a second (clock frequency shift right 4)
                  wait for button up
                  debounce by waiting 1/16 of a second (clock frequency shift right 4)
    
    Button2       test for Button2 down
                  if not down jump to start
                  complete some action
                  debounce by waiting 1/16 of a second (clock frequency shift right 4)
                  wait for button up
                  debounce by waiting 1/16 of a second (clock frequency shift right 4)
                  
                  jump to start
    
  • cavelambcavelamb Posts: 720
    edited 2013-01-15 12:12
    This almost works right.
    The problem is that it can repeat too quickly and look like it's not latching...
    It's not really a debounce. Touchpads don't "bounce" inthe traditional sense.

    A quarter second delay at the top of the loop helped settle it down.
    That could be other code, of course, but for a demo (shrug)...

    TOTO.SPIN
    CON { Toto - Touch On/Touch Off }
      _CLKMODE=XTAL2 
      _xinfreq = 5_000_000
    VAR
      LONG MS001  , Lstate[8]
      Byte Buttons
      
    OBJ button: "QS_Button13"    ' touchpad driver
    
    PUB Toto | B                      ' local variable B
      MS001 := CLKFREQ / 1_000      ' define 1 millisec 
      button.start( @Buttons )    ' send address of Buttons
    
      Repeat B from 0 to 7          ' initialize all off
         LState[B] := 0                  '    
                    
      Repeat                                ' main loop
         waitMS(250)                    ' short delay to slow autorepeat
         Repeat B from 0 to 7       ' scan all buttons
           if Buttons & |< B            ' button pressed?
             if  LState[B] == 0         '  toggle associated LState 
               LState[B]   := 1  
             else                 
               LState[B]   := 0    
             '
              
    '  next, display results
         Repeat B from 0 to 7       ' show states for all
           if Lstate[B] ==1       
              TurnON(B+16)        
           else                   
               TurnOFF(B+16)      
       
    PUB WaitMS(W)                   ' wait for W milliseconds           
      WaitCNT (W*MS001+cnt)
      
    PUB TurnON(pin)
        dira[pin] := 1
        outa[pin] := 1
        
    PUB TurnOFF(pin)
        dira[pin] := 1
        outa[pin] := 0 
    


    Touchpad driver:
    'CON { QS_Button13.spin }
    '    { returns buttons packed bitwise in a single byte}
    VAR                  
      LONG ButtonAdr, ButtonCog, decay
      LONG Stack[ 16 ]                 ' define my stack
    
    PUB start( BAdr )                  ' start this in a new cog
      ButtonAdr := BAdr                ' save address of return byte
      if ButtonCog                     ' did the new cog start?
        cogstop(ButtonCog-1)           ' OOPS! no cog available
      ButtonCog := cognew(ButtonScan, @Stack) + 1
      decay := 4*(clkfreq/1000)
        
    PUB ButtonScan | B, B1              ' local variables
      dira [0..7] := 111111          ' all pad pins outputs    
      outa [0..7] := 111111          ' all pad pins high   
      'main loop - scan the buttons   
      Repeat                            ' loop forever
         Repeat B from 0 to 7           ' QS LEDS are pins 0-7
           dira [B] := 1                ' make pin an output 
           dira [B] := 0                ' make pin an input
           waitcnt(decay+cnt)           ' short delay for some decay
           B1 := ina[B]                 ' read the pad
           if B1 == 0                   ' 0 here means pressed
              BYTE[ButtonAdr] |= |< B   ' set bit if pressed   
           else                    
              BYTE[ButtonAdr] &= !|< B  ' clear bit if not
    
Sign In or Register to comment.