Shop OBEX P1 Docs P2 Docs Learn Events
Qs about the BUTTON command — Parallax Forums

Qs about the BUTTON command

stlericstleric Posts: 13
edited 2011-11-19 13:04 in BASIC Stamp
Is there a post or document that (better) explains the 'button' command? I'm finding the explanation given in the manual unclear in a couple of respects. First how do the 'downstate' and 'targetstate' parameters and the actual voltage at the pin all relate to each other? The manual refers to the button "being pressed" but that could go either way depending on how the port pins are wired up. For instance here's my little test program:
' {$STAMP BS2}
' {$PBASIC 2.5}

btnWrk   VAR   Byte
delay      CON   255

btnWrk = 0
PAUSE 5000
DEBUG "z", CR

DO
   BUTTON 0, 1, delay, 255, btnWrk, 0, Nothing0
   DEBUG "0", CR
Nothing0:
   BUTTON 1, 1, delay, 255, btnWrk, 0, Nothing1
   DEBUG "1", CR
Nothing1:
   BUTTON 2, 1, delay, 255, btnWrk, 0, Nothing2
   DEBUG "2", CR
Nothing2:

Now, when the program starts, depending on how my switch is set up and the values of the two state params I get an erroneous execution of the "DEBUG "0", CR" command.

My second question is how long is the cycle time that's used in computing the delay and autorepeat times? I'm using a BS2, but in general, what is it?


TIA,
eric

