Is there a code level reason why my interrupt is not getting called?

The official pyboard running MicroPython.
This is the reference design and main target board for MicroPython.
You can buy one at the store.
Target audience: Users with a pyboard.
Post Reply
Philosophix
Posts: 24
Joined: Wed Jan 02, 2019 11:45 am

Is there a code level reason why my interrupt is not getting called?

Post by Philosophix » Thu Jan 03, 2019 4:52 pm

Code: Select all

import os
import pyb
import lcd160cr
from pyb import Pin, ExtInt

lcd = lcd160cr.LCD160CR('Y')
lcd.set_orient(lcd160cr.LANDSCAPE_UPSIDEDOWN)
lcd.set_font(2, scale=2)
lcd.set_text_color(lcd.rgb(0, 0, 0), lcd.rgb(255, 255, 255))

def clear_lcd():
    lcd.set_pen(1, lcd.rgb(255, 255, 255))
    lcd.erase()

axle_pulse_counter = 0

def axle_pulse_detected(line):
    axle_pulse_counter += 1
    clear_lcd()
    lcd.set_pos(2,10)

    if axle_pulse_counter % 2 == 1:
        lcd.write('Off')
    else:
        lcd.write('On')

ext = ExtInt(Pin('X19'), ExtInt.IRQ_FALLING, Pin.PULL_NONE, axle_pulse_detected)
clear_lcd()

jickster
Posts: 629
Joined: Thu Sep 07, 2017 8:57 pm

Re: Is there a code level reason why my interrupt is not getting called?

Post by jickster » Thu Jan 03, 2019 5:35 pm

It wouldn’t hurt to call

ext.enable()


Sent from my iPhone using Tapatalk Pro

jickster
Posts: 629
Joined: Thu Sep 07, 2017 8:57 pm

Is there a code level reason why my interrupt is not getting called?

Post by jickster » Thu Jan 03, 2019 5:40 pm

I think your script just exits cause there’s nothing to keep it from exiting.

Just to test, put an infinite

while True: pass

loop at the very bottom.

Sent from my iPhone using Tapatalk Pro

Philosophix
Posts: 24
Joined: Wed Jan 02, 2019 11:45 am

Re: Is there a code level reason why my interrupt is not getting called?

Post by Philosophix » Thu Jan 03, 2019 6:00 pm

Tested both of your suggestions, but no luck. I think (though am not sure) that the infinite while loop at the end is not needed as the interrupt callback is already set and should fire regardless.

User avatar
Roberthh
Posts: 3667
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: Is there a code level reason why my interrupt is not getting called?

Post by Roberthh » Thu Jan 03, 2019 8:53 pm

It might be required to add:
global axle_pulse_counter
in the function axle_pulse_detected(line). I used that in a code, which by chance also uses X19, and that one works.

Philosophix
Posts: 24
Joined: Wed Jan 02, 2019 11:45 am

Re: Is there a code level reason why my interrupt is not getting called?

Post by Philosophix » Fri Jan 04, 2019 6:55 am

Adding

Code: Select all

global axle_pulse_counter
fixed the problem as all variables are assumed to be local in a python function. You can access a global variable without the explicit global declaration, but you can't modify it without it. You live, you learn. Thanx a million Roberthh!!
Last edited by Philosophix on Fri Jan 04, 2019 7:35 am, edited 2 times in total.

Philosophix
Posts: 24
Joined: Wed Jan 02, 2019 11:45 am

Re: Is there a code level reason why my interrupt is not getting called?

Post by Philosophix » Fri Jan 04, 2019 7:14 am

For future reference:

Code: Select all

ext.enable()
and

Code: Select all

while True: pass 
were not needed to make the interrupt work.

Also the interrupt callback function axle_pulse_detected(line) will only be:

Code: Select all

def axle_pulse_detected(line):
    global axle_pulse_counter
    axle_pulse_counter += 1
The lcd printouts were just for debugging the external interrupt.

User avatar
Roberthh
Posts: 3667
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: Is there a code level reason why my interrupt is not getting called?

Post by Roberthh » Fri Jan 04, 2019 7:32 am

The reason for needing to declare the global is scoping. The ISR, when called, has no context and no visibility of symbols outside it's own code. But since the source code is a usual python script and the ISR loosk like a normal python function, you would expect symbols at global level to be accessible in that function.

User avatar
dhylands
Posts: 3821
Joined: Mon Jan 06, 2014 6:08 pm
Location: Peachland, BC, Canada
Contact:

Re: Is there a code level reason why my interrupt is not getting called?

Post by dhylands » Fri Jan 04, 2019 8:45 pm

I would have thought that global would be required in general and has nothing to do with ISRs.

Code: Select all

MicroPython v1.9.4-665-g7795b2e5c-dirty on 2018-10-19; linux version
Use Ctrl-D to exit, Ctrl-E for paste mode
>>> num = 0
>>> def incr():
...     num += 1
... 
>>> for i in range(4):
...     print(num)
...     incr()
... 
0
Traceback (most recent call last):
  File "<stdin>", line 3, in <module>
  File "<stdin>", line 2, in incr
NameError: local variable referenced before assignment
>>> 
Errors like this in an ISR tend to get converted into MemoryErrors unless you declare an emergency exception buffer, as described here: http://docs.micropython.org/en/latest/r ... ion-buffer

User avatar
Roberthh
Posts: 3667
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: Is there a code level reason why my interrupt is not getting called?

Post by Roberthh » Fri Jan 04, 2019 8:53 pm

Yes and no. The example below looks different. Besides that, declaring globals is anyhow helpful for clarity.

Code: Select all

>>> num=1
>>> def f():
...     print(num)
... 
>>> f()
1
>>> b=bytearray(1)
>>> def y():
...     b[0] = b[0] + 1
... 
>>> y()
>>> b
bytearray(b'\x01')

Post Reply