Skip to content

Commit 0c86db0

Browse files
committed
Switch, Pushbutton and Delay_ms: can change callbacks at runtime.
1 parent f1962d4 commit 0c86db0

File tree

5 files changed

+76
-27
lines changed

5 files changed

+76
-27
lines changed

v3/docs/DRIVERS.md

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ goes outside defined bounds.
3232

3333
# 2. Installation and usage
3434

35-
The drivers are in the primitives package. To install copy the `primitives`
35+
The drivers require a daily build of firmware or a release build >=1.15. The
36+
drivers are in the primitives package. To install copy the `primitives`
3637
directory and its contents to the target hardware.
3738

3839
Drivers are imported with:
@@ -158,20 +159,21 @@ Constructor arguments:
158159

159160
Methods:
160161

161-
1. `press_func` Args: `func` (mandatory) a `callable` to run on button push.
162-
`args` a tuple of arguments for the `callable` (default `()`).
163-
2. `release_func` Args: `func` (mandatory) a `callable` to run on button
164-
release. `args` a tuple of arguments for the `callable` (default `()`).
165-
3. `long_func` Args: `func` (mandatory) a `callable` to run on long button
166-
push. `args` a tuple of arguments for the `callable` (default `()`).
167-
4. `double_func` Args: `func` (mandatory) a `callable` to run on double
168-
push. `args` a tuple of arguments for the `callable` (default `()`).
162+
1. `press_func` Args: `func=False` a `callable` to run on button push,
163+
`args=()` a tuple of arguments for the `callable`.
164+
2. `release_func` Args: `func=False` a `callable` to run on button release,
165+
`args=()` a tuple of arguments for the `callable`.
166+
3. `long_func` Args: `func=False` a `callable` to run on long button push,
167+
`args=()` a tuple of arguments for the `callable`.
168+
4. `double_func` Args: `func=False` a `callable` to run on double push,
169+
`args=()` a tuple of arguments for the `callable`.
169170
5. `__call__` Call syntax e.g. `mybutton()` Returns the logical debounced
170171
state of the button (`True` corresponds to pressed).
171172
6. `rawstate()` Returns the logical instantaneous state of the button. There
172173
is probably no reason to use this.
173174

174-
Methods 1 - 4 should be called before starting the scheduler.
175+
Methods 1 - 4 may be called at any time. If `False` is passed for a callable,
176+
any existing callback will be disabled.
175177

176178
Class attributes:
177179
1. `debounce_ms` Debounce time in ms. Default 50.
@@ -188,12 +190,12 @@ def toggle(led):
188190
led.toggle()
189191

190192
async def my_app():
193+
pin = Pin('X1', Pin.IN, Pin.PULL_UP) # Pushbutton to gnd
194+
red = LED(1)
195+
pb = Pushbutton(pin)
196+
pb.press_func(toggle, (red,)) # Note how function and args are passed
191197
await asyncio.sleep(60) # Dummy
192198

