""" GPIO Pin Debouncer Adafruit invests time and resources providing this open source code. Please support Adafruit and open source hardware by purchasing products from Adafruit! Written by Dave Astels for Adafruit Industries Copyright (c) 2018 Adafruit Industries Licensed under the MIT license. All text above must be included in any redistribution. """ import time import digitalio class Debouncer(object): """Debounce an input pin""" DEBOUNCED_STATE = 0x01 UNSTABLE_STATE = 0x02 CHANGED_STATE = 0x04 def __init__(self, pin, mode=None, interval=0.010): """Make am instance. :param int pin: the pin (from board) to debounce :param int mode: digitalio.Pull.UP or .DOWN (default is no pull up/down) :param int interval: bounce threshold in seconds (default is 0.010, i.e. 10 milliseconds) """ self.state = 0x00 self.pin = digitalio.DigitalInOut(pin) self.pin.direction = digitalio.Direction.INPUT if mode != None: self.pin.pull = mode if self.pin.value: self.__set_state(Debouncer.DEBOUNCED_STATE | Debouncer.UNSTABLE_STATE) self.previous_time = 0 if interval is None: self.interval = 0.010 else: self.interval = interval def __set_state(self, bits): self.state |= bits def __unset_state(self, bits): self.state &= ~bits def __toggle_state(self, bits): self.state ^= bits def __get_state(self, bits): return (self.state & bits) != 0 def update(self): """Update the debouncer state. Must be called before using any of the properties below""" self.__unset_state(Debouncer.CHANGED_STATE) current_state = self.pin.value if current_state != self.__get_state(Debouncer.UNSTABLE_STATE): self.previous_time = time.monotonic() self.__toggle_state(Debouncer.UNSTABLE_STATE) else: if time.monotonic() - self.previous_time >= self.interval: if current_state != self.__get_state(Debouncer.DEBOUNCED_STATE): self.previous_time = time.monotonic() self.__toggle_state(Debouncer.DEBOUNCED_STATE) self.__set_state(Debouncer.CHANGED_STATE) @property def value(self): """Return the current debounced value of the input.""" return self.__get_state(Debouncer.DEBOUNCED_STATE) @property def rose(self): """Return whether the debounced input went from low to high at the most recent update.""" return self.__get_state(self.DEBOUNCED_STATE) and self.__get_state(self.CHANGED_STATE) @property def fell(self): """Return whether the debounced input went from high to low at the most recent update.""" return (not self.__get_state(self.DEBOUNCED_STATE)) and self.__get_state(self.CHANGED_STATE)