How to measure how long I pressed a button ?


+ Reply to Thread
Results 1 to 19 of 19
  1. #1
    Join Date
    Dec 2008
    Location
    Ploiesti, ROMANIA
    Posts
    579

    Default How to measure how long I pressed a button ?

    Howdy ! I'm back on the forum after some absence (I had some personal problems).
    I am trying to develop a project. I use a PIC12F675 with which I read the value of a group of 6 resistors, of different values, individually, to perform 6 specific tasks.
    I am attaching the diagram. I am also attaching the code used so far, by which I try, in the first phase, to read if a button was pressed briefly or long, in order to make two different decisions depending on the duration of the press.
    I wasted many hours with gemini/chatgpt, none of them managed to identify the problem of the code not working. I tried dozens of options, without any results.
    What proved to me, once more, that we are superior (still?) to artificial intelligence, at least in certain aspects.

    Can you help me identify and solve the problem? Thank you in advance !


    Code:
    @ __config _XT_OSC & _WDT_OFF & _PWRTE_ON & _MCLRE_ON & _BODEN_ON & _CP_ON 
    
    DEFINE OSC  4
    INCLUDE "modedefs.bas"
    CMCON    = 7
    TRISIO   = %00001001
    INTCON   = 0 
    IOC      = 0
    GPIO     = 0
    ANSEL    = %00110001
    
    
    
    ' Constante
    longpress CON 5000 ' maximum press (5 sec)
    shortpress CON 100 ' minimum press
    
    ' Variabile
    
    durata 		var word
    PressStartTime 	var word
    overflow_counter_low var word
    T1CON = %00000110 ' Prescaler  1:64, activating Timer1
    TMR1H = 0 ' Resetam Timer1
    TMR1L = 0
    
    GPIO.2 = 0
    ADCON0 = %10000001
    PAUSEUS 100 
    
    Main:
    
        durata = 0
        overflow_counter_low = 0
    
    
        ADCON0.1 = 1
        While ADCON0.1 = 1 : Wend 
    
    
        DataW.HighByte = ADRESH 
        DataW.LowByte = ADRESL
    
    
    if DataW < 805 then
            if DataW > 50  AND DataW < 160 THEN b_level = 1
            if DataW > 180 AND DataW < 270 THEN b_level = 2
            if DataW > 290 AND DataW < 380 THEN b_level = 3
            if DataW > 400 AND DataW < 500 THEN b_level = 4
            if DataW > 540 AND DataW < 650 THEN b_level = 5
            if DataW > 690 AND DataW < 800 THEN b_level = 6
    
    
            if b_level <> 0 then
                TMR1H = 0
                TMR1L = 0
                PressStartTime = TMR1L
    
    	while durata < longpress
        		if T1CON.0 == 1 then
            	overflow_counter_low = overflow_counter_low + 1
            		if overflow_counter_low == 65535 then
                		overflow_counter_low = 0
                		durata = durata + 65535
            		endif
        		endif
        
        	durata = durata + (TMR1H * 256 + TMR1L)
    	wend
    
    	durata = durata - PressStartTime
            PAUSE 100
    	SEROUT GPIO.2, 2, ["Press for : ", #durata, " ms", 13, 10]
    
            endif
    
    endif
    
    
    GOTO Main
    Name:  schematic.BMP
Views: 122
Size:  36.2 KB
    Last edited by fratello; - 27th March 2024 at 16:55.

  2. #2
    Join Date
    May 2013
    Location
    australia
    Posts
    2,389


    Did you find this post helpful? Yes | No

    Default Re: How to measure how long I pressed a button ?

    in order to measure a buttons hold time you need to either note time button was pressed then the time button was released
    the duration is release time - when pressed time, or when button is pressed start a timer and then stop it when button released
    you are not doing either of these things
    you never start timer1, you never note when the button is released
    Warning I'm not a teacher

  3. #3
    Join Date
    Dec 2008
    Location
    Ploiesti, ROMANIA
    Posts
    579


    Did you find this post helpful? Yes | No

    Default Re: How to measure how long I pressed a button ?

    Thanks for reply !
    T1CON = %00000110 ; this command does not start timer1?
    Or do I have to use the command: T1CON.0 = 1 'start Timer1 ?
    How to see if button is released ? IF DataW.... it's not enough ?
    Last edited by fratello; - 28th March 2024 at 09:19.

  4. #4
    Join Date
    May 2013
    Location
    australia
    Posts
    2,389


    Did you find this post helpful? Yes | No

    Default Re: How to measure how long I pressed a button ?

    No it just sets it to use external clock

    Name:  TIMER1.jpg
Views: 110
Size:  155.9 KB
    Warning I'm not a teacher

  5. #5
    Join Date
    May 2013
    Location
    australia
    Posts
    2,389


    Did you find this post helpful? Yes | No

    Default Re: How to measure how long I pressed a button ?

    you have set timer1 to overflow every 16.38 mS , you never count the overflows
    also adding 65535 to a word var seems very odd do you actually intend to subtract 1


    i can't see how any of this can work, i makes no sense to me

    Code:
    while durata < longpress
        	if T1CON.0 == 1 then
            	overflow_counter_low = overflow_counter_low + 1
            	if overflow_counter_low == 65535 then
                		overflow_counter_low = 0
                		durata = durata + 65535
            	endif
        	endif    
        	durata = durata + (TMR1H * 256 + TMR1L)
    wend
    Warning I'm not a teacher

  6. #6
    Join Date
    May 2013
    Location
    australia
    Posts
    2,389


    Did you find this post helpful? Yes | No

    Default Re: How to measure how long I pressed a button ?

    Quote Originally Posted by fratello View Post
    How to see if button is released ? IF DataW.... it's not enough ?
    i possibly could be enough but you never reevaluate it until the whole timing mess has long completed
    Warning I'm not a teacher

  7. #7
    Join Date
    Dec 2008
    Location
    Ploiesti, ROMANIA
    Posts
    579


    Did you find this post helpful? Yes | No

    Default Re: How to measure how long I pressed a button ?

    Quote Originally Posted by richard View Post
    you have set timer1 to overflow every 16.38 mS , you never count the overflows
    also adding 65535 to a word var seems very odd do you actually intend to subtract 1
    ....
    i can't see how any of this can work, i makes no sense to me
    Gemini code !

  8. #8
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,521


    1 out of 1 members found this post helpful. Did you find this post helpful? Yes | No

    Default Re: How to measure how long I pressed a button ?

    What happens if more than one button is pressed at the same time?

    Anyway, this might serve as starting point. It compiles but it is not tested.
    Code:
    Long_Press CON 5000
    Short_Press con 100
    
    cnt VAR WORD
    b_level VAR BYTE
    DataW VAR WORD
    
    Main:
        GOSUB ReadButton
        
        IF b_level > 0 THEN
        	cnt = 0
            WHILE b_level > 0  
        	   cnt = cnt + 10  
        	   if cnt > Long_Press THEN EXIT
        	   PAUSE 10
        	   GOSUB ReadButton
        	WEND
        	
        	SEROUT GPIO.2, 2, ["You pressed button ", #b_level, " for ", #cnt, "ms", 13, 10]
        endif
    Goto Main	
    
    
    ReadButton:
        ADCON0.1 = 1
    	While ADCON0.1 = 1 : Wend 
    	
        DataW.HighByte = ADRESH 
        DataW.LowByte = ADRESL
    
    	b_level = 0
    	if DataW < 805 then
            	if DataW > 50  AND DataW < 160 THEN b_level = 1
            	if DataW > 180 AND DataW < 270 THEN b_level = 2
            	if DataW > 290 AND DataW < 380 THEN b_level = 3
            	if DataW > 400 AND DataW < 500 THEN b_level = 4
            	if DataW > 540 AND DataW < 650 THEN b_level = 5
            	if DataW > 690 AND DataW < 800 THEN b_level = 6
    	ENDIF
    RETURN

  9. #9
    Join Date
    Dec 2008
    Location
    Ploiesti, ROMANIA
    Posts
    579


    Did you find this post helpful? Yes | No

    Default Re: How to measure how long I pressed a button ?

    Thanks !
    But nothing on serial ...(in Proteus 8)
    Last edited by fratello; - 28th March 2024 at 18:33.

  10. #10
    Join Date
    Nov 2003
    Location
    Greece
    Posts
    3,807


    Did you find this post helpful? Yes | No

    Default Re: How to measure how long I pressed a button ?

    forget Proteus.

    Also I think Henrik forgot to add the label Exit: just before the Serout command.

    Ioannis
    Last edited by Ioannis; - 28th March 2024 at 19:03.

  11. #11
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,521


    Did you find this post helpful? Yes | No

    Default Re: How to measure how long I pressed a button ?

    No, I did not forget to add a label.
    EXIT is a keyword used to break out of the current loop.

    AI, simulation, virtualization.... What happened to the good old breadboard?

    Do I really need to spin this up on my dev board here or can you do some troubleshooting on your own and not just say "it's not working". You did include the same setupcode used before didn't you?

  12. #12
    Join Date
    Dec 2008
    Location
    Ploiesti, ROMANIA
    Posts
    579


    Did you find this post helpful? Yes | No

    Default Re: How to measure how long I pressed a button ?

    It works ! Finally, the first program that shows me the duration. BUT .... the correct identification of the pressed button does not work ! I pressed ONLY button 0 : short or long ...It doesn't matter which button I press: if I press it briefly it indicates button 0, if I press it long it indicates button 5. Why?
    Anyway thanks for pointing into a good direction !
    Name:  term.jpg
Views: 98
Size:  35.5 KB


    Solved !
    Name:  term2.jpg
Views: 98
Size:  29.6 KB
    Last edited by fratello; - 29th March 2024 at 10:23.

  13. #13
    Join Date
    May 2013
    Location
    australia
    Posts
    2,389


    Did you find this post helpful? Yes | No

    Default Re: How to measure how long I pressed a button ?

    AI, simulation, virtualization.... What happened to the good old breadboard?
    the chances of AI finding well written pbp code to plagiarize from are slim at best.
    afaics AI can only write code if it can plagiarize it from somewhere, the code only works if the stolen code exactly matched your circumstances.
    its quite amazing that this plagiarism is tolerated just because a machine is stealing it. open source etc. does not mean you can copy it and pass it off as your own original work.
    breadboard , the manual and a data sheet is at least an honest and rewarding learning experience

    henriks work as it needs to be

    Code:
    #CONFIG
    cfg =  _INTRC_OSC_NOCLKOUT
    cfg&= _WDT_ON
    cfg&= _PWRTE_OFF
    cfg&= _MCLRE_ON
    cfg&= _BODEN_ON
    cfg&= _CP_OFF
    cfg&= _CPD_OFF
      __CONFIG cfg
    #ENDCONFIG
    
    
        CMCON    = 7
        TRISIO   = 111001
        INTCON   = $C0 
        PIE1.0   = 1
        ANSEL    = 110001
        ADCON0 = 000001
    Long_Press CON 5000
    Short_Press con 100
    
    
    cnt VAR WORD
    b_level VAR BYTE
    but     VAR BYTE
    DataW VAR WORD
    
    
    Main:
        GOSUB ReadButton
        
        IF but > 0 THEN
            cnt = 0
            WHILE but > 0  
               cnt = cnt + 10  
               if cnt > Long_Press THEN EXIT
               PAUSE 10
               GOSUB ReadButton
            WEND
            
            SEROUT GPIO.2, 2, ["You pressed button ", #b_level, " for ", #cnt, "ms", 13, 10]
        endif
    Goto Main    
    
    
    
    
    ReadButton:
        ADCON0.1 = 1
        While ADCON0.1 = 1 : Wend 
        
        DataW.HighByte = ADRESH 
        DataW.LowByte = ADRESL
    
    
        but = 0
        if DataW < 805 then
                but=1
                if DataW > 50  AND DataW < 160 THEN b_level = 1
                if DataW > 180 AND DataW < 270 THEN b_level = 2
                if DataW > 290 AND DataW < 380 THEN b_level = 3
                if DataW > 400 AND DataW < 520 THEN b_level = 4
                if DataW > 540 AND DataW < 650 THEN b_level = 5
                if DataW > 690 AND DataW < 800 THEN b_level = 6
        ENDIF
    RETURN
    Warning I'm not a teacher

  14. #14
    Join Date
    May 2013
    Location
    australia
    Posts
    2,389


    1 out of 1 members found this post helpful. Did you find this post helpful? Yes | No

    Default Re: How to measure how long I pressed a button ?

    a bit fancier


    Code:
    #CONFIGcfg =  _INTRC_OSC_NOCLKOUT
    cfg&= _WDT_ON
    cfg&= _PWRTE_OFF
    cfg&= _MCLRE_ON
    cfg&= _BODEN_ON
    cfg&= _CP_OFF
    cfg&= _CPD_OFF
      __CONFIG cfg
    #ENDCONFIG
        DEFINE INTHAND _TICK
        
        DEFINE DEBUG_REG GPIO
        DEFINE DEBUG_BIT 2
        DEFINE DEBUG_BAUD 9600
        DEFINE DEBUG_MODE 0
        
        CMCON    = 7
        TRISIO   = 111001
        INTCON   = $C0 
        PIE1.0   = 1
        ANSEL    = 110001
    CLEAR
    ' Constante
    TimerReload   CON   61637     ;3.906mS
    ' Variabile
    W_TEMP        VAR BYTE BANK0
    STATUS_TEMP   VAR BYTE BANK0
    MILLIES       var word BANK0
    b_level       var byte
    b_state       var byte
    NOW           var word
    LEDT          var word
    buttont       var word
    duration      var word
    DataW         var word
    
    
    GPIO.2 = 0
    ADCON0 = 000001
    T1CON = 000001 'Prescaler 1:1,Timer1  ON  
    
    
    Main:
        PIE1.0 = 0
        NOW = MILLIES    ;in 3.906mS ticks
        PIE1.0 = 1
        IF NOW - LEDT > 250 THEN    ;1 sec
            LEDT = NOW
            TOGGLE GPIO.1
        ENDIF
        ADCON0.1 = 1
        While ADCON0.1 = 1 : Wend 
        DataW.HighByte = ADRESH 
        DataW.LowByte  = ADRESL
        if DataW < 805 then
                if DataW > 50  AND DataW < 160 THEN b_level = 1
                if DataW > 180 AND DataW < 270 THEN b_level = 2
                if DataW > 290 AND DataW < 380 THEN b_level = 3
                if DataW > 400 AND DataW < 520 THEN b_level = 4
                if DataW > 540 AND DataW < 650 THEN b_level = 5
                if DataW > 690 AND DataW < 800 THEN b_level = 6
          if  b_state == 0 then      
                b_state  = 1 
                buttont  = now
          else
                DEBUG "button ",#b_level, 13, 10
          endif
        ELSE 
          if   b_state then
    '           duration = (now - buttont)<<2
               duration = now - buttont
               buttont = duration.lowbyte */1000
               b_state  = 0 
               DEBUG "Pressed button ",#b_level," for : ", #duration.highbyte,".",#buttont, " S", 13, 10
    '           DEBUG "Pressed button ",#b_level," for : ", #duration, "mS", 13, 10
               b_level = 0
          endif
        endif 
    GOTO Main
    
    
    
    
    TICK:            ;isr
    asm
        MOVWF _W_TEMP ;copy W to temp register,could be in either bank
        SWAPF STATUS,W ;swap status to be saved into W
        BCF STATUS,RP0 ;change to bank 0 regardless of     current bank
        MOVWF _STATUS_TEMP
        MOVE?CT 0, T1CON, TMR1ON ; stop timer
        MOVLW LOW(_TimerReload) ; Add TimerReload
        ADDWF TMR1L,F
        BTFSC STATUS,C
        INCF TMR1H,F
        MOVLW HIGH(_TimerReload)
        ADDWF TMR1H,F
        MOVE?CT 1, T1CON, TMR1ON ; start timer
        MOVE?CT 0, PIR1, TMR1IF ; CLR timer FLAG
        INCF _MILLIES ,F
        BTFSC STATUS,Z
        INCF _MILLIES+1 ,F
        SWAPF _STATUS_TEMP,W;swap STATUS_TEMP register int    W, sets bank to original state
        MOVWF STATUS ;move W into STATUS register
        SWAPF _W_TEMP,F ;swap W_TEMP
        SWAPF _W_TEMP,W ;swap W_TEMP into W
        RETFIE
    endASM
    Last edited by richard; - 29th March 2024 at 11:04. Reason: note modified button 4 for my testing
    Warning I'm not a teacher

  15. #15
    Join Date
    Dec 2008
    Location
    Ploiesti, ROMANIA
    Posts
    579


    Did you find this post helpful? Yes | No

    Default Re: How to measure how long I pressed a button ?

    Thank you very much !!! I can't wait to test it at the weekend !

    LE : I use PBP 2.5, so TimerReload CON 61637 = WARNING Line 10: 111001 Numeric overflow, value truncated.
    Last edited by fratello; - 29th March 2024 at 11:14.

  16. #16
    Join Date
    May 2013
    Location
    australia
    Posts
    2,389


    Did you find this post helpful? Yes | No

    Default Re: How to measure how long I pressed a button ?

    I use PBP 2.5, so
    i know nothing about ancient history

    and the number is word sized anyway
    Warning I'm not a teacher

  17. #17
    Join Date
    Dec 2008
    Location
    Ploiesti, ROMANIA
    Posts
    579


    Did you find this post helpful? Yes | No

    Default Re: How to measure how long I pressed a button ?

    Mea culpa ... I identified and corrected the errors.Name:  my_err.jpg
Views: 100
Size:  54.8 KB

  18. #18


    Did you find this post helpful? Yes | No

    Default Re: How to measure how long I pressed a button ?

    I would think tighten up the adc values comparisons to fill in the gaps so reading doesn't fall off........ <160 next to >161, etc

  19. #19
    Join Date
    Dec 2008
    Location
    Ploiesti, ROMANIA
    Posts
    579


    Did you find this post helpful? Yes | No

    Default Re: How to measure how long I pressed a button ?

    In the initial software, I use a procedure to check the pressed button; if 10 presses have the same ADC as a result, then I validate the button press. I tried to complete the code proposed above with this verification procedure. But, although the results APPEAR to be correct, on the breadboard the assembly does not work at all, none of the 6 commands are executed (of course, I commented Serout instruction and uncomment the other instruction) . Please, could you identify what exactly I did wrong?

    Main:
    apasat=0
    adcvalue=0

    GOSUB ReadButton

    IF b_level > 0 THEN
    cnt = 0
    WHILE b_level > 0
    cnt = cnt + 10
    if cnt > Long_Press THEN
    actiune = 1
    EXIT
    endif
    PAUSE 5
    GOSUB ReadButton
    WEND
    b_level = 0
    if b_act = 1 then gosub comenzi ; if button pressed is OK, no error
    ENDIF
    Goto Main


    ReadButton:
    ADCON0.1 = 1
    While ADCON0.1 = 1 : Wend

    DataW.HighByte = ADRESH
    DataW.LowByte = ADRESL
    b_level = 0
    actiune = 0
    IF DataW < 805 then
    if DataW > 50 AND DataW < 160 THEN b_level = 1
    if DataW > 180 AND DataW < 270 THEN b_level = 2
    if DataW > 290 AND DataW < 380 THEN b_level = 3
    if DataW > 400 AND DataW < 500 THEN b_level = 4
    if DataW > 540 AND DataW < 650 THEN b_level = 5
    if DataW > 690 AND DataW < 800 THEN b_level = 6

    apasat = b_level
    adcvalue=DataW

    if apasat=last_b_level then ; procedure for cheking pressed button
    b_cnt=b_cnt+1
    pauseus 200
    if b_cnt > 10 then b_act = 1 ; button pressed is OK
    endif

    last_b_level=apasat
    ENDIF

    RETURN

    ;================================================= ===========================

    comenzi:
    SEROUT GPIO.2, 2, ["You pressed button ", #apasat, " for ", #cnt, " ms", " ACTIUNE: ", #actiune, " ok ? ", #b_act, 13, 10]
    ;IF b_level=1 THEN gosub comand1
    ;IF b_level=2 THEN gosub comand2
    ;IF b_level=3 THEN gosub comand3
    ;IF b_level=4 THEN
    ; if actiune = 1 then
    ; gosub comand1
    ; else
    ; gosub comand 4
    ; endif
    ;ENDIF
    ;IF b_level=5 THEN gosub comand5
    ;IF b_level=6 THEN gosub comand6


    last_b_level=0
    b_cnt=0
    Return
    Last edited by fratello; - 2nd April 2024 at 08:34.

Similar Threads

  1. TMR1 & Button - long delay (1 min) before starting
    By flotulopex in forum mel PIC BASIC Pro
    Replies: 9
    Last Post: - 14th March 2017, 13:03
  2. Long / short press button...but reading ADC
    By fratello in forum mel PIC BASIC Pro
    Replies: 37
    Last Post: - 10th July 2016, 08:37
  3. Replies: 5
    Last Post: - 26th February 2011, 05:51
  4. Replies: 1
    Last Post: - 14th October 2010, 18:33
  5. Button pressed time control
    By tanero in forum mel PIC BASIC Pro
    Replies: 12
    Last Post: - 15th August 2005, 15:17

Members who have read this thread : 17

You do not have permission to view the list of names.

Posting Permissions

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