193-
pin = Pin('X1', Pin.IN, Pin.PULL_UP) # Pushbutton to gnd
194-
red = LED(1)
195-
pb = Pushbutton(pin)
196-
pb.press_func(toggle, (red,)) # Note how function and args are passed
197199
asyncio.run(my_app()) # Run main application code
198200
```
199201

v3/docs/TUTORIAL.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1125,6 +1125,8 @@ Methods:
11251125
the `Task` instance. This allows the `Task` to be cancelled or awaited.
11261126
6. `wait` One or more tasks may wait on a `Delay_ms` instance. Execution will
11271127
proceed when the instance has timed out.
1128+
7. `callback` args `func=None`, `args=()`. Allows the callable and its args to
1129+
be assigned, reassigned or disabled at run time.
11281130

11291131
In this example a `Delay_ms` instance is created with the default duration of
11301132
1s. It is repeatedly triggered for 5 secs, preventing the callback from

v3/primitives/delay_ms.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,7 @@ def __call__(self): # Current running status
6565

6666
def rvalue(self):
6767
return self._retn
68+
69+
def callback(self, func=None, args=()):
70+
self._func = func
71+
self._args = args

v3/primitives/pushbutton.py

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# pushbutton.py
22

3-
# Copyright (c) 2018-2020 Peter Hinch
3+
# Copyright (c) 2018-2021 Peter Hinch
44
# Released under the MIT License (MIT) - see LICENSE file
55

66
import uasyncio as asyncio
@@ -23,34 +23,37 @@ def __init__(self, pin, suppress=False, sense=None):
2323
self._tf = False
2424
self._ff = False
2525
self._df = False
26-
self._lf = False
2726
self._ld = False # Delay_ms instance for long press
2827
self._dd = False # Ditto for doubleclick
2928
self.sense = pin.value() if sense is None else sense # Convert from electrical to logical value
3029
self.state = self.rawstate() # Initial state
3130
asyncio.create_task(self.buttoncheck()) # Thread runs forever
3231

33-
def press_func(self, func, args=()):
32+
def press_func(self, func=False, args=()):
3433
self._tf = func
3534
self._ta = args
3635

37-
def release_func(self, func, args=()):
36+
def release_func(self, func=False, args=()):
3837
self._ff = func
3938
self._fa = args
4039

4140
def double_func(self, func=False, args=()):
4241
self._df = func
4342
self._da = args
44-
if self._dd:
45-
self._dd.stop()
46-
self._dd = Delay_ms(self._ddto) if func else False
43+
if func: # If double timer already in place, leave it
44+
if not self._dd:
45+
self._dd = Delay_ms(self._ddto)
46+
else:
47+
self._dd = False # Clearing down double func
4748

4849
def long_func(self, func=False, args=()):
49-
self._lf = func
50-
self._la = args
51-
if self._ld:
52-
self._ld.stop()
53-
self._ld = Delay_ms(self._lf, self._la) if func else False
50+
if func:
51+
if self._ld:
52+
self._ld.callback(func, args)
53+
else:
54+
self._ld = Delay_ms(func, args)
55+
else:
56+
self._ld = False
5457

5558
# Current non-debounced logical button state: True == pressed
5659
def rawstate(self):
@@ -75,7 +78,7 @@ async def buttoncheck(self):
7578
if state: # Button pressed: launch pressed func
7679
if self._tf:
7780
launch(self._tf, self._ta)
78-
if self._lf: # There's a long func: start long press delay
81+
if self._ld: # There's a long func: start long press delay
7982
self._ld.trigger(Pushbutton.long_press_ms)
8083
if self._df:
8184
if self._dd(): # Second click: timer running

v3/primitives/tests/switches.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
test_swcb Switch with callback
2727
test_btn Pushutton launching coros
2828
test_btncb Pushbutton launching callbacks
29+
btn_dynamic Change coros launched at runtime.
2930
'''
3031
print(tests)
3132

@@ -141,3 +142,40 @@ def test_btncb():
141142
pb.double_func(toggle, (yellow,))
142143
pb.long_func(toggle, (blue,))
143144
run()
145+
146+
# Test for the Pushbutton class where callback coros change dynamically
147+
def setup(pb, press, release, dbl, lng, t=1000):
148+
s = '''
149+
Functions are changed:
150+
LED's pulse for 2 seconds
151+
press pulses blue
152+
release pulses red
153+
double click pulses green
154+
long pulses yellow
155+
'''
156+
pb.press_func(pulse, (press, t))
157+
pb.release_func(pulse, (release, t))
158+
pb.double_func(pulse, (dbl, t))
159+
if lng is not None:
160+
pb.long_func(pulse, (lng, t))
161+
print(s)
162+
163+
def btn_dynamic():
164+
s = '''
165+
press pulses red
166+
release pulses green
167+
double click pulses yellow
168+
long press changes button functions.
169+
'''
170+
print('Test of pushbutton scheduling coroutines.')
171+
print(helptext)
172+
print(s)
173+
pin = Pin('X1', Pin.IN, Pin.PULL_UP)
174+
red = LED(1)
175+
green = LED(2)
176+
yellow = LED(3)
177+
blue = LED(4)
178+
pb = Pushbutton(pin)
179+
setup(pb, red, green, yellow, None)
180+
pb.long_func(setup, (pb, blue, red, green, yellow, 2000))
181+
run()

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy