MicroPython_ESP32_psRAM_LoBo icon indicating copy to clipboard operation
MicroPython_ESP32_psRAM_LoBo copied to clipboard

ISR called multiple times on falling edge

Open carterw opened this issue 7 years ago • 10 comments

I pulled fresh code from the repository yesterday, did a clean and then a build, and flashed firmware.

I have code that sets up some pins in pullup mode and initializes the Pin object to call an ISR on a falling edge. The pins are attached to pushbuttons on a PCB that ground the pins when pressed. This code works as expected with firmware from about a month ago. The ISR is invoked one time.

pObj = Pin(pin_id, Pin.IN, Pin.PULL_UP, value=None, handler=myHandler, trigger=Pin.IRQ_FALLING, debounce=200, acttime=300)

I'm seeing my ISR being called three times now, twice on a falling edge and then again on a rising edge. When I invoke pin.isrvalue() in the scheduled method that is ultimately invoked as a result of the interrupt, the pin value is shown accurately as it was at that point in time.

To summarize, holding the button down results in 2 interrupts, and releasing it results in another interrupt even though the trigger is Pin.IRQ_FALLING. With previous firmware there was only one interrupt on a button press. Similar behavior occurs when I use Pin.IRQ_RISING.

carterw avatar Sep 10 '18 23:09 carterw

Is nobody else seeing this problem? It is happening with mechanical pushbuttons, presumably with some bounce, and I am seeing it with two kinds of buttons. Increasing the 'debounce' and 'acttime' values does not help.

Testing with a sensor, which presumably has no bounce in the pin state transition, results in only one interrupt.

carterw avatar Sep 13 '18 14:09 carterw

Still wanting to know if anyone else is having trouble with this.

carterw avatar Oct 04 '18 22:10 carterw

Still seeing this problem.

carterw avatar Dec 01 '18 17:12 carterw

I've come across a situation where this appears to be happening as a result of a pin transition (low to high in this case) being generated by an external device. The ISR is triggered twice as a result of the transition, and since there aren't any mechanical components involved there probably isn't any bouncing happening.

This seems like a pretty serious defect to me. Loboris can you please take a look?

carterw avatar Dec 04 '18 18:12 carterw

I've narrowed the problem down to something in the debounce/activation code. Invoking the Pin function with debounce or acctime set to something other than zero results in multiple calls to the interrupt handler even if there was no bouncing on the pin whatsoever.

A large change to machine_pin.c was committed on June 4 that introduced code which fires off a debounce_task() if debounce or acctime are non-zero. I am suspecting that the task or associated code causes the interrupt handler to be invoked more than once.

carterw avatar Dec 05 '18 18:12 carterw

I have the same problem

ijustwant avatar May 14 '19 16:05 ijustwant

I also got a problem defining a button with a handler. The code below fire the function "sleepmode" as soon as i enter the codeline, but the pin25 is not low.

button = machine.Pin(25, machine.Pin.IN, machine.Pin.PULL_UP, trigger=machine.Pin.IRQ_LOLEVEL, handler=sleepmode(0))

Any suggestions ?

ijustwant avatar Jul 30 '19 13:07 ijustwant

I think you are passing the result of invoking the sleepmode() function to the handler variable.

Should be; handler=sleepmode)

carterw avatar Jul 30 '19 14:07 carterw

I only get error messages. Do you have an example for setting pin 25 low to call a function ?

ijustwant avatar Jul 31 '19 06:07 ijustwant

What errors are you seeing? Is your interrupt handler function being called?

One thing to be aware of is that there are a lot of restrictions on what your interrupt service routine can do. You can't allocate any memory for example. Read this article.

Your ISR will get the pin object as an argument, and basically needs to call micropython.schedule() in order to get around the limitations.

def isrScheduler(pObj):    # this is the interrupt handler
    # isrIntermediary() gets called at some point
    #  and is passed the pin object, you can do whatever you want there
    micropython.schedule(isrIntermediary, pObj)    

carterw avatar Jul 31 '19 14:07 carterw