Skip to content

Commit

Permalink
Merge pull request #38 from Neradoc/better-button-class
Browse files Browse the repository at this point in the history
Update Button class to match debouncer logic
  • Loading branch information
FoamyGuy committed Mar 21, 2022
2 parents 72b7319 + a2508e8 commit 4b0f67f
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 29 deletions.
15 changes: 14 additions & 1 deletion .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
62 changes: 38 additions & 24 deletions adafruit_debouncer.py
Expand Up @@ -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
9 changes: 5 additions & 4 deletions examples/debouncer_multi.py
Expand Up @@ -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 !")

0 comments on commit 4b0f67f

Please sign in to comment.