1

gobject を使用して python で記述されたジョイスティック クラスがありますが、1 つの小さな問題を除いてうまく機能します。以下のコードを実行するとボタンがバウンスし、すべてのボタンが複数回押されたことが検出されます。合理的な精度で、ボタンを押すごとに1つのメッセージに減らすにはどうすればよいですか?

''' 
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

HTH!

于 2011-07-05T06:08:04.357 に答える