ukavaktan
Posts: 5
Joined: Wed Sep 15, 2021 10:01 am

Interrupt handling problem in Pico

Wed Sep 15, 2021 10:18 am

Hello Everyone,

I had a problem with interrupts in Pico. I was calling an interrupt via a pin (I used clips) and the first thing that interupt is doing is stopping interrupts, But still I have more than one interrupt call which i cant explain. I could not find an answer in the forums or the internet. The code is something like this:

Code: Select all

import machine
import utime

led = machine.Pin(25, machine.Pin.OUT)
button = machine.Pin(15, machine.Pin.IN, machine.Pin.PULL_UP)

def my_interrupt(pin):
    machine.Pin(15).irq(handler=None)
    print("Interrupt Detected!")
    my_timer()

def my_timer():
    print("Function Begin!")
    print("Function END!")
    machine.Pin(15).irq(trigger=machine.Pin.IRQ_FALLING, handler=my_interrupt)

while True:
    led.toggle()
    for x in range(5):
        for y in range(10000):
            i = 1
        a = 0
        a=a+1
    print(button.value())
I would be happy if someone can advesie me what i am doing wrong.

hippy
Posts: 10731
Joined: Fri Sep 09, 2011 10:34 pm
Location: UK

Re: Interrupt handling problem in Pico

Wed Sep 15, 2021 11:26 am

ukavaktan wrote:
Wed Sep 15, 2021 10:18 am
The code is something like this:
It would be best to post your exact code. What you have never initialises any interrupt handler so it's not clear how you are observing any.

scotty101
Posts: 4290
Joined: Fri Jun 08, 2012 6:03 pm

Re: Interrupt handling problem in Pico

Wed Sep 15, 2021 12:47 pm

You have some unreachable code

This line

Code: Select all

machine.Pin(15).irq(trigger=machine.Pin.IRQ_FALLING, handler=my_interrupt)
is inside the my_timer function which is only called when the my_interrupt function is called. my_interrupt is only called when the interrupt that you configure in my_timer is called.

Move the above line to be just before your while loop.
Electronic and Computer Engineer
Pi Interests: Home Automation, IOT, Python and Tkinter

hippy
Posts: 10731
Joined: Fri Sep 09, 2011 10:34 pm
Location: UK

Re: Interrupt handling problem in Pico

Wed Sep 15, 2021 5:04 pm

scotty101 wrote:
Wed Sep 15, 2021 12:47 pm
Move the above line to be just before your while loop.
Possibly duplicate it before the while loop (without indentation).

Otherwise only the first interrupt will be seen. It is disabled in 'my_interrupt' so presumably needs to be re-enabled in 'my_timer'.

I am not confident about -

Code: Select all

button = machine.Pin(15, machine.Pin.IN, machine.Pin.PULL_UP)
And then -

Code: Select all

machine.Pin(15).irq(handler=None)
machine.Pin(15).irq(trigger=machine.Pin.IRQ_FALLING, handler=my_interrupt)
It might work - I haven't tested it - but the recommended practice would be to use -

Code: Select all

def my_interrupt(pin):
    pin.irq(handler=None)                                           # <--
    print("Interrupt Detected!")
    my_timer(pin)                                                   # <--

def my_timer(pin):                                                  # <--
    print("Function Begin!")
    print("Function END!")
    pin.irq(trigger=machine.Pin.IRQ_FALLING, handler=my_interrupt)  # <---

ukavaktan
Posts: 5
Joined: Wed Sep 15, 2021 10:01 am

Re: Interrupt handling problem in Pico

Thu Sep 16, 2021 3:26 pm

You are right hippy, I think i erased an important line while erasing experimental comments. The code should be like this with interrupt handler declared.
The interrupt is declared after functions but before the while loop, so I guess it won't cause any problem.
What i don't understand is pico is acting like it has a buffer of pressed buttons like a keyboard.

Code: Select all

import machine
import utime

led = machine.Pin(25, machine.Pin.OUT)
button = machine.Pin(15, machine.Pin.IN, machine.Pin.PULL_DOWN)

def my_interrupt(pin):
    machine.Pin(15).irq(handler=None)
    print("Interrupt Detected!")
    my_timer()

def my_timer():
    print("Function Begin!")
    for x in range(10):
        for y in range(4000):
            led.toggle()
    #led.value(0)

    machine.Pin(15).irq(handler=my_interrupt)
    print("Function END!")

machine.Pin(15).irq(trigger=machine.Pin.IRQ_FALLING, handler=my_interrupt)

while True:
    led.toggle()
    for x in range(5):
        for y in range(10000):
            i = 1
        a = 0
        a=a+1
    print(button.value())
I will experiment more at the evening and submit my findings.

ukavaktan
Posts: 5
Joined: Wed Sep 15, 2021 10:01 am

Re: Interrupt handling problem in Pico

Thu Sep 16, 2021 6:11 pm

Here is the exact code I am running on pico:
When interrupt is called, pico goes to interrupt and the function. It takes some while to complete function and enable the interrupt again.
The interrupt called, again and again, way after I touch the two clips which doesn't make sense. I am pretty confused :roll:

Code: Select all

import machine
import utime

