Page 1 of 1

Simple Interrupt Problem

Posted: Sun Oct 30, 2016 1:35 pm
by KMcLoud
I was working on a significantly more complex programs and having some problems that I traced back to the fact that the interrupt wasn't firing.

I've written a new, extremely simple program just to prove to myself that I can make interrupts work, and its not going so well.

it uses the user button on the expansion board to trigger interrupts to increment a counter (or at least that's the idea)

here's the contents of, there is no

import micropython
from machine import Pin


int_counter =0

def int_handler():
global int_counter

button=Pin('GP17', mode=Pin.IN, pull=Pin.PULL_UP)
button.irq(trigger=Pin.IRQ_RISING|Pin.IRQ_FALLING, handler=int_handler)

I know the pin setup is working because when I go to the repl and run button() I get a value that toggles as I press and release the button

I know the handler function works because when I manually run int_handler(), int_counter increments.

Further, I suspect the trigger is working because when I press the button for the first time, the heartbeat LED blinks very rapidly for a couple seconds. However it won't do that again unless the button.irq() method is re-called.

However, when I press the button, int_counter does not increment.

Any idea what's going on here? I'm stumped

Re: Simple Interrupt Problem

Posted: Sat Nov 05, 2016 10:23 am
by KMcLoud
FYI, in case anyone else runs into this.

One of the devs over on the Pycom forum straightened this out for me.

when a pin interrupt is triggered and it calls its callback, it passes the pin object as an argument to the callback function.

Apparently, the fact that this happens inside an interrupt prevents the normal error message from getting out even with EMERGENCY_EXCEPTION_BUF set

I didn't think the docs made this clear, so its definitely something to watch out for.

Re: Simple Interrupt Problem

Posted: Sun Nov 06, 2016 1:45 am
by dhylands
Not sure what you mean by "prevents the normal error message from getting out".

Interrupts aren't allowed to allocate memory, and that includes memory to create an exception object. There is a pre-allocated MemoryError object and by default that gets thrown for any and all exceptions inside an interrupt handler.

You can call:

Code: Select all

import micropython
and that will preallocate an emergency buffer which is used to allocate an exception and traceback information for exceptions which occur inside interrupt handlers.

This page covers much more depth about writing interrupt handlers: ... rules.html

Exceptions from interrupt handlers never make it out to the main program, since they would essentially windup interrupting some random piece of code in the main thread.

Re: Simple Interrupt Problem

Posted: Sun Nov 06, 2016 8:52 am
by pythoncoder
A couple of general points. MicroPython callbacks including interrupt handlers generally take a single argument which is the object causing the callback. Secondly it's usually best to run user code from rather than Further it's easiest to create your own module which you can run from the REPL. Only when the module is fully debugged do you need to alter to simply issue

Code: Select all

import mymodule
Having development code automatically run after a soft reset tends to be inconvenient.

Re: Simple Interrupt Problem

Posted: Sun Nov 06, 2016 2:33 pm
by KMcLoud
thanks for the tip!

Thanks for taking a look

I was running the exception buffer in the above code, I expected it to raise an exception within the main program, but now I see how that could be problematic.

all the docs page says about catching the exception is "Debugging is simplified if the following code is included in any program using interrupts."

so how would one catch an exception from within an interrupt?

I understand that the code in the handler should be simple enough for this not to be an issue, I'm generally just toggling boolean flags. However, in cases like this catching that exception would sure help with debugging.

Re: Simple Interrupt Problem

Posted: Sun Nov 06, 2016 5:13 pm
by pythoncoder
The emergency buffer ensures that an exception in an interrupt handler produces a readable error message for debugging purposes. I'm pretty sure there's no way to trap such an exception. The key with interrupt handlers is to make them a short and simple as possible and to handle any abnormal conditions in code in the handler itself - i.e. aim to ensure that it never throws an exception.

Re: Simple Interrupt Problem

Posted: Sun Nov 06, 2016 6:17 pm
by dhylands
You catch an exception in an interrupt handler the same way that you do in regular code, but using try/catch.

I normally don't bother, since I typically don't do things in interrupt handlers which would cause exceptions, except for typos and bad code :)

The C code that calls the interrupt callback essentially puts a try/catch around the call to the callback, and if an exception is fired it reports that the callback failed to catch the exception and prints out the exception object.