Shop OBEX P1 Docs P2 Docs Learn Events
Simple Button — Parallax Forums

Simple Button

TheVigTheVig Posts: 41
edited 2012-10-31 13:45 in Propeller 1
Could I get a simple example of when I push a button on a pin the serial terminal displays that button push?

Thanks,
Jim
«1

Comments

  • Mike GreenMike Green Posts: 23,101
    edited 2012-10-29 07:12
    Here's a simple example of a routine to sense the state of a pushbutton:
    CON xinfreq = 5_000_000   ' assume you have a standard Propeller setup with a 5MHz crystal
        clkmode = xtal1 + pll16x
        buttonPin = 3   ' change this for whatever pin you have your pushbutton hooked to
        buttonOn = 1   ' change this to 0 if your pushbutton grounds the input pin when pushed
    
    OBJ pst : "Parallax Serial Terminal"   ' included with the Propeller Tool installation
    
    PUB main
       pst.start(115_200)   ' normal Baud for Parallax Serial Terminal
    
       repeat
          if ina[buttonPin] == buttonOn   ' check for pushbutton to be pushed
             pst.str(string("Pushbutton pushed",pst#NL))   ' do something if so
          repeat while ina[buttonPin] == buttonOn   ' wait for pushbutton to be released
    
  • MagIO2MagIO2 Posts: 2,243
    edited 2012-10-29 07:13
    Did you have a look into the sticky thread "Propeller Education Kit Labs, Tools,·and Applications"?

    You'll find all the basics explained there! You'll find examples for readin input and there is an addon regarding serial communication with PC/PST.
  • TheVigTheVig Posts: 41
    edited 2012-10-29 07:41
    It outputs gobilly gook in the serial terminal. I have the baud rates the same. Hmm.
  • TheVigTheVig Posts: 41
    edited 2012-10-29 07:45
    Also looking at this, the routine transmits continuously as the button is pressed.

    I'm drawing a blank (probably because I'm not good at the spin syntax yet) on sending a single command when the button is pressed, and then another single command when the button is let off.

    Thanks,
    Jim
  • TheVigTheVig Posts: 41
    edited 2012-10-29 07:56
    OK...I Got this code working. Still looking for single command logic.
    OBJ
      pst : "Parallax Serial Terminal"   ' included with the Propeller Tool installation     
    CON
      _clkmode        = xtal1 + pll16x           ' Feedback and PLL multiplier
      _xinfreq        = 5_000_000                ' External oscillator = 5 MHz
      LEDs_START      = 16                        ' Start of I/O pin group for on/off signals
      LEDs_END        = 23                       ' End of I/O pin group for on/off signals
      PUSHBUTTON      = 0                       ' Pushbutton Input Pin
    
    PUB main                         ' Main method
      pst.start(115_200)
      dira[LEDs_START..LEDs_END]~~               ' Set entire pin group to output
    
      repeat
    
        if ina[PUSHBUTTON] == 1                  ' If pushbutton pressed
            outa[16] :=1                         ' Change the state of pin group
            pst.Str(String("Pushbutton pushed"))
        else
            outa[16] :=0
            
          
    
  • Mike GreenMike Green Posts: 23,101
    edited 2012-10-29 08:02
    If you entered the routine exactly as it's shown (indenting and all), it will not transmit continuously as the button is pressed (because the 2nd repeat prevents that).

    You really need to work through the examples in the Propeller Education Kit Labs tutorials. Start simple, get each simple example working first, before you move on.

    Sending a single command when the button is pushed, then another when it's released is a basic programming skill and has little to do with Spin syntax. It's the notion of a program having several states and the program shifting from one state to another when a particular event occurs. In this state, a loop (REPEAT) represents a state. The program moves from one loop (pushbutton down) to another (pushbutton up) when a specific event occurs (pushbutton released and pushbutton pushed respectively).

    What you displayed in post #6 will output continuously to the serial terminal when the pushbutton is pushed. When people provide you with code examples, use what they give you first, before modifying it. You'll learn more and it will probably work better.
  • TheVigTheVig Posts: 41
    edited 2012-10-29 08:14
    If you entered the routine exactly as it's shown (indenting and all), it will not transmit continuously as the button is pressed (because the 2nd repeat prevents that).[\quote]

    1. I had to change your code to this to get it to run:
    [code]
    CON
    _xinfreq = 5_000_000 ' assume you have a standard Propeller setup with a 5MHz crystal
    _clkmode = xtal1 + pll16x
    buttonPin = 0 ' change this for whatever pin you have your pushbutton hooked to
    buttonOn = 0 ' change this to 0 if your pushbutton grounds the input pin when pushed

    OBJ pst : "Parallax Serial Terminal" ' included with the Propeller Tool installation

    PUB main
    pst.start(115_200) ' normal Baud for Parallax Serial Terminal

    repeat
    if ina[buttonPin] == buttonOn ' check for pushbutton to be pushed
    pst.str(string("Pushbutton pushed",pst#NL)) ' do something if so
    repeat while ina[buttonPin] == buttonOn ' wait for pushbutton to be released
    [\code]

    2. 2nd repeat does not repeat the button from continuously firing "Pushbutton Pushed." Even though I copied and pasted.

    3. I have programming experience, but not in the syntax of spin which prevents me from knowing exactly what will do a loop, while, etc so it is difficult for me to express in spin what I want to have happen.

    4. Your example did point me in the right direction so thank you.

    Thanks,
    Jim
  • Mike GreenMike Green Posts: 23,101
    edited 2012-10-29 08:38
    Yes, I'm sorry I mistyped and left off the underlines. The code I posted will also work better if the 2nd repeat is indented to match the pst.str like this:
       repeat
          if ina[buttonPin] == buttonOn ' check for pushbutton to be pushed
             pst.str(string("Pushbutton pushed",pst#NL)) ' do something if so
             repeat while ina[buttonPin] == buttonOn ' wait for pushbutton to be released
    
    The outer repeat just makes this code repeat continuously. The assumption is that the pushbutton is initially off. The first time this code sees the pushbutton down, it displays the message, then waits for the pushbutton to be released (the 2nd repeat) before continuing so you'll get one message per push. With the indenting the way I posted it initially, the program will only catch some pushbutton presses (sorry!)
  • Mike GreenMike Green Posts: 23,101
    edited 2012-10-29 09:41
    Here's a much better example of the main loop:
       repeat
          repeat until ina[buttonPin] == buttonOn   ' wait for pushbutton to be pushed
          pst.str(string("Pushbutton pushed",pst#NL))
          repeat while ina[buttonPin] == buttonOn   ' wait for pushbutton to be released
          pst.str(string("Pushbutton released",pst#NL))
    
  • TheVigTheVig Posts: 41
    edited 2012-10-29 09:52
    Thank you so much for taking the time to help. Can't wait to try it out when I get off work tonight!

    Any chance there might be a emulator out there so I can test code without an actual board in front of me? That would be rad!

    -Jim
  • MagIO2MagIO2 Posts: 2,243
    edited 2012-10-29 10:10
    For me the best emulator is a quickstart. It fits into an Altoids tin together with a rollable USB cable. And here it is, the propeller to go!
  • TheVigTheVig Posts: 41
    edited 2012-10-29 11:37
    I don't always have a board in front of me...like either I am away from home, or I've got things packed away or tied up.

    It'd be cool to be able to design in a virtual environment (software emulator of the quickstart board) before even beginining to start prototyping a real live board.
  • MagIO2MagIO2 Posts: 2,243
    edited 2012-10-29 13:40
    In general a bare quickstart is only a little help because it only has sensor buttons and some LEDs. An emulator has even less than that. Nearly all projects make use of additional hardware. How would you emulate this?

    Oh..and by the way, here is an emulator: http://sourceforge.net/projects/gear-emu/
    But I think it's PASM only

    Just out of curiosity I wrote one myself, but discontinued that after a while because of more interesting stuff ;o)
  • TheVigTheVig Posts: 41
    edited 2012-10-29 16:10
    So I made my code with exactly what you said:
    OBJ
      pst : "Parallax Serial Terminal"   ' included with the Propeller Tool installation     
    CON
      _clkmode        = xtal1 + pll16x           ' Feedback and PLL multiplier
      _xinfreq        = 5_000_000                ' External oscillator = 5 MHz
      PUSHBUTTON      = 0                       ' Pushbutton Input Pin
    
    PUB main                         ' Main method
      pst.start(115_200)
       repeat
          repeat until ina[PUSHBUTTON] == 1   ' wait for pushbutton to be pushed
          pst.str(string("Pushbutton pushed",pst#NL))
          repeat while ina[PUSHBUTTON] == 1   ' wait for pushbutton to be released
          pst.str(string("Pushbutton released",pst#NL))
    

    When I push and hold down the button, this is what is output in the serial terminal:
    Pushbutton pushed
    Pushbutton released
    Pushbutton pushed
    Pushbutton released
    Pushbutton pushed
    Pushbutton released
    Pushbutton pushed
    Pushbutton released
    Pushbutton pushed
    Pushbutton released
    
    When I let off, it stops.

    What I need it to do is say "Pushbutton pushed" and then stop while the button is being held down.
    When I release, it needs to say "Pushbutton released".

    I don't understand why this is being so difficult.
  • kuronekokuroneko Posts: 3,623
    edited 2012-10-29 16:48
    If you change your main method to do the following, what do you get in the display while holding the button?
    PUB main                         ' Main method
      pst.start(115_200)
      repeat
        pst.char(48+ina[PUSHBUTTON])
    
  • TheVigTheVig Posts: 41
    edited 2012-10-29 18:59
    When the button is not pressed the output is all 000's

    When the button is press the output is a combination of 11110000's
    0000000000000000000000000000000000000000000000000000000000000000000000000000000000000011111111111111111111111111111111111111111111111111111111111111111111111111111111111110000000000000000000000000000000000000000000000000000000000000000000000000000000000000111111111111111111111111111111111111111111111111111111111111111111111111111111111111110000000000000000000000000000000000000000000000000000000000000000000000000000000000000111111111111111111111111111111111111111111111111111111111111111111111111111111111111100000000000000000000000000000000000000000000000000000000000000000000000000000000000000111111111111111111111111111111111111111111111111111111111111111111111111111111111111100000000000000000000000000000000000000000000000000000000000000000000000000000000000000

    Which I ran a program on to count, it is either 85 or 86 ones or zeros before transitioning.

    I've been playing around with waitpeq functions with the same results of the cloogy repeat algorithm provided by Mike Green

    Do you think I need to add timing or is my board defective?

    -Jim
  • kuronekokuroneko Posts: 3,623
    edited 2012-10-29 19:18
    That's certainly an odd button. Looks like some form of auto-repeat. FWIW, I simply generated a pulse wave from another cog (2s on, 2s off) and the program ([post=1138174]#15[/post]) follows with its output in 2s intervals, i.e. the program itself is working fine.

    Not sure what else to suggest ...

    Edit: When I modify my pulse program to flip level every 1/120th of a second (60Hz period) I get similar character counts to what you were reporting. Which suggests some form of noise. Does that make sense?
  • jmgjmg Posts: 15,173
    edited 2012-10-29 19:54
    kuroneko wrote: »
    Edit: When I modify my pulse program to flip level every 1/120th of a second (60Hz period) I get similar character counts to what you were reporting. Which suggests some form of noise. Does that make sense?

    60Hz certainly sounds like AC pickup....

    Try a Single Pole change over switch, (SPDT) between 0V , Vcc and see if the issues in #17 go away.
  • CRST1CRST1 Posts: 103
    edited 2012-10-30 05:56
    You have not said anything about your button setup. Is there a pullup or pulldown on the circuit.
  • TheVigTheVig Posts: 41
    edited 2012-10-30 10:29
    Ok so lets start with the basics so I can make sure I am on the right track.

    1. Using a P8X32A QuickStart Board
    For pinout and description:
    http://www.parallaxsemiconductor.com/products/quickstart

    2. The switches are normally open momentary buttons

    3. Using P9 (header 10) to monitor status of the pin

    4. Using P16 wired to the onboard LED give an onboard visual status of the switch.

    5. The propeller should transmit a serial signal to be read by a custom computer program (Right now the PST)


    Q1. Should the switch be connected from from Pins P9 to Vss Ground (header 39)? Or something different?
    Q2. What is the appropriate _CLKMODE for the P8x32A?
    Q3. What is the appropriate _CLKFREQ for this application
    Q4. How should the initial state of the P9 be configured. (set as input, set to low, etc...)


    Below is code that doesn't work correctly. The Led on P16 turns on as soon as the code runs while the switch is open.
    When the switch closes, the LED turns off.
    Same thing goes for the PST, while the switch is open, the output alternates between ON and OFF quickly
    When the switch is closed, transmission stops.
    OBJ
      pst : "Parallax Serial Terminal"   ' included with the Propeller Tool installation     
    CON
      _xinfreq = 5_000_000               ' assume you have a standard Propeller setup with a 5MHz crystal
      _clkmode = xtal1 + pll16x                             
      Pin = 9
      Led = 16
    PUB main                             ' Main method
      pst.start(115_200)
      DIRA[Led]~~                        ' Set Led as output
      DIRA[Pin]~                         ' Set Pin as input
      OUTA[Pin]~                         ' Set input Pin to low
      OUTA[Led]~                         ' Set output Led to low
      
      repeat
        WAITPEQ(|<Pin, |<Pin,0)          ' Wait for Pin to equal high
          pst.Str(String("ON"))
          outa[Led] := 1
           
        WAITPNE(|<Pin, |<Pin,0)          ' Wait for Pin to not equal high (equal low) 
          pst.Str(String("OFF"))
          outa[Led] := 0
    
    Note: I've played around with waiting for low vs high first since I am pulling it down with connecting to ground, but nothing seems to help...but perhaps I haven't nailed the right combination yet.


    Extra questions I will have down the road once I start using something other than the PST:
    Q5. Will the P8x32A transmit the serial information right over the USB connection where I can read the data with a program?
    Q6. Do I need to manage the Com Port connection with the propellant dll in the program?
  • TheVigTheVig Posts: 41
    edited 2012-10-30 12:17
    Should I count the zeros and wait until the number exceeds 100 before it triggers OFF?...I am trying to write out the code but still struggling with spin syntax.
  • MagIO2MagIO2 Posts: 2,243
    edited 2012-10-30 13:34
    Q1. The classical way is that one side of the switch goes to the propeller pin and this side is also connected to a pullup resistor. The other side of the switch is connected to GND. The point is, that the resistor pulls the pin to high as long as the switch is open. The switch with no resistance will draw it to low in case it's pushed.

    Q2/3
    CON
      _CLKMODE      = XTAL1 + PLL16X                        
      _XINFREQ      = 5_000_000
    
    of course you can also run the quickstart with internal propeller clock RCFAST or RCSLOW. Don't know the right settings in this case - never used it.

    Q4 using the classical method means that the pin is simply an input, so nothing to do when starting the propeller, as per default all pins are input after reset/switch on.

    Q5/Q6 If I understand your questions correctly: yes and yes. You only have to make sure that your own program can free the COM port, so that it nicely works together with propeller tool or propellent. If your program does not close the port again, the propeller tool / propellent won't be able to upload new software.
  • jmgjmg Posts: 15,173
    edited 2012-10-30 13:36
    TheVig wrote: »
    Should I count the zeros and wait until the number exceeds 100 before it triggers OFF?...I am trying to write out the code but still struggling with spin syntax.

    First try a change-over toggle switch, between 3.3 and Gnd and verify those connections with a meter.
    Check nothing else is driving your pin.
    #17 and #18 sound like floating connection issues..?
  • TheVigTheVig Posts: 41
    edited 2012-10-30 14:40
    Ok, so I didn't realize I should build a circuit around for a button.

    Using the I/O and Timing Basics Lab example found in the Propeller Education Kit Labs book Version 1.2 page 46 I built this circuit:

    circuit.png


    When I click the button I get:
    ONOFFONOFFONOFFONOFFON (sometimes more than others, but it does stop instead of just flowing constantly while the button is held down.)

    When I release the button I get exactly what I want:
    OFF

    I'm so much closer! How do I get rid of all of those extra toggles when I hit the button.

    Circuit? or Code?

    -Jim
    300 x 300 - 974B
  • TheVigTheVig Posts: 41
    edited 2012-10-30 14:45
    Adding a waitcnt fixed it. It works now!!
    OBJ
      pst : "Parallax Serial Terminal"   ' included with the Propeller Tool installation     
    CON
      _xinfreq = 5_000_000               ' assume you have a standard Propeller setup with a 5MHz crystal
      _clkmode = xtal1 + pll16x                             
      Pin = 9
      Led = 16
    PUB main                             ' Main method
      pst.start(115_200)
      DIRA[Led]~~                        ' Set Led as output
      DIRA[Pin]~                         ' Set Pin as input
      OUTA[Pin]~                         ' Set input Pin to low
      OUTA[Led]~                         ' Set output Led to low
      
      repeat
        WAITPEQ(|<Pin, |<Pin,0)          ' Wait for Pin to equal high
          pst.Str(String("ON"))
          outa[Led] := 1
          waitcnt(5_000_000 + cnt)
          outa[Led] := 0
           
        WAITPNE(|<Pin, |<Pin,0)          ' Wait for Pin to not equal high (equal low) 
          pst.Str(String("OFF"))
          outa[Led] := 0
    
  • MagIO2MagIO2 Posts: 2,243
    edited 2012-10-31 06:36
    Glad to hear that it works..

    What you see is the button bouncing back and forth for a small amount of time when you push it. And your solution is fine even if I'd expect the bouncing to be more in the area of 100ms or even less. With one second wait-time you might not detect "double clicks". So, it very much depends on what you use the button for whether a more sophisticated debounce-code is needed.
  • TheVigTheVig Posts: 41
    edited 2012-10-31 07:15
    It's a pretty good switch, one of those arcade buttons, which are usually pretty accurate and quick. Do you think I could modify the circuit at all to smooth out what is happening when the switch is on?

    I would like to have double taps, triple taps, so any suggestions on that "sophisticated debounce-code" (Perhaps an example of handling double taps with spin...which I was actually going to handle with the computer, but it might be better to just build them right in ;-)

    Do I need a debounce-code or adjust the wait time? I'm wide open to suggestions here!


    -Jim



    P.S.
    I'd like to thank everyone for jumping in and helping me out. I am so glad to finally get my project up and running. I've fiddled around with the QuickStart for the last year make lights blink and Smile...Did build a circuit and compiled code for measuring the resistance of a pot but bailed when I had troubles with Midi transmitting as garbage. My button now sends NoteOn and then NoteOff data. I am so HAPPY!
  • cavelambcavelamb Posts: 720
    edited 2012-10-31 08:18
    TheVig wrote: »
    It's a pretty good switch, one of those arcade buttons, which are usually pretty accurate and quick. Do you think I could modify the circuit at all to smooth out what is happening when the switch is on?

    I would like to have double taps, triple taps, so any suggestions on that "sophisticated debounce-code" (Perhaps an example of handling double taps with spin...which I was actually going to handle with the computer, but it might be better to just build them right in ;-)

    Do I need a debounce-code or adjust the wait time? I'm wide open to suggestions here!


    -Jim



    P.S.
    I'd like to thank everyone for jumping in and helping me out. I am so glad to finally get my project up and running. I've fiddled around with the QuickStart for the last year make lights blink and Smile...Did build a circuit and compiled code for measuring the resistance of a pot but bailed when I had troubles with Midi transmitting as garbage. My button now sends NoteOn and then NoteOff data. I am so HAPPY!


    In human terms when you press the button the switch closes (once) and all works as expected.
    In electronic terms that switch bounces several times (as you noticed)
    So, when you detect the first closure, do a short waitcnt to let it stop bouncing.

    How long? Dunno. Depends on the switch and how fast the processor is running.
    Start with a few microseconds and see how that works?

    Sommething like?
    if ina[button] == 1 (with a pull DOWN, or 0 if using a pull UP)
    waitcnt(someUS+cnt)
  • TheVigTheVig Posts: 41
    edited 2012-10-31 09:06
    That makes sense. I never really thought about the fact that mechanically the switch was bouncing like that.

    For the double click, is there a wait max for switch to toggle?
  • TheVigTheVig Posts: 41
    edited 2012-10-31 13:06
    I think I just wrapped my head around this...

    Tracking time between the ON and OFF, then another ON and OFF, the program should be able to tell if a double tap occured.

    Does anyone have experience with a program like this, any catches I should be worried about? Especially if I try to ad a triple tap :cool:
Sign In or Register to comment.