Wednesday, September 13, 2017

Raspberry Pi detect keypress(es) and duration

Today I started my first Raspberry Pi project which involves HW (tactile switch). Setting up the required components on a proto board turned out to be less complex as expected, but when searching for python code to detect long/short keypress events (and eventually measure the time as well) I've not found nothing really useful. Thus I decided to accept the challenge and implement my own solution to distinguish between long an short key presses (via callback function) and to measure the time in ms.

import os
import RPi.GPIO as GPIO
import time

longpress_ctms=lambda: int(round(time.time()*1000))
longpress_cfg={}
longpress_event={}

def longpress_add(channel,bt,min,longcb,shortcb):
    global longpress_cfg

    longpress_cfg[channel]=dict({'bt':bt,'min':min,'lcb':longcb,'scb':shortch})
    GPIO.setup(channel,GPIO.IN,pull_up_down=GPIO.PUD_DOWN)
    GPIO.add_event_detect(channel,GPIO.BOTH,callback=longpress_cb,bouncetime=longpress_cfg[channel]['bt'])

def longpress_cb(channel):
    if GPIO.input(channel):
        longpress_press(channel)
    else:
        longpress_release(channel)
    
def longpress_press(channel):
    global longpress_event

    longpress_event[channel]=longpress_ctms()

def longpress_release(channel):
    global longpress_event
    
    dur=longpress_ctms()-longpress_event[channel]
    if dur>=longpress_cfg[channel]['min']:
        longpress_cfg[channel]['lcb'](channel,dur)
    else:
        longpress_cfg[channel]['scb'](channel,dur)

# Callbacks
def long(channel,duration):
    print 'Long press for channel '+str(channel)+' ('+str(duration)+'ms)'

def short(channel,duration):
    print 'Short press for channel '+str(channel)+' ('+str(duration)+'ms)'

# Init
GPIO.setmode(GPIO.BCM)
longpress_add(18,75,1000,long,short)
longpress_add(23,75,1000,long,short)

# Main loop
try:
    while True:
        time.sleep(1000)
except KeyboardInterrupt:
    pass
finally:
    GPIO.cleanup()


Parameters for "longpress_add" are:

channel - channel/pin to detect keypress for
bt - minimum time (bouncetime) between two callbacks in milliseconds
min - minimum duration for long presses
longcb - callback for long presses
shortcb - callback for short presses

Running the python script from above (for channel 18 + 23) I do get the following output:

$ python longpress.py
Short press for channel 18 (551ms)
Long press for channel 18 (2683ms)
Short press for channel 23 (312ms)
Long press for channel 23 (2081ms)
^C

I hope this post inspires you to create some fancy Raspberry Pi solutions as well and to share them with the community.

PS: This is one of my first python scripts ever, so please be gentle if there are some coding issues ...

No comments: