I've been looking for a while to how to get the kind of click of a button on GPIO. Is it a single click? Double? Triple or more? Is it a long click? a very long click? a combination of them?

I haven't found a good solution to this problem out there, so I hope to do something useful sharing my solution here.

import RPi.GPIO as GPIO
import time
import threading

BtnPin = 40 # GPIO pin

timeout = 0.5 # how long can pass between two clicks to consider them part of the same event
short_click = 0.65 # length of a single click
long_click = 1.0 # length of a long click
very_long_click = 4.0 # length of a veeeery long click

# set up the GPIO pins to register the presses
GPIO.setup(BtnPin, GPIO.IN, pull_up_down=GPIO.PUD_UP)    # Set BtnPin's mode is input

# returns the kind ok click
def pressed():
    start_time = time.time()
    while not GPIO.input(BtnPin):
    pressed_time = time.time() - start_time
    if pressed_time < short_click:
        return 'short'
    elif pressed_time > very_long_click:
        return 'very long'
        return 'long'

# returns the kind of click event
def pressing():
    global clicks
    tmpclicks = []
    start_time = time.time()
    while time.time() - start_time < timeout:
        if not GPIO.input(BtnPin):
            start_time = time.time()
    clicks = tmpclicks

clicks = [] # set up an empty list for the kind of clicks

lasting = 0

while True:
    print (lasting) # just to show you can do other while getting the clicks
    lasting +=1
    # we create a thread for getting click events so we can other while waiting for the clicks
    except NameError:
        if not GPIO.input(BtnPin):
            t= threading.Thread(target=pressing)
        if clicks:
            if clicks == ['short']:
                print ("Single click")
            elif clicks == ['short', 'short']:
                print ("Double click")
            elif clicks == ['short','short', 'short']:
                print ("Triple click")
            elif clicks == ['long']:
                print ("Long click")
            elif clicks == ['long', 'long']:
                print ("Double long click")
            elif clicks == ['very long']:
                print ("Very long click")
            clicks = []
            del t

clicks is a list, so you can detect different kinds and combinations of events.

  • 1
    It would be simpler to use the held options in gpiozero.readthedocs.io/en/stable/api_input.html#button – Milliways Jun 15 '19 at 23:53
  • You program is good. I neither have read program differentiating short, long, and multiple clicks. Many programs might deal with things like software debouncing etc, but that is not what you are interested here. I read (but I have not tried) that other hackers might use event driven interrupt functions to detect button clicks. They also use python "dictionary" datatype to define click types. I often use dictionaries to define new things. This way you can easily expand or structure up you dictonary WITHOUT modifying you procedural function by adding more elif's, thus no so error prone. – tlfong01 Jun 16 '19 at 3:32
  • I forgot to say why you idea is good. I have been playing with 4 key to 16 key keypads. Now I hope to use only one key to represent more than one thing I wish to do. So if I press a key shortly, I would hear one beep. If I press longer, say, 4 seconds, then I would hear 4 beeps and meaning that I want number 4. Of course it is nothing new, many home appliances like induction cooker for example might have 4 or 5 buttons and one LCD display to replace a 16 key keypad. This is sort of UI, user interface design, and getting important in IoT devices with little space for large keypads. – tlfong01 Jun 16 '19 at 3:43
  • @Milliways, thank you for pointing out that option, I'll check it out! – GIMBorgo Jun 18 '19 at 7:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.