From a4526a67ae1b8e69601624c5e8b6e7c11db9fc39 Mon Sep 17 00:00:00 2001 From: david gauchard Date: Tue, 25 Jan 2022 14:46:35 +0100 Subject: [PATCH 1/5] + Button class and example for short press counter and long press detector --- adafruit_debouncer.py | 55 +++++++++++++++++++++++++++++++++++++ examples/debouncer_multi.py | 20 ++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 examples/debouncer_multi.py diff --git a/adafruit_debouncer.py b/adafruit_debouncer.py index 7ab0579..feae0f4 100644 --- a/adafruit_debouncer.py +++ b/adafruit_debouncer.py @@ -127,3 +127,58 @@ def last_duration(self): def current_duration(self): """Return the number of seconds since the most recent transition.""" return ticks_diff(ticks_ms(), self._state_changed_ticks) / _TICKS_PER_SEC + + + +class Button(Debouncer): + """Debounce counter""" + def __init__(self, pin, short_duration = 0.2, long_duration = 0.5, active_down = True, **kwargs): + self.short_duration = short_duration + self.long_duration = long_duration + self.active_down = active_down + self.last_change_ticks = ticks_ms() + self.short_counter = 0 + self.short_showed = 0 + self.long_registered = False + self.long_showed = False + super(Button, self).__init__(pin, **kwargs) + + def pushed (self): + return (self.active_down and super().fell) or (not self.active_down and super().rose) + + def released (self): + return (self.active_down and super().rose) or (not self.active_down and super().fell) + + def update (self): + super().update() + if self.pushed(): + self.last_change_ticks = ticks_ms() + self.short_counter = self.short_counter + 1 + elif self.released(): + self.last_change_ticks = ticks_ms() + if self.long_registered: + self.long_registered = False + self.long_showed = False + else: + now_ticks = ticks_ms() + duration = ticks_diff(now_ticks, self.last_change_ticks) + if not self.long_registered and self.value != self.active_down and duration > self.long_duration: + self.long_registered = True + self.short_showed = self.short_counter - 1 + self.short_counter = 0 + elif self.short_counter > 0 and self.value == self.active_down and duration > self.short_duration: + self.short_showed = self.short_counter + self.short_counter = 0 + + @property + def short_count (self): + ret = self.short_showed + self.short_showed = 0 + return ret + + @property + def long_press (self): + if self.long_registered and not self.long_showed: + self.long_showed = True + return True + return False diff --git a/examples/debouncer_multi.py b/examples/debouncer_multi.py new file mode 100644 index 0000000..3835718 --- /dev/null +++ b/examples/debouncer_multi.py @@ -0,0 +1,20 @@ +import board +import digitalio +from adafruit_debouncer import Button + +""" +This example shows how to count short clicks or detect a long press +""" + +pin = digitalio.DigitalInOut(board.D12) +pin.direction = digitalio.Direction.INPUT +pin.pull = digitalio.Pull.UP +switch = Button(pin) + +while True: + switch.update() + if switch.long_press: + print('long') + count = switch.short_count + if count != 0: + print('count=', count) From dda5f5668b501d5cdf02e96b49bc587e9344c9ea Mon Sep 17 00:00:00 2001 From: david gauchard Date: Tue, 25 Jan 2022 23:16:33 +0100 Subject: [PATCH 2/5] pylint fixes --- adafruit_debouncer.py | 33 +++++++++++++++++---------------- examples/debouncer_multi.py | 4 +--- 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/adafruit_debouncer.py b/adafruit_debouncer.py index feae0f4..29d6114 100644 --- a/adafruit_debouncer.py +++ b/adafruit_debouncer.py @@ -28,8 +28,8 @@ __version__ = "0.0.0-auto.0" __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_Debouncer.git" -from adafruit_ticks import ticks_ms, ticks_diff from micropython import const +from adafruit_ticks import ticks_ms, ticks_diff _DEBOUNCED_STATE = const(0x01) _UNSTABLE_STATE = const(0x02) @@ -132,52 +132,53 @@ def current_duration(self): class Button(Debouncer): """Debounce counter""" - def __init__(self, pin, short_duration = 0.2, long_duration = 0.5, active_down = True, **kwargs): + def __init__(self, pin, short_duration=0.2, long_duration=0.5, active_down=True, **kwargs): self.short_duration = short_duration self.long_duration = long_duration self.active_down = active_down self.last_change_ticks = ticks_ms() self.short_counter = 0 - self.short_showed = 0 + self.short_to_show = 0 self.long_registered = False self.long_showed = False super(Button, self).__init__(pin, **kwargs) - def pushed (self): + def _pushed(self): return (self.active_down and super().fell) or (not self.active_down and super().rose) - def released (self): + def _released(self): return (self.active_down and super().rose) or (not self.active_down and super().fell) - def update (self): + def update(self): super().update() - if self.pushed(): + if self._pushed(): self.last_change_ticks = ticks_ms() self.short_counter = self.short_counter + 1 - elif self.released(): + elif self._released(): self.last_change_ticks = ticks_ms() if self.long_registered: self.long_registered = False self.long_showed = False else: - now_ticks = ticks_ms() - duration = ticks_diff(now_ticks, self.last_change_ticks) + duration = ticks_diff(ticks_ms(), self.last_change_ticks) if not self.long_registered and self.value != self.active_down and duration > self.long_duration: self.long_registered = True - self.short_showed = self.short_counter - 1 + self.short_to_show = self.short_counter - 1 self.short_counter = 0 elif self.short_counter > 0 and self.value == self.active_down and duration > self.short_duration: - self.short_showed = self.short_counter + self.short_to_show = self.short_counter self.short_counter = 0 @property - def short_count (self): - ret = self.short_showed - self.short_showed = 0 + def short_count(self): + """Return the number of short press""" + ret = self.short_to_show + self.short_to_show = 0 return ret @property - def long_press (self): + 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 diff --git a/examples/debouncer_multi.py b/examples/debouncer_multi.py index 3835718..38e9757 100644 --- a/examples/debouncer_multi.py +++ b/examples/debouncer_multi.py @@ -2,9 +2,7 @@ import digitalio from adafruit_debouncer import Button -""" -This example shows how to count short clicks or detect a long press -""" +# This example shows how to count short clicks or detect a long press pin = digitalio.DigitalInOut(board.D12) pin.direction = digitalio.Direction.INPUT From 0e64e8503339dfc9a1b4aac5c2029d2f21597bff Mon Sep 17 00:00:00 2001 From: david gauchard Date: Tue, 25 Jan 2022 23:24:41 +0100 Subject: [PATCH 3/5] pylint fixes #2 --- adafruit_debouncer.py | 2 +- examples/debouncer_multi.py | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/adafruit_debouncer.py b/adafruit_debouncer.py index 29d6114..e09cad9 100644 --- a/adafruit_debouncer.py +++ b/adafruit_debouncer.py @@ -141,7 +141,7 @@ def __init__(self, pin, short_duration=0.2, long_duration=0.5, active_down=True, self.short_to_show = 0 self.long_registered = False self.long_showed = False - super(Button, self).__init__(pin, **kwargs) + super().__init__(pin, **kwargs) def _pushed(self): return (self.active_down and super().fell) or (not self.active_down and super().rose) diff --git a/examples/debouncer_multi.py b/examples/debouncer_multi.py index 38e9757..f29a793 100644 --- a/examples/debouncer_multi.py +++ b/examples/debouncer_multi.py @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2022 david gauchard +# SPDX-License-Identifier: MIT + import board import digitalio from adafruit_debouncer import Button From b89a85acdf40995dfc9d730a5ac659c0a6c7beba Mon Sep 17 00:00:00 2001 From: david gauchard Date: Wed, 26 Jan 2022 22:29:09 +0100 Subject: [PATCH 4/5] ticks are now in ms --- adafruit_debouncer.py | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/adafruit_debouncer.py b/adafruit_debouncer.py index e09cad9..401154f 100644 --- a/adafruit_debouncer.py +++ b/adafruit_debouncer.py @@ -129,14 +129,17 @@ def current_duration(self): return ticks_diff(ticks_ms(), self._state_changed_ticks) / _TICKS_PER_SEC - class Button(Debouncer): """Debounce counter""" - def __init__(self, pin, short_duration=0.2, long_duration=0.5, active_down=True, **kwargs): - self.short_duration = short_duration - self.long_duration = long_duration + def __init__(self, pin, + short_duration_ms=200, + long_duration_ms=500, + active_down=True, + **kwargs): + self.short_duration_ms = short_duration_ms + self.long_duration_ms = long_duration_ms self.active_down = active_down - self.last_change_ticks = ticks_ms() + self.last_change_ms = ticks_ms() self.short_counter = 0 self.short_to_show = 0 self.long_registered = False @@ -144,28 +147,34 @@ def __init__(self, pin, short_duration=0.2, long_duration=0.5, active_down=True, super().__init__(pin, **kwargs) def _pushed(self): - return (self.active_down and super().fell) or (not self.active_down and super().rose) + return (self.active_down and super().fell) or \ + (not self.active_down and super().rose) def _released(self): - return (self.active_down and super().rose) or (not self.active_down and super().fell) + return (self.active_down and super().rose) or \ + (not self.active_down and super().fell) def update(self): super().update() if self._pushed(): - self.last_change_ticks = ticks_ms() + self.last_change_ms = ticks_ms() self.short_counter = self.short_counter + 1 elif self._released(): - self.last_change_ticks = ticks_ms() + 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_ticks) - if not self.long_registered and self.value != self.active_down and duration > self.long_duration: + duration = ticks_diff(ticks_ms(), self.last_change_ms) + if not self.long_registered and \ + self.value != self.active_down and \ + duration > self.long_duration_ms: self.long_registered = 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 duration > self.short_duration: + elif self.short_counter > 0 and \ + self.value == self.active_down and \ + duration > self.short_duration_ms: self.short_to_show = self.short_counter self.short_counter = 0 From 016a726658eb32391a9af54ba028f27e4e589297 Mon Sep 17 00:00:00 2001 From: david gauchard Date: Wed, 26 Jan 2022 22:35:52 +0100 Subject: [PATCH 5/5] reformat with black --- adafruit_debouncer.py | 40 +++++++++++++++++++++++-------------- examples/debouncer_multi.py | 4 ++-- 2 files changed, 27 insertions(+), 17 deletions(-) diff --git a/adafruit_debouncer.py b/adafruit_debouncer.py index 401154f..6944819 100644 --- a/adafruit_debouncer.py +++ b/adafruit_debouncer.py @@ -131,11 +131,15 @@ def current_duration(self): class Button(Debouncer): """Debounce counter""" - def __init__(self, pin, - short_duration_ms=200, - long_duration_ms=500, - active_down=True, - **kwargs): + + def __init__( + self, + pin, + short_duration_ms=200, + long_duration_ms=500, + active_down=True, + **kwargs + ): self.short_duration_ms = short_duration_ms self.long_duration_ms = long_duration_ms self.active_down = active_down @@ -147,12 +151,14 @@ def __init__(self, pin, super().__init__(pin, **kwargs) def _pushed(self): - return (self.active_down and super().fell) or \ - (not self.active_down and super().rose) + return (self.active_down and super().fell) or ( + not self.active_down and super().rose + ) def _released(self): - return (self.active_down and super().rose) or \ - (not self.active_down and super().fell) + return (self.active_down and super().rose) or ( + not self.active_down and super().fell + ) def update(self): super().update() @@ -166,15 +172,19 @@ def update(self): 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 \ - duration > self.long_duration_ms: + if ( + not self.long_registered + and self.value != self.active_down + and duration > self.long_duration_ms + ): self.long_registered = 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 \ - duration > self.short_duration_ms: + elif ( + self.short_counter > 0 + and self.value == self.active_down + and duration > self.short_duration_ms + ): self.short_to_show = self.short_counter self.short_counter = 0 diff --git a/examples/debouncer_multi.py b/examples/debouncer_multi.py index f29a793..976cd84 100644 --- a/examples/debouncer_multi.py +++ b/examples/debouncer_multi.py @@ -15,7 +15,7 @@ while True: switch.update() if switch.long_press: - print('long') + print("long") count = switch.short_count if count != 0: - print('count=', count) + print("count=", count)