Shop OBEX P1 Docs P2 Docs Learn Events
Need assistance w/ code to allow pushbuttons that send text to TV screen — Parallax Forums

Need assistance w/ code to allow pushbuttons that send text to TV screen

Tim UTim U Posts: 9
edited 2009-11-08 16:56 in Propeller 1
Hey Folks,
··············· I have been playing with this for days now and I know there must be some solution that can help fix my delima.
If your good with buttons to send/ display text to a small TV screen, please read below.· I have included the Spin code I have written so far.
I am fairly new to this Propeller Kit so please if you have an idea that can help or solve my problem, please include details.

Thanks
Tim U


Equipment Being Used:
-········ Propeller Started Kit
-········ Small 5 x 4 inch TV screen
-········ 4 ea. pushbutton switches connected to Pins 0,1,6,& 7
-········ 4 ea. 1k Ohm Resistors
-········ the demo program called “tv_terminal.spin”
·
What I am Trying to Achieve:
···········
··········· I am trying to write a program that will display some text to the TV screen upon startup / power-up of the system (let's call it an "Introduction Message").· This text will guide the user to press buttons 1 through 4 for the various information, and hold that information on the screen till either, it times out, or another button is pressed by the user, (perhaps directing back to the introduction text message).
·
The Problem I am Having:

··········· I can get the text to display on the TV screen, but I have to hold the button down in order for it to stay on the screen (I assume to keep the pin in the "high condition").· Also in order to be able to give the user adequate time to read the displayed text I am using the waitcnt command and when the program is waiting it will not recognize any other button presses. If I decrease the wait-time then the text just scrolls too fast and is unreadable.
·
Questions:
  1. How can I make this work to my specification?
  2. Do I need to employ a second COG (or more) to run in parallel?
  3. Do I need more PUBS and if so do I employ them to print the text or to monitor the button presses?
  4. Is there anyway I can us a combination of the 4 buttons to expand the function of the program?· ··(IE: ·“press button 1 and button 2 at the same time to display more text or perform a separate function&#8221[noparse];)[/noparse]
·
Here is the Code I have written so far:
·
CON
·
······· _clkmode······· = xtal1 + pll16x·· '' This sets the clock and also the Phase Lock Loop to 6x
······· _xinfreq······· = 5_000_000······· '' This sets the clock Freq to 5 MHz
······· OutputPin = 16
······· InputPin0 = 0
······· InputPin1 = 1
· ······InputPin6 = 6
······· InputPin7 = 7
·······
VAR
···· '' ******* Variable Declaration is accomplished here **********
······· long··· testerror
······· long··· vlong
······· word··· vword
······· byte··· vbyte·······
·
OBJ····
······· term··· : "tv_terminal"······· ' This is where you call the external object "tv_terminal" to be used in this program
······· delays· : "givemeadelay.spin"· ' A short program that will do the waitcnt commands. Just pass one number to it.· S = second· M S= millisecond .
······································
·
·
PUB start
·
·
·· term.start(12)··············· 'start the TV terminal which is located on Pin #12·
··
· dira[noparse][[/noparse]OutputPin] := 1
· dira[noparse][[/noparse]InputPin0] := 0··········· 'designation· direction input pin of switch #1
· dira[noparse][[/noparse]InputPin1] := 0··········· 'designation· direction input pin of switch #2·
· dira[noparse][[/noparse]InputPin6] := 0··········· 'designation· direction input pin of switch #3·
· dira[noparse][[/noparse]InputPin7] := 0··········· 'designation· direction input pin of switch #4·
·
··· ··
·repeat
·
··· if ina[noparse][[/noparse]InputPin0] ==0
······························· term.str (string("Button #1 was pressed")) 'short text message to indicate button was pressed
······························· term.out ($0D)
······························· delays.givemeadelayS(5) ' gives a delay for 5 seconds
·······························
··· elseif ina[noparse][[/noparse]InputPin1] ==0
······························· term.str (string("Button #2 was pressed"))
······························· term.out ($0D)
···························· ···delays.givemeadelayS(5)
·······························
··· elseif ina[noparse][[/noparse]InputPin6] ==0
······························· term.str (string("Button #3 was pressed"))
······························· term.out ($0D)
······························· delays.givemeadelayS(5)
·
··· elseif ina[noparse][[/noparse]InputPin7] ==0
······························· term.str (string("Button #4 was pressed"))
······························· term.out ($0D)
······························· delays.givemeadelayS(5)··································· ·····················
··· else
······························· term.str (string(" No Button was pressed"))
······························· term.out ($0D)
······························· delays.givemeadelayS(5)

Comments

  • MagIO2MagIO2 Posts: 2,243
    edited 2009-11-06 13:33
    You need to give the schematics or describe a bit more. One side of the pushbutton goes to GND, the other goes to the propeller pin? Additionally a resistor goes from the pin to supply voltage? That's at least what the code expects.
    In your description you write 'I assume to keep the pin in the "high condition"', which makes me believe that this might be wrong.

      dira[noparse][[/noparse]InputPin0] := 0            'designation  direction input pin of switch #1
      dira[noparse][[/noparse]InputPin1] := 0            'designation  direction input pin of switch #2  
      dira[noparse][[/noparse]InputPin6] := 0            'designation  direction input pin of switch #3 
      dira[noparse][[/noparse]InputPin7] := 0            'designation  direction input pin of switch #4 
    
    

    · Not a bug, but the lines above are not needed. Per default all pins are input.
                                term.str (string("Button #2 was pressed")) 
                                term.out ($0D) 
    can be replaced by
    
                                term.str (string("Button #2 was pressed", $0D ) )
    


    Problem in your code is that you have to press the button at exactly that time, when the if statement is executed. But the if-statement always ends in a branch of code where you wait for 5 seconds - even if you did not push any button.

    Make yourself familiar with the waitpne and waitpeq instructions and use one of those in front of the if-statement to wait until a button is pushed.

    To react on combination of buttons is a bit more tricky, as the propeller is much faster than you and you will hardly be able to push two or more buttons at exactly the same time! So, when the propeller detects a pushed button it should wait for .. say a few hundred milliseconds and read the input again.

    The if statement has to be replaced by a case statement and reading the input has to be done differently:
    var
      long buttons
     
    ...
     
      ' wait for at least one button to be pushed
     
      buttons := %0000              ' initialize the variable which detects the pushed buttons
     
      repeat 10                     ' this checks the pins 10 times and the runtime makes sure that we waited for some time ... maybe needs to be increased?
        buttons := buttons | !ina[noparse][[/noparse] InputPin0 ]
        buttons := buttons | !(ina[noparse][[/noparse] InputPin1 ]<<1)
        buttons := buttons | !(ina[noparse][[/noparse] InputPin6 ]<<2)
        buttons := buttons | !(ina[noparse][[/noparse] InputPin7 ]<<3)
      
      ' here the result is checked
      case buttons
        %0001:  ' button 0
           ' do something
     
        %0010:  ' button 1
           ' do something
    
     
    
        %0100:  ' button 6
           ' do something
     
        %1000:  ' button 7
           ' do something
     
        %1001:  ' button 0 AND button 7
           ' do something
     
        .... ' whatever combinations you want
      
    

    ·Hope that helped and works ... can't test it currently.




    ·PS: At least it should keep you busy for the next few days [noparse]:o[/noparse])



    Post Edited (MagIO2) : 11/6/2009 1:44:29 PM GMT
  • kwinnkwinn Posts: 8,697
    edited 2009-11-06 15:13
    A simpler method of doing what you want would be to read all the buttons at once (0-7 and mask off 0,1,6,7), debounce them as a group, and then select an action based on the state of all four buttons.
  • Tim UTim U Posts: 9
    edited 2009-11-07 15:35
    Dear MagIO2 and kwinn,

    Thanks for your ideas, I will try these out and see if I can get some better control over my system.

    MagIO2,
    The way my switch/s is/are set up is as follows. One side of the switch is connected to VDD through the 1kOhm resistor and also pin #0. The other side of the switch is connected to VSS. I may have miss spoke when I stated....."'I assume to keep the pin in the "high condition"'.

    I will read up on WAITPEQ & WAITPNE and employ them in my program. Will post an updated code on this thread for you to see.

    Thanks again, you have given me some good ideas here.

    Tim U
  • T ChapT Chap Posts: 4,249
    edited 2009-11-07 16:35
    Post what you wrote for the wait PUB. OR try to use waitcnt instead and see what happens.

    In a case where you press a set of buttons like that it can be a good practice to 'trap' the button state if on to not allow anything else to happen until the user releases the button, this will prevent a false trigger if they hold it too long.

    I don't use TV objects ever but see if this helps out any.

    1k is a little stiff for a pull up, not that it is causing your problem. 10k is better for a pushbutton.


      if ina[noparse][[/noparse]InputPin0] ==0
    
                                    term.str (string("Button #1 was pressed")) 'short text message to indicate button was pressed
    
                                    term.out ($0D)
    
                                    delays.givemeadelayS(5) ' gives a delay for 5 seconds
    
                                    repeat while ina[noparse][[/noparse]InputPin0] ==  0      'traps the loop here until button released
    
    
    




    To build in some debounce, simply read the pin state a few times in a row to make sure it is settled:


      if ina[noparse][[/noparse]InputPin0] ==0
        waitcnt(100_000)
          if ina[noparse][[/noparse]InputPin0] ==0
           waitcnt(100_000)
             if ina[noparse][[/noparse]InputPin0] ==0
    
    
                                    term.str (string("Button #1 was pressed")) 'short text message to indicate button was pressed
    
                                    term.out ($0D)    
    
                                    delays.givemeadelayS(5) ' gives a delay for 5 seconds
    
                                    repeat while ina[noparse][[/noparse]InputPin0] ==  0      'traps the loop here until button released
    
    
    

    Post Edited (Todd Chapman) : 11/7/2009 5:00:20 PM GMT
  • Tim UTim U Posts: 9
    edited 2009-11-08 14:30
    Thanks Todd, Ill try it, also will try using the 10K resistors insted of the 1K.

    Tim U
  • Tim UTim U Posts: 9
    edited 2009-11-08 14:31
    Oh I almost forgot. Here is the code for my wait PUB


    PUB givemeadelayMS(d)
    waitcnt(clkfreq/1000*d+cnt)
    return


    PUB givemeadelayUS(d)
    waitcnt(clkfreq/1_000_000*d+cnt)
    return


    PUB givemeadelayS(d)
    waitcnt(clkfreq/1*d+cnt)
    return
  • Tim UTim U Posts: 9
    edited 2009-11-08 15:52
    Guys,
    I am having a hard time to understand how this WAITPEQ command sintax works.... Can someone explain this in a simple terms? Like I understand % means binary, but where do they come up with the number strings 0100 and 1100?????


    Using WAITPEQ
    WAITPEQ is a great way to synchronize code to external events. For example:
    waitpeq(%0100, %1100, 0) 'Wait for P3 & P2 to be low & high
    outa[noparse][[/noparse]0] := 1 'Set P0 high
    The above code pauses the cog until I/O pin 3 is low and I/O pin 2 is high, then sets I/O pin 0 high.
  • T ChapT Chap Posts: 4,249
    edited 2009-11-08 16:05
    For example, using binary the first pin (P0) would use syntax %0 (physical output pin 1 = software pin = P0)

    waitpeq is wait for the pin to equal... So you must first define WHICH pin are we talking about, then define what the pin is to equal for the code to consider it changed and we move to the next line.


    %1100 means, from left to right, pin 4 pin 3 pin 2 pin 1 (P3, P2, P1, P0), and we are watching for pins 4 and 3 in this code.

    waitpeq(%0100, %1100, 0) the first number %0100 sets the desired STATE of the pins to EQUAL, and we want pin 4 to equal 0 and pin 3 to equal 1, when this condition is met the code can proceed to the next line.


    The second number %1100 defines the pins to watch : 4 and 3

    There is a maximum 32 total pins, with the highest pin number being P31, the lowest is 0, 32 bits can represent 32 pins as 'bit field'

    %1 means to watch pin 1 (P0)
    %11 watch pins 1 and 2 (P0, P1)
    %10000000_00000000_00000000_00000000 is to watch pin 32 (P31)


    If you are only interested in lower number pins like 3 and 4, it is not required to type out all 32 bits, the values above the % symbol are just considered 0's when the code sees it. If you need to represent a 1 somewhere you have to type out the entire string to put the 1 where you need it. In some cases where there is just a single 1 on high pin number, you can bitshift over the 1, like pin 31 could be represented as %1 << 31 so you don't type out the entire 32 bits.

    Post Edited (Todd Chapman) : 11/8/2009 4:15:35 PM GMT
  • Tim UTim U Posts: 9
    edited 2009-11-08 16:56
    Todd,
    EXCELLENT explaination!!!! I followed you very easy and now the manual makes sense. Thanks for responding so quickly.

    Tim U
Sign In or Register to comment.