1

我有一个用 gobject 用 python 编写的操纵杆类,除了一个小问题外,它工作得很好。当我运行下面的代码时按钮弹跳,它会多次按下所有按钮。如何以合理的准确性将其减少到每次按下按钮时一条消息?

''' 
Copyright 2009 Jezra Lickter 

This software is distributed AS IS. Use at your own risk. 
If it borks your system, you have  been forewarned. 

This software is licensed under the LGPL Version 3 
http://www.gnu.org/licenses/lgpl-3.0.txt 


for documentation on Linux Joystick programming please see 
http://www.mjmwired.net/kernel/Documentation/input/joystick-api.txt 
''' 

import gobject #needed for sending signals 
import struct #needed for holding chunks of data 

class Joystick(gobject.GObject): 
    '''The Joystick class is a GObject that sends signals that represent 
    Joystick events''' 
    EVENT_BUTTON = 0x01 #button pressed/released 
    EVENT_AXIS = 0x02  #axis moved  
    EVENT_INIT = 0x80  #button/axis initialized  
    #see http://docs.python.org/library/struct.html for the format determination 
    EVENT_FORMAT = "IhBB" 
    EVENT_SIZE = struct.calcsize(EVENT_FORMAT) 

    # we need a few signals to send data to the main 
    '''signals will return 4 variables as follows: 
    1. a string representing if the signal is from an axis or a button 
    2. an integer representation of a particular button/axis 
    3. an integer representing axis direction or button press/release 
    4. an integer representing the "init" of the button/axis 
    ''' 
    __gsignals__ = { 
    'axis' : 
    (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, 
    (gobject.TYPE_INT,gobject.TYPE_INT,gobject.TYPE_INT)), 
    'button' : 
    (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, 
    (gobject.TYPE_INT,gobject.TYPE_INT,gobject.TYPE_INT)) 
    } 


    def __init__(self,dev_num): 
        gobject.GObject.__init__(self) 
        #define the device 
        device = '/dev/input/js%s' % dev_num 
        #error check that this can be read 
        try: 
            #open the joystick device 
            self.device = open(device) 
            #keep an eye on the device, when there is data to read, execute the read         function 
            gobject.io_add_watch(self.device,gobject.IO_IN,self.read_buttons) 
        except Exception,ex: 
            #raise an exception 
            raise Exception( ex ) 

    def read_buttons(self, arg0='', arg1=''): 
        ''' read the button and axis press event from the joystick device 
        and emit a signal containing the event data 
        ''' 
        #read self.EVENT_SIZE bytes from the joystick 
        read_event = self.device.read(self.EVENT_SIZE)   
        #get the event structure values from  the read event 
        time, value, type, number = struct.unpack(self.EVENT_FORMAT, read_event) 
        #get just the button/axis press event from the event type  
        event = type & ~self.EVENT_INIT 
        #get just the INIT event from the event type 
        init = type & ~event 
        if event == self.EVENT_AXIS: 
            signal = "axis" 
        elif event == self.EVENT_BUTTON: 
            signal = "button" 
        if signal: 
            print("%s %s %s %s" % (signal,number,value,init) ) 
            self.emit(signal,number,value,init) 

        return True 

if __name__ == "__main__": 
    try: 
        j = Joystick(0) 
        loop = gobject.MainLoop() 
        loop.run() 
    except Exception,e: 
        print(e) 
4

2 回答 2

3

有很多方法可以消除按钮的抖动。一个简单的、非阻塞的方法是:

  1. 随着时间的推移反复检查按钮的状态,然后......
  2. ...如果按钮“瞬间”状态不是被认为是“活动”的状态,那么...
  3. ...增加一个计数器和...
  4. ...如果计数器达到给定阈值,则切换按钮的“活动”状态。
  5. 每次“瞬时”和“活动”状态相同时,都应重置计数器

当然,这种方法要求检查程序以合理的定期间隔运行,因为反应时间由 给出frequency*threshold

编辑:我没有实际运行它的硬件,但去抖动方法应该类似于:

if button_now() != button_state:
    debounce_counter += 1
    if debounce_counter == DEBOUNCE_THRESHOLD:
        button_state = not button_state
else:
    debounce_counter = 0

在上面的代码中:

  • button_now()轮询硬件(并True/False根据按钮电路是闭合还是断开返回),
  • button_state是程序的其余部分如何“看到”按钮(再次:True/False根据按钮向下或向上),`
  • DEBOUNCE_THRESHOLD是你根据公式定义的常数reaction-time-of-the-button = frequency-of-debouncing-routine * threshold

于 2011-07-05T06:08:04.357 回答
0

通常,在 x、y 和按钮触点之间各有一个 1uF/10uF 电容器和 GND 硬件去抖动,因此不需要代码。

于 2019-06-26T12:22:47.960 回答