diff --git a/.gitignore b/.gitignore index 7926313..2c6ddfd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,18 @@ -# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries +# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries # # SPDX-License-Identifier: Unlicense *.mpy +.idea +__pycache__ +_build +*.pyc +.env +.python-version +build*/ +bundles +*.DS_Store +.eggs +dist +**/*.egg-info +.vscode diff --git a/adafruit_debouncer.py b/adafruit_debouncer.py index 5182e5f..868a217 100644 --- a/adafruit_debouncer.py +++ b/adafruit_debouncer.py @@ -133,75 +133,89 @@ def current_duration(self): class Button(Debouncer): - """Debounce counter""" + """ + Debouncer for buttons. Reports ``pressed`` and ``released`` for the button state. + Counts multiple short presses, allowing to detect double clicks, triple clicks, etc. + Reports long presses separately. A long press can immediately follow multiple clicks, + in which case the long click will be reported in the same update as the short clicks. + + :param DigitalInOut/function pin: the DigitalIO or function to debounce. + :param int short_duration_ms: the maximum length of a short press in milliseconds. + :param int long_duration_ms: the minimum length of a long press in milliseconds. + :param bool value_when_pressed: the value of the predicate when the button is + pressed. Defaults to False (for pull up buttons). + """ def __init__( self, pin, short_duration_ms=200, long_duration_ms=500, - active_down=True, + value_when_pressed=False, **kwargs ): self.short_duration_ms = short_duration_ms self.long_duration_ms = long_duration_ms - self.active_down = active_down + self.value_when_pressed = value_when_pressed self.last_change_ms = ticks_ms() self.short_counter = 0 self.short_to_show = 0 self.long_registered = False - self.long_showed = False + self.long_to_show = False super().__init__(pin, **kwargs) - def _pushed(self): - return (self.active_down and super().fell) or ( - not self.active_down and super().rose + @property + def pressed(self): + """Return whether the button was pressed or not at the last update.""" + return (self.value_when_pressed and self.rose) or ( + not self.value_when_pressed and self.fell ) - def _released(self): - return (self.active_down and super().rose) or ( - not self.active_down and super().fell + @property + def released(self): + """Return whether the button was release or not at the last update.""" + return (self.value_when_pressed and self.fell) or ( + not self.value_when_pressed and self.rose ) def update(self, new_state=None): super().update(new_state) - if self._pushed(): + if self.pressed: self.last_change_ms = ticks_ms() self.short_counter = self.short_counter + 1 - elif self._released(): + elif self.released: self.last_change_ms = ticks_ms() if self.long_registered: self.long_registered = False - self.long_showed = False else: duration = ticks_diff(ticks_ms(), self.last_change_ms) if ( not self.long_registered - and self.value != self.active_down + and self.value == self.value_when_pressed and duration > self.long_duration_ms ): self.long_registered = True + self.long_to_show = True self.short_to_show = self.short_counter - 1 self.short_counter = 0 elif ( self.short_counter > 0 - and self.value == self.active_down + and self.value != self.value_when_pressed and duration > self.short_duration_ms ): self.short_to_show = self.short_counter self.short_counter = 0 + else: + self.long_to_show = False + self.short_to_show = 0 @property def short_count(self): - """Return the number of short press""" - ret = self.short_to_show - self.short_to_show = 0 - return ret + """Return the number of short press if a series of short presses has + ended at the last update.""" + return self.short_to_show @property def long_press(self): - """Return whether long press has occured""" - if self.long_registered and not self.long_showed: - self.long_showed = True - return True - return False + """Return whether a long press has occured at the last update.""" + return self.long_to_show diff --git a/examples/debouncer_multi.py b/examples/debouncer_multi.py index 976cd84..424ca78 100644 --- a/examples/debouncer_multi.py +++ b/examples/debouncer_multi.py @@ -15,7 +15,8 @@ while True: switch.update() if switch.long_press: - print("long") - count = switch.short_count - if count != 0: - print("count=", count) + print("Long Press") + if switch.short_count != 0: + print("Short Press Count =", switch.short_count) + if switch.long_press and switch.short_count == 1: + print("That's a long double press !")