1

I'd like to detect multiple presses of the same button and interpret that differently, for example "tap" means to do function A and "tap-tap" means to do function B.

I've been doing some googling but haven't yet come across a detailed solution for this. I'm sure I can figure out an algorithm/implementation from scratch if I need to, but I'd rather not re-invent the wheel. Ideally this would be implemented in NodeJS, but I can translate the concepts from another language if need be.

1

Here's the solution I came up with:

'use strict'

const Gpio = require('pigpio').Gpio

class PushButton extends Gpio {

    constructor(gpioPin, double_tap_interval_ms = 400) {
        super(gpioPin, {
            mode: Gpio.INPUT,
            pullUpDown: Gpio.PUD_DOWN,
            edge: Gpio.FALLING_EDGE,            
            alert: true
        });
        this.glitchFilter(10000)
        this.double_tap_interval_ms = double_tap_interval_ms
        this.previous_tap_tick = 0
        this.double_tap_timeout = undefined

        this.on('alert', (level, tick) => {
            if (level == 1) {
                if (this.previous_tap_tick == 0) {
                    // This prevents the math below from screwing up the 
                    // difference check on the first execution
                    this.previous_tap_tick = tick - (this.double_tap_interval_ms * 1000) - 1
                }

                // This difference uses the JavaScript sign propagating right shift 
                // operator to prevent subtraction errors when the tick wraps around.
                // See https://github.com/fivdi/pigpio/blob/master/doc/gpio.md#event-alert
                // for more info.

                let difference = ((tick >> 0) - (this.previous_tap_tick >> 0))
                if (difference / 1000 < this.double_tap_interval_ms) {
                    clearTimeout(this.double_tap_timeout)
                    this.emit('double-tap')
                }
                else {
                    this.double_tap_timeout = setTimeout(() => {
                        this.emit('single-tap')
                    }, this.double_tap_interval_ms)
                    this.previous_tap_tick = tick
                }
            }
        })
    }
}

module.exports = PushButton


// For example:

let b = new PushButton(24)
b.on('single-tap', ()=> {
    console.log('caught single-tap')
})

b.on('double-tap', ()=> {
    console.log('caught double-tap')
})
-1

Look-up "state machine" concept.

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.