led = machine.Pin(25, machine.Pin.OUT)
button = machine.Pin(15, machine.Pin.IN, machine.Pin.PULL_DOWN)

def my_interrupt(pin):
    machine.Pin(15).irq(handler=None)
    print("Interrupt Detected!")
    my_timer()

def my_timer():
    print("Function Begin!")
    for x in range(20):
        for y in range(10000):
            a=1
        led.toggle()
    #led.value(0)

    machine.Pin(15).irq(handler=my_interrupt)
    print("Function END!")

machine.Pin(15).irq(trigger=machine.Pin.IRQ_FALLING, handler=my_interrupt)

while True:
    led.toggle()
    for x in range(5):
        for y in range(10000):
            i = 1
        a = 0
        a=a+1
    print(button.value())
Here is the output from Thonny.

Code: Select all

0
0
0
0
Interrupt Detected!
Function Begin!
Function END!
Interrupt Detected!
Function Begin!
Function END!
Interrupt Detected!
Function Begin!
Function END!
Interrupt Detected!
Function Begin!
Function END!
Interrupt Detected!
Function Begin!
Function END!
Interrupt Detected!
Function Begin!
Function END!
Interrupt Detected!
Function Begin!

scotty101
Posts: 4290
Joined: Fri Jun 08, 2012 6:03 pm

Re: Interrupt handling problem in Pico

Fri Sep 17, 2021 8:13 am

You need to "debounce" the button input.

When you press a button the electrical contacts don't close neatly, they will open/close/open/close before they finally settle to the close state. What I'd suspect is that your code is picking up each of these wobbles.

Many debounce code examples will check to see if the switch has changed state within a certain period of time to ignore the very fast open/close events that happen as a button is pressed.
Electronic and Computer Engineer
Pi Interests: Home Automation, IOT, Python and Tkinter

hippy
Posts: 10731
Joined: Fri Sep 09, 2011 10:34 pm
Location: UK

Re: Interrupt handling problem in Pico

Fri Sep 17, 2021 10:36 am

scotty101 wrote:
Fri Sep 17, 2021 8:13 am
You need to "debounce" the button input.
'my_timer' includes a delay loop so that should be doing the debouncing.

This may be an issue related to re-specifying 'machine.Pin(15, ...)' as noted earlier.

Or it could be an issue that the edge interrupt flag is sticky so it gets set during debouncing, and acted upon as soon as the interrupt is re-enabled.

MicroPython doesn't call the interrupt handler immediately an interrupt condition occurs. It schedules the handler to be run some time in the future. Where and when hardware and internal interrupt flags are cleared is 'anyone's guess'.

It seems entirely feasible to me that the interrupt could be seen, cleared, and handler scheduled, another interrupt seen with the handler scheduled again, before the handler executes its first statement.

Attempting to disable interrupts within the interrupt handler and re-enable them later may be a flawed approach which is doomed to failure.

ukavaktan
Posts: 5
Joined: Wed Sep 15, 2021 10:01 am

Re: Interrupt handling problem in Pico

Tue Sep 21, 2021 6:46 am

MicroPython doesn't call the interrupt handler immediately an interrupt condition occurs. It schedules the handler to be run some time in the future. Where and when hardware and internal interrupt flags are cleared is 'anyone's guess'.
MicroPython doesn't call the interrupt handler immediately an interrupt condition occurs. It schedules the handler to be run some time in the future. Where and when hardware and internal interrupt flags are cleared is 'anyone's guess'.

It seems entirely feasible to me that the interrupt could be seen, cleared, and handler scheduled, another interrupt seen with the handler scheduled again, before the handler executes its first statement.

Attempting to disable interrupts within the interrupt handler and re-enable them later may be a flawed approach which is doomed to failure.
That is a pretty good point, thanks a lot. I will try to write the code on C and compare them.

ukavaktan
Posts: 5
Joined: Wed Sep 15, 2021 10:01 am

Re: Interrupt handling problem in Pico

Tue Sep 21, 2021 6:50 am

scotty101 wrote:
Fri Sep 17, 2021 8:13 am
You need to "debounce" the button input.
I thought I can get away without debouncing because the program logic was okay in that direction. Of course, in the end, it is not working and it is obvious that it is a debouncing problem. I was wondering how debouncing be a problem in the program.

WillyO65
Posts: 13
Joined: Thu Sep 23, 2021 6:59 pm
Location: Netherlands

Re: Interrupt handling problem in Pico

Tue Sep 28, 2021 8:43 pm

ukavaktan wrote:
Tue Sep 21, 2021 6:50 am
scotty101 wrote:
Fri Sep 17, 2021 8:13 am
You need to "debounce" the button input.
I thought I can get away without debouncing because the program logic was okay in that direction. Of course, in the end, it is not working and it is obvious that it is a debouncing problem. I was wondering how debouncing be a problem in the program.
In my old days, the button press would set a flag initially.
Then, after 10 ~ 20ms, the software checked the button state once more if the flag was set.
If the button state was the same as the previous state, the software considered the press as valid. Otherwise the flag was cleared to go for another round of button presses.
I used a spare timer to generate the interrupts for checking the state of the button.

HTH,
-W.
Debug using 0xDEADBEEF 8-)
Electronics hobbyist, tinkerer, sailor

Return to “General”