Shop OBEX P1 Docs P2 Docs Learn Events
Changing frequency of blinking LED with button — Parallax Forums

Changing frequency of blinking LED with button

akuakuakuaku Posts: 11
edited 2011-10-04 11:50 in General Discussion
Hi, I'm having a bit of difficulty programming with my BS2 stamp.
I'm trying to get a light to blink in one-second intervals when the button is pushed and held - then blink in 50-millisecond intervals the next time the button is pushed and held.
I've been trying to use subroutines to get this to work, but they seem to overlap each other (i.e. when I press the button once there is a 50-millisecond blink followed by a one-second blink).
I've copied what I have on my stamp editor below.
Does anyone have any suggestions?

Thanks



DO

DEBUG ? IN3

GOSUB blink_at_50
GOSUB blink_at_1000

LOOP

blink_at_50:
IF (IN3 = 1 ) THEN
HIGH 15
PAUSE 50
LOW 15
PAUSE 50
ELSE
PAUSE 100
ENDIF
RETURN

blink_at_1000:

IF (IN3 = 1 ) THEN
HIGH 15
PAUSE 1000
LOW 15
PAUSE 1000
ELSE
PAUSE 100
ENDIF
RETURN

Comments

  • ercoerco Posts: 20,259
    edited 2011-10-03 16:38
    Define the problem better. What does it do when the button isn't pressed. Nothing?
  • ercoerco Posts: 20,259
    edited 2011-10-03 16:45
    Try something more like this:

    blink_at_50:
    IF IN3=0 THEN blink_at_1000' not pushed, skip ahead
    HIGH 15
    PAUSE 50
    LOW 15
    PAUSE 50
    goto blink_at_50


    blink_at_1000:
    IF IN3=0 THEN blink_at_50' not pressed, skip back
    HIGH 15
    PAUSE 1000
    LOW 15
    PAUSE 1000
    goto blink_at_1000
  • $WMc%$WMc% Posts: 1,884
    edited 2011-10-03 17:41
    IN3 = 1 not pressed (pulled high)
    IN3 = 0 pressed (pulled low )
    '
    This asumes a 10k pull-up resister on the input PIN 3 and a 220 ohm resister pulling the input low through the button.
    '
    '
    Main:
    '
    IF IN3 = 0 THEN
    HIGH 15
    PAUSE 50
    LOW 15
    ELSE
    HIGH 15
    PAUSE 1000
    LOW 15
    ENDIF
    GOTO Main
    1024 x 668 - 19K
  • akuakuakuaku Posts: 11
    edited 2011-10-03 18:04
    erco, what you have provided works much better then I had originally posted. But, for some reason it doesn't always go to the next command (sometimes it repeats the command). It seems a bit random when changing from the two commands.
    For example i will push the button and it will blink at 50 then I'll push it again and it will go at 1000 then i'll push it a third time and it will blink at 1000 again instead of returning to 50.

    WMc. Yes that is the setup that I am currently using. A second pause is needed I think after the low too, but that's another interesting approach.

    Thanks
  • akuakuakuaku Posts: 11
    edited 2011-10-03 18:08
    I'm also hoping to add more 'time pause values' the two have been sorted out.
  • kwinnkwinn Posts: 8,697
    edited 2011-10-03 18:36
    I am not that familiar with stamp basic but this does sound like a problem caused by switch bounce. Does the basic input statement automatically debounce the input signal?
  • RDL2004RDL2004 Posts: 2,554
    edited 2011-10-03 18:36
    It could be some kind of switch bounce problem.
  • RDL2004RDL2004 Posts: 2,554
    edited 2011-10-03 19:04
    Heh, posted at the same time. Kwinn beat me.
    Here is some button debounce code I use. It's set up for four buttons. JohnnyMac is the originator.
    I think it was from one of the N&V columns, but I'm not sure which one.

    ' {$STAMP BS2}
    ' {$PBASIC 2.5}
    
    
    BtnBus  VAR INA
    
    
    btns    VAR Nib
    idx     VAR Nib
    
    
    Main:
    
      DO
        GOSUB Get_Buttons
        DEBUG HOME
        DEBUG "Inputs = ", IBIN4 btns
        PAUSE 50
      LOOP
    
    Get_Buttons:
    
      btns = %1111
        FOR idx = 1 TO 5
        btns = btns & ~BtnBus
        PAUSE 5
        NEXT
      RETURN
    
  • ercoerco Posts: 20,259
    edited 2011-10-03 19:26
    He has a 100 ms minimum pause in each routine. Once triggered, that should filter out most bounce.

    akuaku: please confirm that you have the pullup resistor configuration suggested by WMc.
  • akuakuakuaku Posts: 11
    edited 2011-10-03 19:32
    hey erco, yes I have it setup like WMc suggested... It's the same setup from chapter 3, activity 3 in the "whats a micro controller" booklet, so there shouldn't be anything wrong with the circuitry.
    .
  • akuakuakuaku Posts: 11
    edited 2011-10-03 19:34
    Thanks Rick, I'm pretty new at this though and I just got confused looking at it... am I supposed to combine it with what erco had suggested earlier?
  • ercoerco Posts: 20,259
    edited 2011-10-03 20:01
    Try a small capacitor across your switch leads, like 0.1 uF.
  • RDL2004RDL2004 Posts: 2,554
    edited 2011-10-03 20:15
    Hi,

    It's just an example of how to debounce buttons. It's possible that contact bounce in your switch is causing some of your problems.

    If you connect your buttons to pins 0,1,2,3 (INA) and just run the code by itself you will see what it does. Less buttons will work. Oh, and the code is set up for buttons wired as active low (they connect the pin to ground when pressed).

    Here is an example of two different ways to run a subroutine based on which button is pressed. Changing your blink rate could be in the subroutines. One is run from an If Then, the other from a Select Case.

    Again, you can just run the code as is with nothing but the buttons hooked up to see how it works.
  • akuakuakuaku Posts: 11
    edited 2011-10-03 22:06
    I don't know how to plug the capacitor in this circuit...
    I was thinking... would this be easier to program with a Potentiometer (having it blink more frequently when turning the dial one way, and less frequent the other?). This could also work for what I am trying to do.
  • RDL2004RDL2004 Posts: 2,554
    edited 2011-10-03 23:05
    I played around with this for a couple of hours. It seemed to me that the Stamp was spending too much time in pauses to respond correctly to button presses.

    So what I did was put the blinking in two different loops, one slow and one fast, and I used TOGGLE instead of PAUSE. This lets the Stamp be checking the buttons constantly while the LED just sits there either on or off. It pretty much switches instantly from fast to slow and back again when you press the button.

    I kept the debounce code, but only used one button (it can do up to 4 as is), you could probably just use the PBasic BUTTON command instead of the "Get_Buttons" subroutine, but I didn't have time to mess with that. Remember that the way this program is coded, the button needs to be active low and on pin 0, the LED needs to be on pin 15. You could change that of course.
  • ercoerco Posts: 20,259
    edited 2011-10-03 23:52
    From akuaku's first post saying push & hold, I took it that nothing should happen (ie, LED off) when the button is not pressed, which is not supported in some code offered here.

    BUT he never clarified that. akuaku? Pot or switch can be made to work, as you like.
  • RDL2004RDL2004 Posts: 2,554
    edited 2011-10-04 07:29
    You're right erco, they did say "pushed and held". I guess that just didn't register. I also got the order wrong, I started fast instead of slow. Anyway, it was easy enough to change.

    For demo purposes this code is okay, but there's probably more efficient ways to do this, especially if you wanted to expand to more than two blinking rates. It's still early in the morning and I didn't want to stress my brain that hard just yet :)

    I don't really program Stamps very much, so I'm not that good at it and it takes me a while to figure out how to do stuff, but I definitely learned a bit from this (i.e do not type gosub when you mean goto).

    Here is the push and hold code.
  • akuakuakuaku Posts: 11
    edited 2011-10-04 07:46
    Sorry for not clarifying, the idea was to have it off when the button is not held down, and to have the blink intervals switch every time i press the button (having it continuously blink for as long as I hold the button down).
  • RDL2004RDL2004 Posts: 2,554
    edited 2011-10-04 08:11
    Okay, then MoreButtonsPushHold.bs2 will do what you want. You can improve it from there. The button needs to be active low and on pin 0. There can't be anything on pins 1, 2, or 3 as they are set up as buttons also. They might need pull up resistors, not sure. The LED and its resistor go on pin 15. Give it a try.
  • akuakuakuaku Posts: 11
    edited 2011-10-04 09:37
    Rick, this isn't working for me... I have my 220 ohm resistor plugged into P3, but I tried it plugged into P0 and it still wasn't lighting up when the button was pressed.
    I'm curious about using the potentiometer now though, so I'm going to post another topic about it.
    Thanks for your help guys -
    Still, if anyone knows a simple way of using the button to do this please continue to post.
  • RDL2004RDL2004 Posts: 2,554
    edited 2011-10-04 10:25
    Maybe somebody else could check my program and verify that I didn't mess something up, but I think that If you have the button and the LED wired correctly it will work.

    You need two resistors and a normally open button wired as "active low" as in $WMc%'s diagram.
    340 x 444 - 27K
  • Tracy AllenTracy Allen Posts: 6,666
    edited 2011-10-04 10:28
    How about this? You may have to wait 1 second to press the button a second time, to wait for the inner DO loop to clear. The debounce time is 50 ms.
    ' {$STAMP BS2}
    ' {$PBASIC 2.5}
    dur VAR WORD
    N VAR WORD
    DO
      LOW 15  ' LED on this pin, lit when high
      DO : LOOP UNTIL IN3=0   ' switch on this pin, low when pressed
      IF dur = 50 THEN dur=1000 ELSE dur=50  ' toggle the desired rate
      DO
        TOGGLE 15
        PAUSE dur
      LOOP UNTIL IN3=1
    LOOP
    
    Here is a variation that is more responsive, in the sense that the latency is reduced to 50 ms.
    ' {$STAMP BS2pe}
    ' {$PBASIC 2.5}
    dur VAR BYTE
    ix VAR BYTE
    DO
      LOW 15  ' LED on this pin, lit when high
      DO : LOOP UNTIL IN3=0   ' switch on this pin, low when pressed
      IF dur = 1 THEN dur=20 ELSE dur=1  ' going to count 50ms intervals
      DO
        TOGGLE 15
        FOR ix = 1 TO dur
          PAUSE 49       ' 49 to allow for the FOR:NEXT timing
          IF IN3=1 THEN ix=dur   ' break out as soon as button up is detected
        NEXT
      LOOP UNTIL IN3=1
    LOOP
    
  • akuakuakuaku Posts: 11
    edited 2011-10-04 11:01
    whoa awesome! Thanks Tracy! Is it possible to add more blinking rates? If so, how would I go about it?
  • Tracy AllenTracy Allen Posts: 6,666
    edited 2011-10-04 11:50
    Sure. You have to define the sequence. The line in the 2nd program that defines the alternate times is,
    IF dur=1 THEN dur=20 ELSE dur=1 ' in units of 50ms
    Replace that with in-line code, or with a subroutine, that selects the different durations in the sequence you want. Possible hint, create an index variable or even a random variable that steps from 0 up to however many you want, and use that with the LOOKUP command to kick back the durations.
Sign In or Register to comment.