Skip to content

Commit 4b0f67f

Browse files
authored
Merge pull request #38 from Neradoc/better-button-class
Update Button class to match debouncer logic
2 parents 72b7319 + a2508e8 commit 4b0f67f

File tree

3 files changed

+57
-29
lines changed

3 files changed

+57
-29
lines changed

.gitignore

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,18 @@
1-
# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
1+
# SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries
22
#
33
# SPDX-License-Identifier: Unlicense
44

55
*.mpy
6+
.idea
7+
__pycache__
8+
_build
9+
*.pyc
10+
.env
11+
.python-version
12+
build*/
13+
bundles
14+
*.DS_Store
15+
.eggs
16+
dist
17+
**/*.egg-info
18+
.vscode

adafruit_debouncer.py

Lines changed: 38 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -133,75 +133,89 @@ def current_duration(self):
133133

134134

135135
class Button(Debouncer):
136-
"""Debounce counter"""
136+
"""
137+
Debouncer for buttons. Reports ``pressed`` and ``released`` for the button state.
138+
Counts multiple short presses, allowing to detect double clicks, triple clicks, etc.
139+
Reports long presses separately. A long press can immediately follow multiple clicks,
140+
in which case the long click will be reported in the same update as the short clicks.
141+
142+
:param DigitalInOut/function pin: the DigitalIO or function to debounce.
143+
:param int short_duration_ms: the maximum length of a short press in milliseconds.
144+
:param int long_duration_ms: the minimum length of a long press in milliseconds.
145+
:param bool value_when_pressed: the value of the predicate when the button is
146+
pressed. Defaults to False (for pull up buttons).
147+
"""
137148

138149
def __init__(
139150
self,
140151
pin,
141152
short_duration_ms=200,
142153
long_duration_ms=500,
143-
active_down=True,
154+
value_when_pressed=False,
144155
**kwargs
145156
):
146157
self.short_duration_ms = short_duration_ms
147158
self.long_duration_ms = long_duration_ms
148-
self.active_down = active_down
159+
self.value_when_pressed = value_when_pressed
149160
self.last_change_ms = ticks_ms()
150161
self.short_counter = 0
151162
self.short_to_show = 0
152163
self.long_registered = False
153-
self.long_showed = False
164+
self.long_to_show = False
154165
super().__init__(pin, **kwargs)
155166

156-
def _pushed(self):
157-
return (self.active_down and super().fell) or (
158-
not self.active_down and super().rose
167+
@property
168+
def pressed(self):
169+
"""Return whether the button was pressed or not at the last update."""
170+
return (self.value_when_pressed and self.rose) or (
171+
not self.value_when_pressed and self.fell
159172
)
160173

161-
def _released(self):
162-
return (self.active_down and super().rose) or (
163-
not self.active_down and super().fell
174+
@property
175+
def released(self):
176+
"""Return whether the button was release or not at the last update."""
177+
return (self.value_when_pressed and self.fell) or (
178+
not self.value_when_pressed and self.rose
164179
)
165180

166181
def update(self, new_state=None):
167182
super().update(new_state)
168-
if self._pushed():
183+
if self.pressed:
169184
self.last_change_ms = ticks_ms()
170185
self.short_counter = self.short_counter + 1
171-
elif self._released():
186+
elif self.released:
172187
self.last_change_ms = ticks_ms()
173188
if self.long_registered:
174189
self.long_registered = False
175-
self.long_showed = False
176190
else:
177191
duration = ticks_diff(ticks_ms(), self.last_change_ms)
178192
if (
179193
not self.long_registered
180-
and self.value != self.active_down
194+
and self.value == self.value_when_pressed
181195
and duration > self.long_duration_ms
182196
):
183197
self.long_registered = True
198+
self.long_to_show = True
184199
self.short_to_show = self.short_counter - 1
185200
self.short_counter = 0
186201
elif (
187202
self.short_counter > 0
188-
and self.value == self.active_down
203+
and self.value != self.value_when_pressed
189204
and duration > self.short_duration_ms
190205
):
191206
self.short_to_show = self.short_counter
192207
self.short_counter = 0
208+
else:
209+
self.long_to_show = False
210+
self.short_to_show = 0
193211

194212
@property
195213
def short_count(self):
196-
"""Return the number of short press"""
197-
ret = self.short_to_show
198-
self.short_to_show = 0
199-
return ret
214+
"""Return the number of short press if a series of short presses has
215+
ended at the last update."""
216+
return self.short_to_show
200217

201218
@property
202219
def long_press(self):
203-
"""Return whether long press has occured"""
204-
if self.long_registered and not self.long_showed:
205-
self.long_showed = True
206-
return True
207-
return False
220+
"""Return whether a long press has occured at the last update."""
221+
return self.long_to_show

examples/debouncer_multi.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@
1515
while True:
1616
switch.update()
1717
if switch.long_press:
18-
print("long")
19-
count = switch.short_count
20-
if count != 0:
21-
print("count=", count)
18+
print("Long Press")
19+
if switch.short_count != 0:
20+
print("Short Press Count =", switch.short_count)
21+
if switch.long_press and switch.short_count == 1:
22+
print("That's a long double press !")

0 commit comments

Comments
 (0)