消除操纵杆按钮输入

时间:2011-07-05 05:56:09

标签: python hardware joystick gobject

我有一个用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) 

2 个答案:

答案 0 :(得分:2)

有许多方法可以去抖按钮。一种简单,无阻塞的方法是:

  1. 反复检查按钮的状态,随着时间的推移......
  2. ...如果按钮“瞬时”状态不是被认为是“活跃”的状态那么......
  3. ...增加一个计数器......
  4. ...如果计数器达到给定的阈值,则切换按钮的“活动”状态。
  5. 每次“瞬时”和“活动”状态相同时,应重置计数器
  6. 此方法要求检查程序以合理的固定间隔运行,因为反应时间由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定义的常量。

    HTH!

答案 1 :(得分:0)

通常,在x,y和按钮触点之间分别有一个1uF / 10uF电容器,并且GND会反跳,因此不需要代码。