Comments

  • Mike GreenMike Green Posts: 23,101
    edited 2011-11-18 12:12
    You need a separate btnWork variable for each button. The BUTTON statement uses this variable to keep track of the state of the button and the time since the state changed last so it can implement debouncing, delay, and autorepeat times.
  • stlericstleric Posts: 13
    edited 2011-11-18 15:17
    Mike Green wrote: »
    You need a separate btnWork variable for each button. The BUTTON statement uses this variable to keep track of the state of the button and the time since the state changed last so it can implement debouncing, delay, and autorepeat times.

    Thanks for the tip. Before it was good enough but it works much better with your suggestion.

    My first question still stands though (I think).

    Thanks again,
    eric
  • cgxcgx Posts: 4
    edited 2011-11-18 15:53
    Can you write the message again, but this time using a bigger font, is just i left my glasses in the car.

    Thanks---
  • Mike GreenMike Green Posts: 23,101
    edited 2011-11-18 16:50
    The BUTTON statement is probably the most complex. I don't remember seeing a tutorial that satisfactorily explains it. There may be one and someone else may remember where to find it, but I can't help with that. Remember that the BUTTON statement includes the pin number and the desired state, so you can make it work with normally open, normally closed, switch to ground, switch to Vdd, etc.
  • Tracy AllenTracy Allen Posts: 6,662
    edited 2011-11-18 17:57
    I wrote a little bit of a take on how the BUTTON command functions as a State Machine, which you can find here.

    In answer to your question about the cycle and auto-repeat times, it is in terms of iterations, not absolute time. The BUTTON command will always be enclosed in some sort of loop that will execute repeatedly. Suppose the delay is set to 15 and rate is set to 3. Once the button is pressed, that loop has to execute 15 times before the repeat starts (to execute the target action), and after that, the loop has to execute 3 times between actions. So the time completely depends on how long it takes to execute the loop (plus the target action when it is invoked). The article linked explains (to my satisfaction at least!) how that is accomplished under the hood.

    You didn't show your complete loop in your example, but I assume that it is there with multiple button commands. As Mike pointed out, you need a separate work variable byte for each button. Also, in your test, you are disabling both the delay and rate by setting them equal to 255.

    You have downState=1 and targetState=0. That makes the button active high (down=high when pushed), but the action (DEBUG) execute when the button is not down. The targetState parameter is 1 when you want the action executed when the button is in its down state (whether that be low or high).
  • stlericstleric Posts: 13
    edited 2011-11-18 20:12
    I wrote a little bit of a take on how the BUTTON command functions as a State Machine, which you can find here.

    In answer to your question about the cycle and auto-repeat times, it is in terms of iterations, not absolute time. The BUTTON command will always be enclosed in some sort of loop that will execute repeatedly. Suppose the delay is set to 15 and rate is set to 3. Once the button is pressed, that loop has to execute 15 times before the repeat starts (to execute the target action), and after that, the loop has to execute 3 times between actions. So the time completely depends on how long it takes to execute the loop (plus the target action when it is invoked). The article linked explains (to my satisfaction at least!) how that is accomplished under the hood.

    You didn't show your complete loop in your example, but I assume that it is there with multiple button commands. As Mike pointed out, you need a separate work variable byte for each button. Also, in your test, you are disabling both the delay and rate by setting them equal to 255.
    So I didn't, actually the loop ends right after that "Nothing2" label. I was under the impression that setting only the Delay parameter to 255 disables auto-repeat but maintains delay/debounce. IOW if Delay is 255, Rate becomes "don't care". (Upon rereading the refman, in seems delay and debounce are not the same thing).
    You have downState=1 and targetState=0. That makes the button active high (down=high when pushed), but the action (DEBUG) execute when the button is not down. The targetState parameter is 1 when you want the action executed when the button is in its down state (whether that be low or high).
    See this is my problem, you can wire the port so it's normally at VDD or normally at VSS and when you push the button the port goes to (roughly) VSS or VDD respectively. Do they mean DownState = 1 -> positive logic at the pin and DownState = 0 -> negative logic?

    I just skimmed that page you linked while writing this, looks like there's some stuff there I should reread. The part about debouncing reminds me of what they say about laws and sausages.

    Thanks,
    eric
  • Mike GreenMike Green Posts: 23,101
    edited 2011-11-18 21:06
    DownState = 1 means that the I/O pin is (roughly) at Vdd when the button is pushed (down). DownState = 0 means that the I/O pin is (roughly) at Vss when the button is pushed (down). Obviously, the I/O pin is in the opposite state when the button is released (up). Using Delay = 255 does disable autorepeat and leaves debouncing working.
  • stlericstleric Posts: 13
    edited 2011-11-18 21:45
    Mike Green wrote: »
    DownState = 1 means that the I/O pin is (roughly) at Vdd when the button is pushed (down). DownState = 0 means that the I/O pin is (roughly) at Vss when the button is pushed (down). Obviously, the I/O pin is in the opposite state when the button is released (up). Using Delay = 255 does disable autorepeat and leaves debouncing working.

    Now this is clear. They should incorporate this in the refman, I have v2.2 (which I think is current) and they allude to it in a diagram. I think they should state it more explicitly.

    Thanks again,
    eric
  • Tracy AllenTracy Allen Posts: 6,662
    edited 2011-11-19 10:29
    There is debouncing in the sense that the targetAction is performed only once when the button enters or leaves the downState. It has to be detected in the opposite state before the targetAction can occur again. Now that you understand that the downState can be either a Vss or a Vdd level, depending on how the pushbuttons are hooked up, another way to explain targetState is to say that when targetState=1, the targetAction occurs when the button enters its down state, and targetState=0 means that targetAction occurs when the button leaves the down state, that is, as soon as you press the button, versus, when you release the button.

    As noted at the link, there is no debouncing in the wider sense, where it would take multiple samples at the same state before it was called stable in the state. The BUTTON command does not do that. One sample at each level is all it takes. On the other hand, there are at least a few milliseconds (which can be adjusted) in between samples in a loop, and the interval tends to swamp the bounce time of most switches.

    I don't see much point in using the BUTTON command unless you need the delay/repeat features. It uses a whole byte for the state variable, when a single bit will do. I have examples of that on the page referenced.
  • stlericstleric Posts: 13
    edited 2011-11-19 13:04
    There is debouncing in the sense that the targetAction is performed only once when the button enters or leaves the downState. It has to be detected in the opposite state before the targetAction can occur again. Now that you understand that the downState can be either a Vss or a Vdd level, depending on how the pushbuttons are hooked up, another way to explain targetState is to say that when targetState=1, the targetAction occurs when the button enters its down state, and targetState=0 means that targetAction occurs when the button leaves the down state, that is, as soon as you press the button, versus, when you release the button.
    Well, to be clear, I always knew downState could (should) be able to accomodate either positive or negative logic. What was not clear was the how.
    As noted at the link, there is no debouncing in the wider sense, where it would take multiple samples at the same state before it was called stable in the state. The BUTTON command does not do that. One sample at each level is all it takes. On the other hand, there are at least a few milliseconds (which can be adjusted) in between samples in a loop, and the interval tends to swamp the bounce time of most switches.

    I don't see much point in using the BUTTON command unless you need the delay/repeat features. It uses a whole byte for the state variable, when a single bit will do. I have examples of that on the page referenced.
    Did some more reading and I just discovered that it's possible to access the ports directly so I'm with you, I don't see any real use for the BUTTON command at least for my purposes. So to hell with the BUTTON command.

    Thanks again,
    eric
Sign In or Register to comment.