Устранение дребезга кнопок джойстика

У меня есть класс джойстика, написанный на питоне с gobject, он отлично работает, за исключением одной небольшой проблемы. Отскок кнопки, когда я запускаю приведенный ниже код, он фиксирует все нажатия кнопок несколько раз. Как я могу сократить это до одного сообщения на нажатие кнопки с разумной точностью?

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

person giodamelio    schedule 05.07.2011    source источник
comment
См. stackoverflow.com/questions/155071/simple-debounce-routine.   -  person mtrw    schedule 05.07.2011


Ответы (2)


Есть много способов устранить дребезг кнопок. Простой, неблокирующий способ сделать это:

  1. Неоднократно проверяйте состояние кнопки с течением времени и...
  2. ... если "мгновенное" состояние кнопки не считается "активным", то...
  3. ...увеличить счетчик и...
  4. ... если счетчик достигает заданного порога, переключает «активное» состояние кнопки.
  5. Счетчик следует сбрасывать каждый раз, когда «мгновенное» и «активное» состояния совпадают.

Этот метод требует, чтобы процедура проверки выполнялась через разумные регулярные интервалы времени, поскольку время реакции задается frequency*threshold.

EDIT: у меня нет аппаратного обеспечения, чтобы запустить это, но метод устранения дребезга должен выглядеть примерно так:

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.

ХТХ!

person mac    schedule 05.07.2011
comment
что означает переменная button_state? - person giodamelio; 05.07.2011
comment
У меня небольшие проблемы с тем, чтобы это работало с моим кодом. Дело в том, что у меня есть система событий, которая вызывает функцию при нажатии кнопки. Этот код действительно не работает с моей настройкой :(. - person giodamelio; 05.07.2011
comment
@giodamelio - Если вы программируете игру, ваша функция устранения дребезга должна генерировать событие нажатия кнопки для остальной части программы (вместо этого HID следует опрашивать, когда программа простаивает, иначе вы получите дрожание). Наиболее очевидной альтернативой является запуск процедуры блокировки устранения дребезга (например, прерывания): при нажатии кнопки подождите X миллисекунд и снова запросите кнопку. Если кнопка все еще нажата, распространите событие дальше. Но это заблокирует выполнение основной программы. Все кнопки, которые я использовал, имеют время устранения дребезга ~ 20 мс. - person mac; 05.07.2011

Обычно конденсаторы 1 мкФ/10 мкФ между контактами x, y и кнопки, а также заземление аппаратно устраняют дребезг, поэтому код не требуется.

person Systembolaget    schedule 26.06.2019