Single button function


+ Reply to Thread
Page 1 of 2 12 LastLast
Results 1 to 40 of 41
  1. #1
    Join Date
    Jun 2005
    Location
    Wisconsin
    Posts
    382

    Default Single button function

    I have a single button that needs to allow users to navigate menus and increment selections.

    I have tried a few things, but wanted to ask the group for ideas. As usual I'm short on space.

    Function 1: Press and Release = Increment
    Function 2: Press and Hold = Enter

    What I have now works ok until you move onto the next submenu and the value increments right away. (BTW ButtonCnt is tied to TMR1 to count how long the button has been held)

    While Switch=0
    IF ButtonCnt>30 Then SubMenu=SubMenu+1
    Wend

    value=value+1

    Thoughts on this one?

  2. #2
    Join Date
    Feb 2005
    Location
    Kolkata-India
    Posts
    562

    Lightbulb Do your user know Morse

    Hey,

    Just kidding. For user friendliness ,I beleive follow the mouse. Click, Double Click, Hold and any combination of the three.

    1. Hold to enter menu.

    2. Click to cycle between items

    3. Double Click to enter submenu incr/decr

    4. click + Click hold increase / decrease alternate

    5. Double click back to main menu

    6. Double click quit menu

    Please post the code if it works.

    Regards

    Sougata

  3. #3
    Join Date
    Jun 2005
    Location
    Wisconsin
    Posts
    382

    Default

    I found a similar device and will be using the method I described above.

    My conditional statements needed some alteration to function properly.

    Problem solved.

  4. #4
    Join Date
    Apr 2004
    Location
    Ladysmith on Vancouver Island in BC Canada
    Posts
    173

    Default Will this work?

    Hi DynamoBen,

    I wrote a short bit of code here that compiles to 74 words. I'm not sure if it's what you were looking for but I thought I'd post it anyway.

    The first press and release of the button after a hearing a single beep of the buzzer will INCREMENT your variable. Any further (single quick press's) that sounds a single beep will continue to increment the variable and when your finished incrementing then holding the button down for 4.5 seconds will ENTER the variable and exit the loop.

    If you wanted to increment and enter another variable using the same push button then you could place another IF-THEN in the loop and when it beeps a set number of times then the code could jump out of that loop into another loop and the same basic code could be repeated for a different variable (with a little modification to the original code below).

    Also an Led could be used instead of the buzzer. I'm not sure but I think this is what you wanted?

    IF Settings_Push_Button = Is_Pressed THEN
    For i = 0 to 100'this ensures that we return to mainloop
    WHILE Settings_Push_Button = Is_Pressed
    PWM Buzzer,250,1 : PAUSE 1500 : Y = Y + 1
    IF Y = 3 THEN
    'Do the ENTER
    Y = 0
    IF Y = 0 THEN EXIT
    ENDIF
    WEND

    IF Y = 2 THEN
    Y = 0
    'Do the Increment
    ENDIF

    PAUSE 100
    NEXT i
    ENDIF

    EXIT:

    jessey

  5. #5
    Join Date
    Jun 2005
    Location
    Wisconsin
    Posts
    382

    Default

    Alright I'm back at this again. I can’t figure out an efficient way to do this. My original solution was:

    ButtonHeld con 30

    Switch_Routine:
    ButtonCnt=0
    While Switch=0:Wend
    Pause 250
    Return

    Main:
    ' display lcd info here

    IF Switch=0 Then
    GoSub Switch_Routine

    IF ButtonCnt>ButtonHeld Then
    ' change menu option
    Else
    ' increment value
    EndIF
    EndIF

    Goto Main


    Timer1 counts how long (100 ms interval) the switch is held. Once the user releases the switch then it would reenter the Main to execute the code. The problem is there is no feedback to the user if the button has been held long enough. The program stays at the While:Wend until the user releases the button. If I jump out of the switch prior to the release of the switch the loop keeps executing the same switch command until the user releases the switch. Remember: the switch is still being held down.

    I’m looking for ideas. If the user presses and releases the switch the program would increment value. If the user presses and holds the switch for 3 seconds or more it would change menu options.

    Basically I want two buttons in one.

  6. #6
    Join Date
    Jul 2003
    Posts
    2,358

    Default

    Code:
    	MyButton var PortB.0		' Your Button can be anywhere
    					' Connect between PIC pin and Vss
    					' Use Weak Pull-Up or Resistor to Vdd
    
    	ButtonPress var BYTE		' Button Counter Variable
    
    	LongPress con 20		' Change this value for desired SET 
    					' function trip-point in 50mS steps
    					' Currently set for 1 Second
    
    	
    MainLoop:
    	LCDOut $FE,1,"Go Press..."
    ButtonLoop:
    	Gosub GetButton
    	If ButtonPress>0 then
    		If ButtonPress=1
    			LCDOut $FE,1,"Short Press"
    			else	
    			LCDOut $FE,1,"Long Press"
    			endif
    		Pause 1000
    		Goto MainLoop
    		endif
    	Goto ButtonLoop
    
    	'
    	'	Subroutine weighs-up users finger
    	'	in multiples of 50mS
    	'	Constant LONGPRESS determines boredom level
    	'	-------------------------------------------
    	'	on Exit...
    	'	ButtonPress=0 - No Press
    	'	ButtonPress=1 - Short Press
    	'	ButtonPress=2 - Long Press
    GetButton:
    	ButtonPress=0
    	While MyButton=0
    		If ButtonPress<255 then ButtonPress=ButtonPress+1
    		Pause 50 ' This is also our Debounce value
    		Wend
    	If ButtonPress>0 then
    		If ButtonPress=>LongPress then 
    			ButtonPress=2
    			else
    			ButtonPress=1
    			endif
    		endif
    	Return
    If you have an LCD for example, you can always clear the display (or light a LED if you have one) to indicate that a SET has been performed. Here's a variation..
    Code:
    	MyButton var PortB.0		' Your Button can be anywhere
    					' Connect between PIC pin and Vss
    					' Use Weak Pull-Up or Resistor to Vdd
    
    	ButtonPress var BYTE		' Button Counter Variable
    
    	LongPress con 20		' Change this value for desired SET 
    					' function trip-point in 50mS steps
    					' Currently set for 1 Second
    
    	
    MainLoop:
    	LCDOut $FE,1,"Go Press..."
    ButtonLoop:
    	Gosub GetButton
    	If ButtonPress>0 then
    		If ButtonPress=1
    			LCDOut $FE,1,"Short Press"
    			else	
    			LCDOut $FE,1,"Long Press"
    			endif
    		Pause 1000
    		Goto MainLoop
    		endif
    	Goto ButtonLoop
    
    	'
    	'	Subroutine weighs-up users finger
    	'	in multiples of 50mS
    	'	Constant LONGPRESS determines boredom level
    	'	-------------------------------------------
    	'	on Exit...
    	'	ButtonPress=0 - No Press
    	'	ButtonPress=1 - Short Press
    	'	ButtonPress=2 - Long Press
    GetButton:
    	ButtonPress=0
    	While MyButton=0
    		If ButtonPress<255 then ButtonPress=ButtonPress+1
    		Pause 50 ' This is also our Debounce value
    		If ButtonPress=LongPress then LCDOut $FE,1
    		Wend
    	If ButtonPress>0 then
    		If ButtonPress=>LongPress then 
    			ButtonPress=2
    			else
    			ButtonPress=1
    			endif
    		endif
    	Return
    Another variation which I tend to use, is if you have a Piezo, beep it at every Button Press start (ie ButtonCount=1) as a confidence indicator for the user (they like things like that), and then Beep Constantly once the LONGPRESS value has been reached. example...

    Code:
    	'
    	'	Subroutine weighs-up users finger
    	'	in multiples of 50mS
    	'	Constant LONGPRESS determines boredom level
    	'	-------------------------------------------
    	'	on Exit...
    	'	ButtonPress=0 - No Press
    	'	ButtonPress=1 - Short Press
    	'	ButtonPress=2 - Long Press
    GetButton:
    	ButtonPress=0
    	While MyButton=0
    		If ButtonPress<255 then ButtonPress=ButtonPress+1
    		Pause 50 ' This is also our Debounce value
    		If ButtonPress=1 then Gosub Beep
    		If ButtonPress=>LongPress then Gosub Beep
    		Wend
    	If ButtonPress>0 then
    		If ButtonPress=>LongPress then 
    			ButtonPress=2
    			else
    			ButtonPress=1
    			endif
    		endif
    	Return
    You can go on with variations for ever....

    Code:
    	'
    	'	Subroutine weighs-up users finger
    	'	in multiples of 50mS
    	'	Constant LONGPRESS determines boredom level
    	'	-------------------------------------------
    	'	on Exit...
    	'	ButtonPress=0 - No Press
    	'	ButtonPress=1 - Short Press
    	'	ButtonPress=2 - Long Press
    GetButton:
    	ButtonPress=0
    	While MyButton=0
    		If ButtonPress<255 then ButtonPress=ButtonPress+1
    		Pause 50 ' This is also our Debounce value
    		If ButtonPress=1 then Gosub Beep
    		If ButtonPress=>LongPress then Gosub Beep
    		If ButtonPress=255 then Gosub Klaxon ' Users fallen asleep
    		Wend
    	If ButtonPress>0 then
    		If ButtonPress=>LongPress then 
    			ButtonPress=2
    			else
    			ButtonPress=1
    			endif
    		endif
    	Return
    I use a WORD as the Counter in many cases, and if the Button is held for a really long time (eg 30 Seconds or even a Minute), it lets me jump into a Secret Set-Up Menu or just display an unexpected message for the User if I'm feeling devilish... or just as a 'Granny Button' to erase Passwords, Contrast and LCD Backlight levels that have been messed up. Users are a peculiar bunch... they put a password into the Menu (which they promptly forget) or save a near Invisible LCD Contrast setting and then they call Tech-Support to pull them out of the sh*t. It's nice to tell them to Press and Hold the Button for 30 minutes (or until their finger goes numb - whichever comes first) and everything will reset back to the factory default settings... (it'll reset after a minute, but if you tell them 30 they'll not do it a second time).

  7. #7
    Join Date
    Jun 2005
    Location
    Wisconsin
    Posts
    382

    Default

    Melanie as always thank you for your examples and advice.

    What I'm seeing in your examples is what I'm already doing. A single short press functions normally and the user sees a value increment when they release the switch. However in the case of a long press (ENTER) they have no idea, short of adding an led/buzzer/clear screen, that they have held the switch long enough to change menus. Basically they have to count in their head.

    Is this just something I need to live with? Do you run into any problems with this type of interface?

  8. #8
    Join Date
    Jul 2003
    Posts
    2,358

    Default

    Wherever possible I use a 3-button interface (Up/Down/Set), but if I'm stuck with one button, I try to provide some kind of user feedback so they know where they stand...

    Example 1... www.k3planet.com/Datasheet-9910-1.pdf

    ...and people thought I was kidding when I said I put "Yankee Doodle" into a commercial product!

  9. #9
    Join Date
    Jun 2005
    Location
    Wisconsin
    Posts
    382

    Default

    Nice!

    Alright I give; I either need to use another pin for feedback or add another switch. I guess I need to move from a minimalist single switch project to a two switch project.

    Thanks for the assistance.

  10. #10
    Join Date
    May 2004
    Location
    New England
    Posts
    164

    Default

    Quote Originally Posted by DynamoBen
    However in the case of a long press (ENTER) they have no idea, short of adding an led/buzzer/clear screen, that they have held the switch long enough to change menus. Basically they have to count in their head.
    Is this just something I need to live with? Do you run into any problems with this type of interface?
    What about having the menu change happen automatically after a button HOLD of say 1.5 seconds.
    The user sees the menu change, so they know they've held the button long enough.
    After the menu changes, your code then waits for the button to be released before continuing - avoiding spurious inputs at the new menu.
    If the user is goofy enough to continue holding the button, the program just sits waiting until they release it (or rig up a shocker on the button so they get zapped after 20 seconds :-)

    Only quicly looked over Melanies samples - maybe she already suggested something like that?

    Arch
    "Data sheets? I ain't got no data sheets. I don't need no data sheets. I don't have to read any stinking data sheets!"

  11. #11
    Join Date
    Jun 2005
    Location
    Wisconsin
    Posts
    382

    Default

    Quote Originally Posted by Archilochus
    What about having the menu change happen automatically after a button HOLD of say 1.5 seconds.
    The user sees the menu change, so they know they've held the button long enough.
    After the menu changes, your code then waits for the button to be released before continuing - avoiding spurious inputs at the new menu.
    If the user is goofy enough to continue holding the button, the program just sits waiting until they release it (or rig up a shocker on the button so they get zapped after 20 seconds :-)

    Only quicly looked over Melanies samples - maybe she already suggested something like that?

    Arch
    This is exactly what I wanted to do. However it’s a programming nightmare. I have been working on this for days and have come up with nothing. It is simple to describe but difficult to implement.

  12. #12
    Join Date
    Jul 2003
    Posts
    2,358

    Default

    Do you not have anything that can be used as feedback to the user? Describe your User Interface (OK, so we know it's got ONE button) - but what else has your device got in the way of LEDs LCDs or Beepers? And what do you want the Button to Do?

  13. #13
    Join Date
    Jun 2005
    Location
    Wisconsin
    Posts
    382

    Default

    The UI currently consists of one switch and an LCD. The switch is used to change time/date in normal mode. In the backdoor setup its used to set the time/date on a RTC.

    The advantage to having two switches is that the user could have autorepeat functionality when setting the clock in setup. The disadvantage is that the second switch would go unused the rest of the time, which is most of the time.
    Last edited by DynamoBen; - 7th June 2006 at 00:39.

  14. #14
    Join Date
    May 2004
    Location
    New England
    Posts
    164

    Default

    This is cut & adapted from an old piece of graphical LCD menu / sub-menu code that I had laying about. There was more to it, but I removed some stuff that didn't apply. I *think* this code worked OK, but it's been a long time since I played with it. I added some comments to it...

    Code:
    ; Button press pulls input pin LOW
    
    ; This next is placed with the subroutines...
    CountButn:	; Count button press duration during a ~2s loop.
    ; Loop auto-exits after either 2 seconds, or when user releases the button
    ; (if released before 2 seconds are up).
    ; "HoldFlag" used to flag if button pressed (HoldFlag=0), or held (HoldFlag=1).
    	pause 50 : HoldFlag = 0   ; Pause to ignore switch bounce, clear flag 
    	For CounterC = 0 to 49    ; 2s loop checks button input state...
    		Pause 40
    		if Butn then Exit_CountButn  ; When button released, end loop
    	Next CounterC                            ; Increment counter each loop
    Exit_CountButn:	; Test # loops button held for. If > 20 (0.8s), set 'HoldFlag'
    	if CounterC > 20 then HoldFlag = 1	
    	Return
    ;
    ; ####################################
    ;
    ; Here we're in the "main menu" section and looking for a button press OR hold.
    	if Butn = 0 then    ; On button press...
    		gosub CountButn    ; check button press duration (press / hold)
    		WHILE Butn = 0      ; On return from sub, if button still held,
    		WEND                   ; wait until user releases button.
    		if HoldFlag then      ; if HELD more than 0.8S, HoldFlag will be set
    			gosub PressPower : goto SecureChk ; Turn OFF, jump to security mode menu
    		EndIF
    ; if only pressed, NOT held, HoldFlag=0, so continue with whatever you need to do...
    ; Clear out previous arrow before drawing new...
    		CS_Left=0 : CS_Right=1 : GraphicFlag=1 : TextFlag=0
                    LoopStop=7 : StartADR=7690    ; graphic memory address
    		TempXY = PageFlag : gosub SetXY	; Set LCD X, Y locations
    		gosub Write_Data		; Write commands to LCD
    		PageFlag = PageFlag + 1	      ; Increment page counter after button press
    		if PageFlag > 3 then PageFlag=1	; Limits page counter to 1-3
    		gosub DrawArrow			; Draw new 8 byte arrow 
    		CounterA = 74			  ; After any press, loop continues 6sec looking for more presses.
    	EndIF
    "Data sheets? I ain't got no data sheets. I don't need no data sheets. I don't have to read any stinking data sheets!"

  15. #15
    Join Date
    May 2004
    Location
    New England
    Posts
    164

    Default

    Oops - when I cut and altered that example, I messed up...
    The "WHILE / WEND" test for release of the button should be placed AFTER you jump to and write the new menu.
    Otherwise, without the new menu appearing, the user will not know when to let go of the button, and would stand there forever after holding the button... waiting, and waiting...

    Arch
    "Data sheets? I ain't got no data sheets. I don't need no data sheets. I don't have to read any stinking data sheets!"

  16. #16
    Join Date
    Jun 2005
    Location
    Wisconsin
    Posts
    382

    Default

    Your example had the same issue. User sees no change in the display until the button is released.

    I will look into placing the while:wend after display update.

  17. #17
    Join Date
    Jul 2003
    Posts
    2,358

    Default A real live working example of ONE Button usage...

    This appended example is the basis for the worlds most inaccurate clock.

    It’s demonstrating ONE Button usage.

    Press the Button momentarily and it will flip the display between 12/24 Hour Mode.

    Press the Button for an extended time and it will jump into a Menu for you to set the time. Note the creative use of the CURSOR to indicate when a SET Function has been executed...

    It’s just a ditty to show how you can do things with ONE Button.

    And shows that code previously written (Olympic Timer) for a PIC16F876 can be quickly and easily ported and modified for a PIC16F628, or PIC16F628A or B or C...

    It’s also a teaser for half a dozen recent (Timer) threads (and for a gentleman searching for an elapsed timer – hint – hint – somebody nudge him to look at this thread!!!!) to show what can be done with 10 minutes worth of code, half a bucket of Cafe Nero's finest and a plastic straw...

    Code:
    	'
    	'	Buttons.bas
    	'	---------------
    	'	by Melanie 
    	'	written on a Laptop in a lunchbreak in a Cafe Nero
    	'	in Londons famous Regent Street... 7th June 2006
    	'
    	'	A simple demonstrator as to what can be done
    	'	with just ONE Button and an LCD...
    	'	Some Code stolen from OLYMPIC TIMER
    	'
    
    	'
    	'	Device Programming Options
    	'	--------------------------
    	@ DEVICE pic16F628, INTRC_OSC_NOCLKOUT
    					' System Clock Options	
    	@ DEVICE pic16F628, WDT_ON	' Watchdog Timer
    	@ DEVICE pic16F628, PWRT_ON	' Power-On Timer
    	@ DEVICE pic16F628, BOD_ON	' Brown-Out Detect
    	@ DEVICE pic16F628, MCLR_OFF	' Master Clear Options (Internal)
    	@ DEVICE pic16F628, LVP_OFF	' Low-Voltage Programming
    	@ DEVICE pic16F628, CPD_OFF	' Data Memory Code Protect
    	@ DEVICE pic16F628, PROTECT_OFF	' Program Code Protection
    
    	'
    	'	Hardware Defines
    	'	----------------
    		'
    		' 	LCD Display
    		'	-----------
    	Define LCD_DREG PORTB		' Port for LCD Data
    	Define LCD_DBIT 4		' Use upper 4 bits of Port
    	Define LCD_RSREG PORTB		' Port for RegisterSelect (RS) bit
    	Define LCD_RSBIT 3		' Port Pin for RS bit
    	Define LCD_EREG PORTB		' Port for Enable (E) bit
    	Define LCD_EBIT 2		' Port Pin for E bit
    	Define LCB_BITS 4		' Using 4-bit bus
    	Define LCD_LINES 2		' Using 2 line Display
    	Define LCD_COMMANDUS 2000	' Command Delay (uS)
    	Define LCD_DATAUS 50		' Data Delay (uS)
    		'
    		'	Buttons
    		'	-------
    	MyButton var PortB.0
    
    	'
    	'	Software Defines
    	'	----------------
    	AMPMFlag var BYTE		' Flag for 12/24 Hour Mode 0=24, 1=12
    					' - Yes I know it's a BYTE but I can't be bothered
    	ButtonPress var BYTE		' Button Counter Variable
    	DataA var BYTE
    	Hours var BYTE
    	Hundredths var BYTE
    	MenuStep var BYTE		' Status Indicator for Menu Display
    	Minutes var BYTE
    	Seconds var BYTE
    	TMR1Cal	var BYTE		' Timer Calibration Value
    	TMR1CalAR var BYTE		' Timer Advance/Retard Indicator
    	TMR1RunOn var WORD		' variable holding TMR1 Run-On value
    
    
    	'
    	'	EEPROM Settings
    	'	---------------
    	Data @0,0			' Advance/Retard Indicator
    	Data 0				' Calibration Value
    	Data 0				' 12/24 Hour Flag
    
    	'
    	'	Software Constants
    	'	------------------
    	LongPress con 20		' Change this value for desired SET 
    					' function trip-point in 50mS steps
    					' Currently set for 1 Second
    	TMR1CalMax con 100		' Maximum adjustment (+/-100uS per 10mS interrupt)
    	TMR1Preset con $D910		' 10mS Timer Reload value, offset by 20uS
    					' to allow for TMR1 Setting Calculations
    	'
    	'	Initialise PIC
    	'	--------------
    	TRISA=%00000000			' PortA I/O Configuration
    	TRISB=%00000001			' PortB I/O Configuration
    	CMCON=%00000111			' Comparators OFF
    	OPTION_REG.7=0			' Enable weak Pull-Ups (used for PressButton)
    
    	'
    	'	Initialise Main Program
    	'	-----------------------
    	Pause 2000			' Timeout for LCD Hardware to wake-up...
    	Read 0,TMR1CalAR		' Read Calibration Advance/Retard Indicator
    	Read 1,TMR1Cal			' Read Calibration Value
    	Read 2,AMPMFlag			' It's what it says...
    	Hundredths=0			' Reset Timer Counter variables
    	Seconds=0
    	Minutes=0
    	Hours=0
    		'
    		'	Initialise TMR1 Interrupts
    		'	--------------------------
    	Gosub SetTimer			' Set the Timer for next 10mS Interrupt
    	On Interrupt goto TickCount
    	PIE1.0=1			' Enable TMR1 Interrupts
    	INTCON.6=1			' Enable all unmasked Interrupts
    	INTCON.7=1			' Enable Global Interrupts
    DisplayRestart:
    	LCDOut $FE,1			' Clear Display
    	'
    	'	Main Program Loop
    	'	-----------------
    	Enable
    DisplayLoop:
    	LCDOut $FE,$0C
    	If AMPMFlag=0 then
    		'
    		'	Here we have got a 24 Hour Clock Display
    		'	----------------------------------------
    		LCDOut $FE,$84,DEC2 Hours,":",DEC2 Minutes,":",DEC2 Seconds
    		else
    		'
    		'	and here we have a 12 Hour Clock Display
    		'	----------------------------------------
    		LCDOut $FE,$82
    		DataA=Hours
    		If DataA=0 then DataA=12
    		If DataA>12 then DataA=DataA-12
    		If DataA<10 then LCDOut " "
    		LCDOut #DataA,":",DEC2 Minutes,":",DEC2 Seconds," "
    		If Hours>11 then 
    			LCDOut "PM"
    			else
    			LCDOut "AM"
    			endif
    		endif
    	'
    	'	Check For Button Press
    	'	----------------------
    	Gosub GetButton
    		'
    		'	Toggle 24 Hour Mode
    		'	-------------------
    	If ButtonPress=1 then
    		AMPMFlag=AMPMFlag^1
    		Write 2,AMPMFlag
    		Goto DisplayRestart
    		endif
    	If ButtonPress<>2 then goto DisplayLoop
    	Disable
    	'
    	'	Setup Mode
    	'	----------
    	LCDOut $FE,1,"Set Time Please:"
    	LCDOut $FE,$C4,DEC2 Hours,":",DEC2 Minutes,":",DEC2 Seconds,$FE,$C5
    	MenuStep=0
    MenuLoop:
    	Gosub GetButton
    		'
    		'	SET Mode
    		'	--------
    	If ButtonPress=2 then
    		MenuStep=MenuStep+1
    		If MenuStep=3 then
    			LCDOut $FE,1,$FE,$83,"Thank You",$FE,$C0,"Have a Nice Day"
    			Pause 2000
    			Goto DisplayRestart
    			endif
    		endif
    	If ButtonPress=1 then
    		'
    		'	Hours
    		'	-----
    		If MenuStep=0 then
    			Hours=Hours+1
    			If Hours>23 then Hours=0
    			LCDOut $FE,$C4,DEC2 Hours
    			endif
    		'
    		'	Minutes
    		'	-------
    		If MenuStep=1 then
    			Minutes=Minutes+1
    			If Minutes>59 then Minutes=0
    			LCDOut $FE,$C7,DEC2 Minutes
    			endif
    		'
    		'	Seconds
    		'	-------
    		If MenuStep=2 then
    			Seconds=Seconds+1
    			If Seconds>59 then Seconds=0
    			LCDOut $FE,$CA,DEC2 Seconds
    			endif
    		endif
    		'
    		'	Ensure Cursor is in a nice place...
    		'	--------------------------------
    	LCDOut $FE,$0E
    	If MenuStep=0 then 
    		LCDOut $FE,$C5
    		else
    		If MenuStep=1 then
    			LCDOut $FE,$C8
    			else
    			LCDOut $FE,$CB
    			endif
    		endif
    	Goto MenuLoop
    
    	'
    	'	Subroutine weighs-up users finger
    	'	in multiples of 50mS
    	'	Constant LONGPRESS determines boredom level
    	'	-------------------------------------------
    	'	on Exit...
    	'	ButtonPress=0 - No Press
    	'	ButtonPress=1 - Short Press
    	'	ButtonPress=2 - Long Press
    GetButton:
    	ButtonPress=0
    	While MyButton=0
    		If ButtonPress<255 then ButtonPress=ButtonPress+1
    		Pause 50 ' This is also our Debounce value
    		If ButtonPress=>LongPress then LCDOut $FE,$0F
    		Wend
    	If ButtonPress>0 then
    		If ButtonPress=>LongPress then 
    			ButtonPress=2
    			else
    			ButtonPress=1
    			endif
    		endif
    	Return
    
    	'
    	'	Subroutine Loads TMR1 values
    	'	============================
    SetTimer:
    	T1CON.0=0			' Stop the Clock
    	TMR1RunOn.Highbyte=TMR1H	' Load the Run-On (Over-Run) value (if any)
    	TMR1RunOn.Lowbyte=TMR1L
    	TMR1RunOn=TMR1Preset+TMR1RunOn	' Calculate the New (adjusted) value for TMR1
    	If TMR1CalAR=0 then		' Calibration ADVANCE (add) or RETARD (subtract)
    		TMR1RunOn=TMR1RunOn+TMR1Cal
    		else
    		TMR1RunOn=TMR1RunOn-TMR1Cal
    		endif
    	TMR1H=TMR1RunOn.Highbyte		' Save new values to TMR1
    	TMR1L=TMR1RunOn.Lowbyte
    	T1CON.0=1			' Restart the Clock
    	PIR1.0=0			' Reset TMR1's Interupt Flag
    	Return
    
    	'
    	'	Timer Interrupt Handler
    	'	=======================
    TickCount:
    	Gosub SetTimer			' Set the Timer for next 10mS Interrupt
    	Hundredths=Hundredths+1		' Increment 10mS Seconds Counter
    	If Hundredths>99 then
    		Hundredths=0
    		Seconds=Seconds+1
    					' Increment the Seconds
    		If Seconds>59 then
    			Seconds=0
    			Minutes=Minutes+1
    					' Increment the Minutes
    			If Minutes>59 then
    				Minutes=0
    				Hours=Hours+1
    					' Increment the Hours
    				If Hours>23 then Hours=0
    				endif
    			endif
    		endif
    	Resume
    
    	End
    Attached Images Attached Images    

  18. #18
    Join Date
    May 2004
    Location
    New England
    Posts
    164

    Default

    Quote Originally Posted by DynamoBen
    Your example had the same issue. User sees no change in the display until the button is released.

    I will look into placing the while:wend after display update.
    Other than my goof with the WHILE / WEND, the code will jump to a new menu after a HOLD of ~ 1 second. If only pressed, the button test loop ends immediately, and the code continues as needed after a press & release.

    The button test loop auto-terminates after 2 seconds, so even if the user continues holding the button, the code will jump to the new menu anyway, and only after writing the new menu, does it then wait for a button release.

    Arch
    "Data sheets? I ain't got no data sheets. I don't need no data sheets. I don't have to read any stinking data sheets!"

  19. #19
    Join Date
    Jun 2005
    Location
    Wisconsin
    Posts
    382

    Default

    Melanie I've added your code into my project. When setting the times hours, minutes, or seconds the display clears and only displays the value that is currently being altered. Are you seeing the same thing or am I missing something?

  20. #20
    Join Date
    Jul 2003
    Posts
    2,358

    Default

    You're doing something wrong...

    When setting the Time, you can see all the fields (by field, you can see Hours, Minutes and Seconds on the same line, and as you press momentarilly, only the field you are currently parked on will change. When you hold for SET, the cursor changes from an underscore to a Block and on finger release moves to the next field, leaving the previous one with the content you set.

    I refer you to the Button-02 picture... there you can see the underscore cursor parked in the Hours field... pressing momentarily will advance Hours through to 23 then cycle around starting from zero. Hold the Button for SET and the cursor changes to a BLOCK, and on finger release moves to Minutes changing back to an Underscore.

    Check your $FE,xx's are the same as mine...

    Melanie

  21. #21
    Join Date
    Jun 2005
    Location
    Wisconsin
    Posts
    382

    Default

    Duh! <smacks forehead> my switch routine had a LCD clear command in it.

  22. #22
    Join Date
    Mar 2006
    Posts
    41

    Default syntacks(",)

    Good day

    I'm a picbasic newbie i'd like to ask these syntaxes do?

    AMPMFlag=AMPMFlag^1 '>>>>>>>>>>>>>>>>>>>what does this do?

    Lc var byte [15]
    For i = 0 to 15 : read i, b0:if b0 = 0 then
    lookup i,[1,2,3,11,4,5,6,11,7,8,9,10,11,12,13,14], b0
    Lc(i)=b0 '>>>>>>>>>>>>>>>>>>>>>>>>>>>what does this do?
    goto Address

    I would gladly appreciate for any response
    thanks
    ryan

  23. #23
    Join Date
    Jul 2003
    Posts
    2,358

    Default

    AMPMFlag=AMPMFlag^1 '>>>>>>>>>>>>>>>>>>>what does this do?

    AMPMFlag is a BIT variable.
    All this does is toggle the BIT variable, if it was zero it will be set to 1, if it was 1 it will be set to 0. It is the equivallent of...

    IF AMPMFlag=0 then
    AMPMFlag=1
    else
    AMPMFlag=0
    endif



    Lc var byte [15]
    For i = 0 to 15 : read i, b0:if b0 = 0 then
    lookup i,[1,2,3,11,4,5,6,11,7,8,9,10,11,12,13,14], b0
    Lc(i)=b0 '>>>>>>>>>>>>>>>>>>>>>>>>>>>what does this do?

    Lc is a BYTE array 15 elements deep in the range Lc(0) to Lc(14)
    You are loading Lc at array location i with the contents of variable b0

  24. #24
    Join Date
    Mar 2006
    Posts
    41

    Default thanks so much

    Thank you Mel,
    I am incorporating your olympic timer in my medicine scheduler project I used some code snippets from les Johnson's book "experimenting with picbasic" I also read your thread with bits,byte, and arrray handling and found it intuitive!!!
    I am still fixing my keypad routine to scan and output to LCD like a mobile fone does(",) I am trying to find a lcd menu routine for my display I will post it later on a new thread

    thanks again
    ryan

  25. #25

    Default

    here is a chip that will give you 2 button's on one i/o
    http://www.maxim-ic.com/quick_view2.cfm/qv_pk/4588

  26. #26
    Join Date
    Jul 2003
    Posts
    2,358

    Default

    You seriously want to pay $1 for a 2 I/O expander?

    If you need two buttons on one I/O, then you can achieve that with a different value of Capacitor on each of two Buttons and measure the time period for charge. Cost about 5 cents and a bit of magic in software...

  27. #27
    Join Date
    Jun 2005
    Location
    Wisconsin
    Posts
    382

    Default

    You could also use the pot command and tie each button to a different value resistor.

    This gives you the added ability of determining when both buttons are being pressed.

  28. #28

    Default

    Well if I had been trying to solve this problem since March I think a $1 part would be cheap,sorry you didn't like my feable attempt at helping out
    I'll go to my room now and keep quiet.

  29. #29
    Join Date
    Jul 2003
    Posts
    2,358

    Default

    Don't get the hump over my comment... I'm NOT criticising your contribution which is perfectly valid, but think about a $1....

    For $1 you can get a PIC with a heap of I/O's...

    For an extra $1 added to whatever PIC you are currently using would probably give you a dozen I/O's more

    For 75 cents you can get an I2C 8 channel I/O expander...

    For 45 cents you can get a PIC10F to give you your extra I/O's...

    Adding I/O's at the rate of 50 cents per I/O is nonsensical... there's just so many options available for less money - but...

    you've brought it to everyone's attention, and that just might be exactly the product someone is looking for, so thank you for that.

  30. #30

    Default

    Melanie
    I was not in the least bit offended,you must have missed the happy face and it did spur you to give Ben another cheaper option not to mention Ben's idea so in around about way I guess I've helped.

  31. #31
    Join Date
    Jul 2003
    Posts
    2,358

    Default

    I like to think that every comment on this forum, good or bad, is a valid one and holds as much weight as every other. What's wrong for one person may be someone elses perfect "cup of tea" (beer). Even 'crazy price' Maxim must be doing something right - after all, they're still in business....

  32. #32
    Join Date
    Jun 2005
    Location
    Wisconsin
    Posts
    382

    Lightbulb Finally got it!

    After working on this for some time I have come up with a routine that does what I need it to do. I may use Timer1 to keep track of how long the button is held in place of PAUSE, but it works as is.

    There are three button states 0, 1, 2:
    0=no action
    1=short press/release
    2=Held


    Switch_Routine:
    ButtonState=0
    IF Switch=1 Then ButtonCnt=0

    IF Switch=0 Then
    While Switch=0
    Pause 250
    ButtonCnt=ButtonCnt+1

    IF ButtonCnt=ButtonHeld Then
    ButtonState=2
    Return
    EndIF
    Wend

    IF ButtonCnt<ButtonHeld Then ButtonState=1
    EndIF
    Return
    Last edited by DynamoBen; - 12th August 2006 at 18:44.

  33. #33
    Join Date
    Jun 2005
    Location
    Germany
    Posts
    6

    Question Button code doesn't work

    Say hello to everyone,

    where is the fault in this example:


    ButtonPress var BYTE ' Button Counter Variable

    LongPress con 20 ' Change this value for desired SET
    ' function trip-point in 50mS steps
    ' Currently set for 1 Second


    MainLoop:
    LCDOut $FE,1,"Go Press..."
    ButtonLoop:
    Gosub GetButton
    If ButtonPress>0 then
    If ButtonPress=1
    LCDOut $FE,1,"Short Press"
    else
    LCDOut $FE,1,"Long Press"
    endif
    Pause 1000
    Goto MainLoop
    endif
    Goto ButtonLoop

    '
    ' Subroutine weighs-up users finger
    ' in multiples of 50mS
    ' Constant LONGPRESS determines boredom level
    ' -------------------------------------------
    ' on Exit...
    ' ButtonPress=0 - No Press
    ' ButtonPress=1 - Short Press
    ' ButtonPress=2 - Long Press
    GetButton:
    ButtonPress=0
    While MyButton=0
    If ButtonPress<255 then ButtonPress=ButtonPress+1
    Pause 50 ' This is also our Debounce value
    If ButtonPress=LongPress then LCDOut $FE,1
    Wend
    If ButtonPress>0 then
    If ButtonPress=>LongPress then
    ButtonPress=2
    else
    ButtonPress=1
    endif
    endif
    Return

    I have this Sample code compiled and get this error message:

    ERROR Line 18: Bad expression or missing THEN, (Button_01.php)

    See attachment

    I am here new and am pleased about every help.

    Konrad
    Attached Images Attached Images  

  34. #34
    Join Date
    May 2004
    Location
    NW France
    Posts
    3,542

    Post

    Hi, Konrad

    I used such a "multi role" button simply by using the BUTTON Command in a loop...

    the example is here,

    Code:
    '*****************************************************************************
    'Servotest 84 D'après Elektor
    '*****************************************************************************
    '
    '16F84A à 20 Mhz
    
    ' Barregraph 7 leds sur PortB
    ' résolution variable 2-6-20 µS
    ' Mémorisation réglage " moyen"
    
    @  __config _HS_OSC & _WDT_ON & _CP_ON
    
    DEFINE OSC 20 ' 
    DEFINE BUTTON_PAUSE 18
    
    Signal	var PortA.0
    Writeok	var PortA.1 ' Indicateur mode : 0 = manuel 1 = Cycle
    Up 		var PortA.2	' Rotation à Droite
    Down 	var PortA.3 ' Rotation à gauche
    Prog 	var PortA.4 ' Bouton mémorisation
    
    pos 	var Word
    posn 	var Word
    
    compte	var Byte
    dir 	var Byte
    delay	var Byte
    N		var Byte
    
    PORTA 	= 0
    PORTB 	= %00001000 'PortB.7 libre, Led centrale allumée.
    
    TRISA 	= %00011100
    TRISB 	= %00000000
    
    
    READ 1, Posn.HighByte
    READ 2, Posn.LowByte
    
    IF posn = $FFFF OR posn < 750 OR posn > 2250 THEN posn = 1500
    pos = posn
    
    '*****************************************************************************
    mainloop:
    
    Writeok = 0
    
    delay = 0
    
    button Up, 		0, 255, 0, delay, 1, upbutton
    button Down, 	0, 255, 0, delay, 1, dwnbutton
    button Prog, 	0, 255, 0, delay, 1, Program
    
    Gosub Outsig
    PAUSE 18
    compte = 0
    
    Goto Mainloop
    
    
    '*****************************************************************************
    upbutton:
    
    IF Down = 0 THEN 
    
    	Pos = posn
    	Goto Jump1
    	
    Endif
    
    	Compte = compte + 1
    	
    	Select Case Compte
    	
    		Case 255
    			Compte = Compte-1
    			N = 10
    			
    		Case is > 50
    			N = 10
    				
    		Case is > 15 
    		 	N = 3
    		 	
    		Case else
    			N = 1
    			
    	End Select
    	
       	pos = pos + 2*N
       
       	if pos > 2250 then  pos = 2250
      
    Jump1:
    
    For delay = 1 to 9	
    
    	Gosub Outsig
    	Pause 18
    
    Next delay
    
    	Gosub Outsig
    
    Goto mainloop
    
    
    '*****************************************************************************
    dwnbutton:
    
    IF Up = 0 THEN 
    
    	Pos = posn
    	Goto Jump2
    	
    Endif
    
    	Compte = compte + 1
    	
    	Select Case Compte
    	
    		Case 255
    			Compte = Compte - 1
    			N = 10
    			
    		Case is > 50
    			N = 10
    			
    		Case is > 10 
    		 	N = 3
    		 			
    		Case else
    			N = 1
    			
    	End Select
    	
       	pos = pos - 2*N
       
       	if pos < 750 then pos = 750
       	 
    Jump2:
    	
    For delay = 1 to 9	
    
    	Gosub Outsig
    	Pause 18
    
    Next delay
    
    	Gosub Outsig
    
     Goto mainloop
     
    
    '*****************************************************************************
    Program:
    
    Compte = 0
    
    Test: 
    
    IF Prog = 0 Then 
    	
    	compte = compte + 1
    	Gosub Outsig
    	Pause 18
    	
    	IF Compte > 250 THEN Compte = 250: Goto Test
    	IF Compte >= 80 THEN WriteoK = Compte .4 : Goto Test
    	IF Compte >= 20 THEN WriteoK = Compte .2
    	
    	Goto Test		'Attendre relâchement bouton ...
    	
    Endif	
    	
    	IF Compte > 250 OR Compte < 20 Then mainloop
    	
    	IF Compte >= 80 Then
    	 
    		pos = 1500 
    		Goto Save	'remise au Neutre
    
    	Endif	
    
    					'Position "moyenne"
    
    
    Save:
    
    WRITE 1, Pos.HighByte			' 10ms
    WRITE 2, Pos.LowByte			' 10ms
    
    	Posn = pos
    	Gosub Outsig
    
    For delay = 1 to 25
    	
    	WriteoK = 1
    	Gosub Outsig
    	Pause 18
    	
    Next Delay
    	
    	Goto mainloop
    
    
    	
    '*****************************************************************************
    Outsig:
    
    Select Case pos			'Allumage Bargraph
    
    	Case 750
    	
    		PortB = %01100001
    
    	Case is <= posn - 635
    	
    		PortB = %01000000
    		
    	Case is <= posn - 519
    	
    		PortB = %01100000
    		
    	Case is <= posn - 404
    	
    		PortB = %00100000
    		
    	Case is <= posn - 288
    	
    		PortB = %00110000
    		
    	Case is <= Posn - 173	
    	
    		PortB = %00010000
    		
    	Case is <= Posn - 58
    	
    		PortB = %00011000
    		
    	Case is <= Posn
    	
    		PortB = %01001000
    		
    '*****************************************************************************		
    	Case posn					' Position centrée
    	
    		PortB = %01001001
    '*****************************************************************************
    			
    	Case is <= posn + 58
    	
    		PortB = %00001001
    		
    	Case is <= posn + 173
    	
    		PortB = %00001100
    		
    	Case is <= posn + 288
    	
    		PortB = %00000100
    	
    	Case is <= posn + 404
    	
    		PortB = %00000110
    			
    	Case is <= posn + 519
    	
    		PortB = %00000010
    		
    	Case is <= posn + 635
    	
    		PortB = %00000011
    		
    	Case is < posn + 750
    	
    		PortB = %00000001
    		
    	Case 2250
    	
    		PortB = %01000011
    		
    END Select
    		
    Low Signal
    Pulsout Signal, pos /2		'Envoi Signal servo
    
    RETURN
    
    END

    The "important" sections have been Highlighted ...

    Here, the more the pressing UP and DOWN buttons speed up the 'count speed' ... pressing "prog" permits to choose beetween options ...
    Note WriteOk is a led that shows the delay increasing value when pushing the button ...

    Alain
    Last edited by Acetronics2; - 15th January 2008 at 12:58.
    ************************************************** ***********************
    Why insist on using 32 Bits when you're not even able to deal with the first 8 ones ??? ehhhhhh ...
    ************************************************** ***********************
    IF there is the word "Problem" in your question ...
    certainly the answer is " RTFM " or " RTFDataSheet " !!!
    *****************************************

  35. #35
    Join Date
    Jun 2005
    Location
    Germany
    Posts
    6

    Post

    Hi, Alain,

    thanks for the fast reaction and the Code sample.

    I would like to build a "One Button Dimmer"

    1. Short Press Button T1: Toggle LED1 on/off or off/on.

    2. Long Press Button T1: Ramp the Light von LED1 up or Ramp the Light down depending on the one last "Long Press", Ramp direction toggle every "Long Press".

    3. Before power off store the last Ramp value

    See the schematic in the attachment

    Every help is welcome,

    Konrad
    Attached Images Attached Images  

  36. #36
    Join Date
    May 2004
    Location
    NW France
    Posts
    3,542

    Talking Slb 0587

    Hi, Vtt

    A look Here, may be ...

    http://www.electronique-diffusion.fr...lb0587&x=2&y=8

    ...

    some chips still on the market !!! ... and in my drawers ... LOL !

    Alain
    ************************************************** ***********************
    Why insist on using 32 Bits when you're not even able to deal with the first 8 ones ??? ehhhhhh ...
    ************************************************** ***********************
    IF there is the word "Problem" in your question ...
    certainly the answer is " RTFM " or " RTFDataSheet " !!!
    *****************************************

  37. #37
    Join Date
    Feb 2013
    Posts
    489

    Default Re: Slb 0587

    Due to my lack of knowledge, when facing same problem, I did the following - while user keeps button pressed, value of needed variable is being increased and value of waiting variable reset. As user releases the button, waiting variable is being increased, and after it reaches some value (say for 2 seconds), next chunk of code is required. I'd like to do the same with long press, but still can't figure how.

    Any ideas to add long press detection to this code?

    Code:
    setuploop:
    if but2=0 then
    dlycnt=dlycnt+1 'increase debounce variable while button is pressed
    
    pause 1
    endif
    
    if BUT2=1 and dlycnt>100 then 'if button pressed long enough
    dlycnt=0
    high buz 'enable buzzer pin
    menuitem=menuitem+1
    lcdout $fe,1, #menuitem, " pressed "
    pause 5
    low buz 'disable buzzer
    endif
    goto setuploop

  38. #38
    Join Date
    Apr 2014
    Location
    Northeast
    Posts
    313

    Default Re: Single button function

    IF Button = Pressed THEN
    WHILE Button = Pressed
    LOOP
    ENDIF

  39. #39
    Join Date
    Feb 2013
    Posts
    489

    Default Re: Single button function

    I did it in the different way:
    Code:
    setuploop:
    if but2=0 then
    dlycnt=dlycnt+1 'increase debounce variable while button is pressed
    ticker=ticker+1
    pause 1
    endif
    if ticker>1500 and  BUT2=0 then gasvla 'if long pressed, then exit and (or) go to selector item
    if BUT2=1 and dlycnt>100 then  'if short pressed, then do the rap
    ticker=0
    dlycnt=0
    menuitem=menuitem+1  'this is incremental variable, substitute another next time you need it
    lcdout $fe,$c0, " selection: " #menuitem," "  'debug just for case
    pause 1
    endif
    goto setuploop

  40. #40

    Default Re: Single button function

    I did a setup to check for...... short press, then 2 second or 5 second then long press to enter program mode, for next for the timing, then go on to next check and goto's

    Code:
     FOR A1= 1 TO 5        '<.1 SECONDS FOR TIMER
     PAUSE 3 
     GOSUB RDSW
     if SWCH=0 then start
     NEXT A1
     HIGH 2
    read 1,A4 :PAUSE 10: C1=60*A4:C2=C1      
                        
     FOR A1 = 1 TO 100       '2 SECONDS FOR 8 HR
     PAUSE 8
     GOSUB RDSW
     if SWCH=0 then TIMER
     NEXT A1
     C1=28800      '8 HRS
     HIGH 5                       
     
     FOR A1 = 1 TO 100        'CHECK FOR PROGRAM 5 SEC TOTAL
     PAUSE 40
     GOSUB RDSW
     if SWCH=0 then TIMER
     NEXT A1 
     LOW 2:GOTO PROGRAM

Similar Threads

  1. Sony SIRC IR Issue
    By Ryan7777 in forum mel PIC BASIC Pro
    Replies: 10
    Last Post: - 8th August 2015, 08:10
  2. 3 HPWM channels
    By docwisdom in forum mel PIC BASIC Pro
    Replies: 9
    Last Post: - 4th April 2006, 02:43
  3. Code check -- button not working
    By docwisdom in forum mel PIC BASIC Pro
    Replies: 12
    Last Post: - 2nd March 2006, 22:43
  4. Pushbutton code routine suggestions?
    By jessey in forum mel PIC BASIC Pro
    Replies: 2
    Last Post: - 3rd September 2005, 01:02
  5. Button subfunction 16F628
    By Jųan in forum mel PIC BASIC Pro
    Replies: 5
    Last Post: - 19th August 2005, 16:44

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts