Page 1 of 1

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

Posted: Thu Jan 03, 2019 4:52 pm
by Philosophix

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()

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

Posted: Thu Jan 03, 2019 5:35 pm
by jickster
It wouldn’t hurt to call

ext.enable()


Sent from my iPhone using Tapatalk Pro

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

Posted: Thu Jan 03, 2019 5:40 pm
by jickster
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

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

Posted: Thu Jan 03, 2019 6:00 pm
by Philosophix
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.

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

Posted: Thu Jan 03, 2019 8:53 pm
by Roberthh
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.

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

Posted: Fri Jan 04, 2019 6:55 am
by Philosophix
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!!

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

Posted: Fri Jan 04, 2019 7:14 am
by Philosophix
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.

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

Posted: Fri Jan 04, 2019 7:32 am
by Roberthh
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.

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

Posted: Fri Jan 04, 2019 8:45 pm
by dhylands
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

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

Posted: Fri Jan 04, 2019 8:53 pm
by Roberthh
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')