Page 2 of 3
Re: Debouncing with IRQ
Posted: Wed Feb 14, 2018 2:56 pm
by SpotlightKid
Look at the
test_machine function at the bottom of the Gist code. Just replace value for the
swpin parameter with the pin number you want (i.e. 23) and the second and third arg to the
DebouncedSwitch switch constructor with the callback function and its argument.
Here's a really reduced example:
Code: Select all
from debounce import DebouncedSwitch
from machine import Pin
def mycallback(arg):
print("Switch toggled", arg)
sw = DebouncedSwitch(Pin(23, Pin.IN), mycallback, "dummy")
Re: Debouncing with IRQ
Posted: Wed Feb 21, 2018 8:14 pm
by dubaleeiro
Thanks a los.
It worked like a charm !
Re: Debouncing with IRQ
Posted: Fri Feb 23, 2018 6:41 pm
by sebbalex
@SpotlightKid
Thanks for the code, very useful!
The callback is called with only RISING event trigger, is there a chance to get it working with both events
RISING and FALLING ?
thanks a lot
Re: Debouncing with IRQ
Posted: Sat Feb 24, 2018 7:21 pm
by SpotlightKid
sebbalex wrote: ↑Fri Feb 23, 2018 6:41 pm
is there a chance to get it working with both events RISING and FALLING ?
Yes, for this you'll have to pass a
machine.Pin object to
DebouncedSwitch as the first argument and change line 37
and 43 to pass a value for the
trigger parameter (note that
self._set_cb is an alias name for the
irq method of your
Pin instance here):
Code: Select all
self._set_cb(self._sw_cb if cb else None, trigger=Pin.IRQ_FALLING | Pin.IRQ_RISING)
See the documentation on possible values for the trigger parameter:
http://docs.micropython.org/en/latest/p ... ne.Pin.irq
I'll leave it as an exercise to the reader to add an additional constructor parameter for the trigger event to the
DebouncedSwitch class.
Re: Debouncing with IRQ
Posted: Sat Feb 24, 2018 10:22 pm
by sebbalex
first thanks for the update!
I tried as you mentioned but I can't figure it out why it is not working, even after those change only RISING event
is fired..
this is my class instance:
[code]
v = x #dynamic id in a loop
p = machine.Pin(v, machine.Pin.IN, machine.Pin.PULL_UP)
sw = DebouncedSwitch(p, pub_cb, [v,p.value()])
[/code]
Re: Debouncing with IRQ
Posted: Sun Feb 25, 2018 1:46 pm
by SpotlightKid
Sorry, I overlooked the "if self.sw():" statement in line 35. The code will not work for handling callbacks on the rising and falling edge as is. I'll put a version below that does but it doesn't work very well, due to timing issues. The callback for the rising edge is fired with a very noticable delay. I guess this is due to the use of
micropython.schedule.
So I recommend using another debouncing approach in your case. Unfortunately I don't have the time at the moment to offer a solution.
Code: Select all
#
# inspired by: https://forum.micropython.org/viewtopic.php?t=1938#p10931
#
import micropython
try:
from machine import Timer
timer_init = lambda t, p, cb: t.init(period=p, callback=cb)
except ImportError:
from pyb import Timer
timer_init = lambda t, p, cb: t.init(freq=1000 // p, callback=cb)
# uncomment when debugging callback problems
#micropython.alloc_emergency_exception_buf(100)
class DebouncedSwitch:
def __init__(self, sw, cb, arg=None, delay=50, tid=4):
self.sw = sw
# Create references to bound methods beforehand
# http://docs.micropython.org/en/latest/pyboard/library/micropython.html#micropython.schedule
self._sw_cb = self.sw_cb
self._tim_cb = self.tim_cb
self._set_cb = getattr(sw, 'callback', None) or sw.irq
self.delay = delay
self._last = -1
self.tim = Timer(tid)
self.callback(cb, arg)
def sw_cb(self, pin=None):
self._set_cb(None)
self._last = self.sw()
timer_init(self.tim, self.delay, self._tim_cb)
def tim_cb(self, tim):
tim.deinit()
if self.sw() == self._last:
self._last = -1
micropython.schedule(self.cb, self.arg)
self._set_cb(self._sw_cb if self.cb else None)
def callback(self, cb, arg=None):
self.tim.deinit()
self.cb = cb
self.arg = arg
self._set_cb(self._sw_cb if cb else None)
def test_pyb(ledno=1):
import pyb
sw = pyb.Switch()
led = pyb.LED(ledno)
return DebouncedSwitch(sw, lambda l: l.toggle(), led)
def test_machine(swpin=2, ledpin=16):
from machine import Pin
sw = Pin(swpin, Pin.IN)
led = Pin(ledpin, Pin.OUT)
return DebouncedSwitch(sw, lambda l: l.value(not l.value()), led)
Re: Debouncing with IRQ
Posted: Thu Mar 01, 2018 9:17 am
by sebbalex
SpotlightKid wrote: ↑Sun Feb 25, 2018 1:46 pm
Sorry, I overlooked the "if self.sw():" statement in line 35. The code will not work for handling callbacks on the rising and falling edge as is. I'll put a version below that does but it doesn't work very well, due to timing issues. The callback for the rising edge is fired with a very noticable delay. I guess this is due to the use of
micropython.schedule.
So I recommend using another debouncing approach in your case. Unfortunately I don't have the time at the moment to offer a solution.
Thank you anyway, this code is working but as expected there is a huge delay sometimes.
Maybe I should move to a different approach or use the uasyncio library that should have this behaviour built in.
Re: Debouncing with IRQ
Posted: Thu Mar 01, 2018 9:24 am
by pythoncoder
I was going to suggest
uasyncio but I haven't used the WiPy V1.0 for a long time and I don't know how well it is supported. If you do use it you'll find asynchronous, debounced drivers for switches and pushbuttons
here (aswitch.py).
Re: Debouncing with IRQ
Posted: Fri Mar 02, 2018 10:55 pm
by dubaleeiro
@SpotlightKid
I am trying to use the DebouncedSwitch to pause a loop which displays the current time in a 7-segment display, and when I execute the following code, the callback behaves as if I had pushed the button:
Code:
def cbButMenu(arg):
print(arg, 'value')
main_menu()
return
debMenu = DebouncedSwitch(butMenu, cbButMenu, "butMenu")
while True:
curTime = rtc.datetime()
display_time(curTime.hour, curTime.minute)
if cbButMenu("butMenu"):
break
Debbuging:
........
download ok
exec(open('./test4.py').read(),globals())
butMenu value
>>>
could you please point what am I doing wrong here...?
Re: Debouncing with IRQ
Posted: Sun Mar 04, 2018 2:42 pm
by SpotlightKid
You are calling the cButMenu callback function explicitly within the for loop (with the same argument as it would be called by the DebouncedSwitch callback). don't do that.