One shot timer doesn't work always (in conjunction w/ pin IRQ) #9439
-
Hi guys, I have a simple class that (tries to) handle pin input debouncing. The logic is simple: on IRQ event received, start a timer. When the timer fires, check the value of the pin, to see if it's stable. I'm using ESP8266. The issue: sometimes the timer doesn't fire, and I don't understand why. Let's take a look at the code: class Debouncer:
def __init__(self, pin, cb, irqMode = machine.Pin.IRQ_FALLING, wantedValue = 0, period = 100):
self.pin = pin
self.cb = cb
self.wantedValue = wantedValue
self.period = period
self.justCalled = False
self.timer = machine.Timer(-1)
pin.irq(self.irqHandler, irqMode)
# seems that this is the equivalent of JS bind(), which means mem allocation, hence not allowed
# in ISR; cf. https://docs.micropython.org/en/latest/reference/isr_rules.html#creation-of-python-objects
self.ccb = self.timerHandler;
# if this really means mem alloc, then I put this; because used in timerHandler, which is an interrupt
# handler as well
self._irqHandler = self.irqHandler;
def irqHandler(self, pin):
if self.justCalled:
logDebouncer("Debouncer.irqHandler 1 " + str(pin))
else:
logDebouncer("Debouncer.irqHandler 2 " + str(pin))
self.justCalled = True
# even if I disable the IRQ, after this, a few more calls happen (falling into the above if branch)
# I interpret this as these calls being queued
pin.irq(trigger=0);
self.timer.init(period=self.period, mode=machine.Timer.ONE_SHOT, callback=self.ccb);
def timerHandler(self, t):
logDebouncer("Debouncer.timerHandler " + str(self.pin) + " final value = " + str(self.pin.value()))
self.justCalled = False
if self.pin.value() == self.wantedValue:
micropython.schedule(callCallback, self)
self.pin.irq(self._irqHandler, machine.Pin.IRQ_FALLING)
def callCallback(debouncer):
debouncer.cb();
def logDebouncer(str):
if DEBUG_DEBOUNCER:
print(str) So for the code above, sometimes after My hypothesis is that maybe I'm not respecting one of the rules of the ISR. In I found this implementation of debouncing logic, which seems to do more or less what I'm doing. Except the printing. Does anybody has some hints about this issue? Thanks a lot in advance! |
Beta Was this translation helpful? Give feedback.
Replies: 5 comments 5 replies
-
Hard to say if it is a problem with the print or the code. In such a timing critical sequence I would never print, but toggle instead a Pin and look at it with a logic analyzer. That's faster and has almost other dependencies. |
Beta Was this translation helpful? Give feedback.
-
I have doubts about electrical aspects of using IRQs to handle signals from switches: see my notes here. In my opinion switch debouncing is best done by polling in |
Beta Was this translation helpful? Give feedback.
-
For me, it looks overly complicated to have callbacks/IRQs for both the button and the timer. If you don't want to or can't use asyncio with the pushbutton function: |
Beta Was this translation helpful? Give feedback.
-
Thanks a lot guys!
This was also my conclusion. I have made additional tests today, writing a much simpler program, where I'm sure I didn't make memory allocation in my handlers. And the issue was still reproducible. So my thought was using polling.
This was my idea also.
To be honest, I didn't know of its existence. I will study asap. It seems to be what I'm looking for. |
Beta Was this translation helpful? Give feedback.
-
Thanks! I have already used the docs. I used |
Beta Was this translation helpful? Give feedback.
I have doubts about electrical aspects of using IRQs to handle signals from switches: see my notes here. In my opinion switch debouncing is best done by polling in
uasyncio
and the doc I referenced offers classes that do this.