Shop OBEX P1 Docs P2 Docs Learn Events
Condition check using single switch as toggle on/off? — Parallax Forums

Condition check using single switch as toggle on/off?

Oldbitcollector (Jeff)Oldbitcollector (Jeff) Posts: 8,091
edited 2009-12-28 04:38 in Propeller 1
Ok, this is probably very simple, but it's been driving me crazy for the last hour.
Time to ask for help...

I'm trying to use a single pushbutton input as an on/off toggle in my loop.
(Thanks Nick for this headache. [noparse]:)[/noparse]

I can't seem to get wrap my head around detecting the push of button
to change from and on/off state in the loop without it detecting wrong.

something like this:

   counter++  'main loop counter

    if ina[noparse][[/noparse]play] == 1 and counter > 5
      '' Stop what I'm doing here

    if ina[noparse][[/noparse]play] == 1
      '' Continue 




Hopefully I've given and idea what I'm shooting for. Thanks in advance!

OBC

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
New to the Propeller?

Visit the: The Propeller Pages @ Warranty Void.

Comments

  • kwinnkwinn Posts: 8,697
    edited 2009-12-28 02:31
    I think you may need a variable to store the current state (on or off) of the button and flip the state each time the button is pressed and then released.
  • whickerwhicker Posts: 749
    edited 2009-12-28 02:50
    Yeah, there's really more than one programming step going on here.
    Two buttons, one "Start" and the other "Stop" are really easy to do with IF statements.


    To set up toggling with one button, you'll first need to clean up the signal with debounce.
    Microswitches don't bounce for more than about 20ms, but I've seen 12.5ms debounce times as well.

    After you can reliably detect a button press, there's a need to find the rising edge of the debounced signal.
    Then use the rising edge flag in the if statement to toggle the state of something.
  • JonnyMacJonnyMac Posts: 9,208
    edited 2009-12-28 02:55
    You should be able to XOR the present state with the input (assuming pressed = 1) to toggle the state; that said, after toggling you may want to add a short delay to prevent oscillating.
  • kwinnkwinn Posts: 8,697
    edited 2009-12-28 03:16
    In general I run through a loop where the push button switch gives me 4 consecutive high (or low) readings before I consider it a valid level. Then I look for 4 consecutive low (or high) readings, and after that I consider that the button has been pressed and released so I can update the variable (on to off, off to on, etc). Works very well in spin. Pasm needs a waitcnt in the loop.
  • whickerwhicker Posts: 749
    edited 2009-12-28 03:20
    JonnyMac:

    Button = 0, State = 0

    Button = 1, State = 0, Button XOR State = 1
    Toggle State: State = 1
    {Delay in which button is released}

    Button = 0, State = 1, Button XOR State = 1
    Toggle State: State = 0
    {Delay, button is still released}

    Button = 0, State = 0, Button XOR State = 0
  • kwinnkwinn Posts: 8,697
    edited 2009-12-28 04:25
    OBC, here is a PASM routine I used to read and debounce a couple of switches. It is called once per mSecond from the main program.

    Hope it helps.
  • SamMishalSamMishal Posts: 468
    edited 2009-12-28 04:26
    I think your problem is called Push Button BOUNCE.

    You need a DEBOUNCING routine to make sure that you are getting a CLEAN state.

    Try this routine

    Pri Get_Button_Debounced(PB_Pin) | c
    'Returns true if button is pushed assuming active low.
    'It also performs a debounce of the button.
    'the routine assumes you have alread set DirA[noparse][[/noparse]PB_Pin]~~
    'in the calling code
      c := 0
      if InA[noparse][[/noparse]PB_Pin]                                        'if not pushed return 0
         return 0
      repeat                                                'perform debouncing
         waitcnt(ClkFreq/100+cnt)                               
         if InA[noparse][[/noparse]PB_Pin]                                     'again active low
           return 0
         c++
      until c == 10
            
      repeat until InA[noparse][[/noparse]PB_Pin]  'remove this line if all you need is button state and not wait for it to be released
      return true                                                   
    
    

    The line before last can be replaced with a DELAY (e.g. Waitcnt()) to enable a button to
    register as MULTIPLE pushes if it stays down. The delay will define how fast the REPEAT RATE
    is going to be.... just like in a PC keyboard.

    If you keep the line then you will have to Push the button and Release it to register as a push.

    The routine assumes an ACTIVE LOW button.... if you want active high then reverse the
    logic whenever there is an InA[noparse]/noparse.

    Regards



    Samuel

    P.S. as you can tell from the code this will tie up the program execution if the button is pushed
    and stays pushed....I you need CONCURRENT execution then use a cog with the routine.


    Post Edited (SamMishal) : 12/28/2009 4:39:10 AM GMT
  • JonnyMacJonnyMac Posts: 9,208
    edited 2009-12-28 04:27
    Exaclty; when the button is pressed (1) you get a change; when not pressed, no change. I use XOR to do this in many programs. I do some thing like this:

    if ina[noparse][[/noparse]BTN] == Pressed
      state ^= 1
      waitcnt(cnt + (clkfreq >> 2))
    



    Of course, this kind of code must run in a loop and that's not always convenient. It would be pretty easy to create a PASM cog that monitored several inputs, toggling their state (stored in the hub) as required.
  • Oldbitcollector (Jeff)Oldbitcollector (Jeff) Posts: 8,091
    edited 2009-12-28 04:38
    Thanks guys..

    That is the elegant solution I was looking for.
    It looks like there is more going on in the code, so I've got more digging to do elsewhere.

    OBC

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    New to the Propeller?

    Visit the: The Propeller Pages @ Warranty Void.
Sign In or Register to comment.