ExtInt not working as expected.

Showroom for MicroPython related hardware projects.
Target audience: Users wanting to show off their project!
Post Reply
BOB63
Posts: 58
Joined: Sat Jul 25, 2015 8:24 pm
Location: Monza , Italy

ExtInt not working as expected.

Post by BOB63 » Tue Aug 11, 2015 8:39 pm

Hi,
I'm Bob and I'm newbie of this forum and mPY.
I'm working on my first project with mPY with the intention to implemente a datalogger to records during the days , how many times flash a led and for each flash record date , time a incremantal counter.
I've already done this project using a PIC , but now I wont try to implement using the mPY.
Having not enough experience with Python I'm proceeding by steps and now I'm looking how use the ExtInt to detect every falling edge on X1 pin where will be connected the sensor the read the flash.
This is the code I'm using:

Code: Select all


import pyb
from pyb import Pin
from pyb import ExtInt

pin_sonda = Pin('X1', Pin.IN)
L = pyb.LED(2)
ExtInt.enable
contatore=0

def callback(line):
    L.on()
    pyb.delay(1000)
    L.off()
    print("interrupt")
    contatore +=1
      
ext = pyb.ExtInt(pin_sonda, pyb.ExtInt.IRQ_FALLING,pyb.Pin.PULL_NONE,callback)

while True:
      print("wait")
      print(contatore) 

I don't understand why it works partially just on the first flash and then is like the external interrupts is disable.
I say that works partially because the green led flash for 1 second but i dont see using PuTTY the counter increment or the "interrupt" .
On the first I suspect because the counter variable isn't declared in the right way , but i dopn't understad why isn't printed "Interrupt".

Is there someone able to give me any suggestion on what is wrong in the code ?

P.S. Why is i write ExtInt.enable() i got an error from python while in the documentatio is declared in this way ?

Thanks Bob.
Last edited by BOB63 on Tue Oct 03, 2017 8:50 pm, edited 1 time in total.
Thanks. Roberto

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

Re: ExtInt not working as expected.

Post by dhylands » Tue Aug 11, 2015 9:22 pm

A few tips:

1 - put a delay in your main loop. The way it is now your error is scrolling of the screen before you can see it.

2 - Anytime you're dealing with interrupts, I add the following snippet to my python code:

Code: Select all

import micropython
micropython.alloc_emergency_exception_buf(100)
That causes more information to be printed.

I decided to try using the USR button, which is X17. There is no external pullup on the line, so I also had to change the pullup on your call to ExtInt. I then got this error:

Code: Select all

wait
0
interrupt
Uncaught exception in ExtInt interrupt handler line 3
Traceback (most recent call last):
  File "extint.py", line 18, in callback
NameError: local variable referenced before assignment
This is happening due to the contrare += 1 line. You need to declare contrare as global.

Also the line ExtInt.enable returns a function object but doesn't call it. You'd need to do ExtInt.enable() to actually call the function. But it isn't needed for this example.

Here's my modified version of your example:

Code: Select all

import pyb
from pyb import Pin
from pyb import ExtInt

import micropython
micropython.alloc_emergency_exception_buf(100)

pin_sonda = Pin('X17', Pin.IN)
L = pyb.LED(2)
contatore=0

def callback(line):
    L.on()
    pyb.delay(1000)
    L.off()
    print("interrupt")
    global contatore
    contatore +=1
     
ext = ExtInt(pin_sonda, ExtInt.IRQ_FALLING, Pin.PULL_UP, callback)

while True:
      print("wait")
      print(contatore)
      pyb.delay(200)
which produces output like:

Code: Select all

Micro Python v1.4.4-65-gd3572ad on 2015-07-02; PYBv1.0 with STM32F405RG
Type "help()" for more information.
>>> import extint
wait
0
wait
0
wait
0
wait
0
wait
0
interrupt
wait
1
wait
1
wait
1
wait
1
wait
1
interrupt
wait
2
wait
2
wait
2
wait
2
interrupt
wait
3
wait
3
wait
3
wait
3
wait
3

BOB63
Posts: 58
Joined: Sat Jul 25, 2015 8:24 pm
Location: Monza , Italy

Re: ExtInt not working as expected.

Post by BOB63 » Tue Aug 11, 2015 10:44 pm

Dave,
thank you so much for the fast and useful reply. I've a lot to learn before complete my project... :shock:
Thanks. Roberto

BOB63
Posts: 58
Joined: Sat Jul 25, 2015 8:24 pm
Location: Monza , Italy

Re: ExtInt not working as expected.

Post by BOB63 » Wed Aug 12, 2015 10:49 am

Hi,
as expected I'm here again .... It was too easy have solved all my doubts :D .

I've implemented your suggestion and I got an error referred to the fact that i use the " micropython.alloc_emergency_exception_buf(100)".
When I start the program from PuTTY i got this message : AttributeError: 'module' object has no attribute alloc_emergency_exception_buf' .
But I was using "Micro Python v1.0.1" and after have upgraded to v1.4.5 , the problem is fixed.

Starting from your corred version of code I've included also the RTC management into the callback routine , but I'm facing some other problems related to the interrupt handling.Because i got this error :
Uncaught exception in ExtInt interrupt handler line 0
Traceback (most recent call last):
File "main.py", line 71, in callback
MemoryError: memory allocation failed, heap is locked

This is the code used: and timest=rtc.datetime() is the line that is failing.
( I've removed some header rows with my comments so may be that now the row # failing will be different from 71).

Code: Select all

import pyb
from pyb import Pin
from pyb import RTC
from pyb import ExtInt

#import micropython
#micropython.alloc_emergency_exception_buf(100)

rtc = pyb.RTC()
pin_sonda = Pin('X1', Pin.IN)
l = pyb.LED(2)
log = open('logCons.csv', 'w')  

rtc.datetime((2014, 5, 1, 4, 13, 0, 0, 0))
print(rtc.datetime())


contatore=0
current_day = 7
aa=0
mm=0
gg=0
daywk=0
ore=0
minuti=0
secondi=0
a=0 


def callback(line):
    global current_day
    global contatore
    global aa
    global mm
    global gg
    global daywk
    global ore
    global minuti
    global secondi
    global wk_day
    global timest
    
    print("read")
    pyb.delay(100)
    timest=rtc.datetime()  
    wk_day=timest[3]      #also commenting the rest of code starting this line I got memory error.  
    if (wk_day!=current_day):
           current_day=wk_day
           contatore=1
##           aa=timest[0]
##           mm=timest[1]
##           gg=timest[2]
##           daywk=timest[3]
##           ore=timest[4]
##           minuti=timest[5]
##           secondi=timest[6]
           #log.write('{},{},{},{},{},{},{},{}\n'.format(aa, mm, gg,daywk,ore,minuti,secondi,contatore))
           l.on()
           pyb.delay(30)
           l.off()
    else:
            contatore += 1 
##            aa=timest[0]
##            mm=timest[1]
##            gg=timest[2]
##            daywk=timest[3]
##            ore=timest[4]
##            minuti=timest[5]
##            secondi=timest[6]
            #log.write('{},{},{},{},{},{},{},{}\n'.format(aa, mm, gg,daywk,ore,minuti,secondi,contatore))
            l.on()
            pyb.delay(30)
            l.off()

print(contatore) 					
pyb.delay(300)
	
extint = pyb.ExtInt(pin_sonda, pyb.ExtInt.IRQ_FALLING,pyb.Pin.PULL_NONE,callback)

while True:
      
      print("wait")
      pyb.delay(300)
I've tried to comment most of the lines inside the call back routine and I've seen that is enough left the "timest=rtc.datetime() " to have the error.

Where I'm wrong ? :roll:
Thanks Bob.
Thanks. Roberto

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

Re: ExtInt not working as expected.

Post by dhylands » Wed Aug 12, 2015 3:08 pm

So the fundamental issue is that your callback is really an interrupt handler, and currently, interrupt handlers are not allowed to allocate memory.

Unfortunately, the statement '{}'.format(1) needs to allocate memory. As does anything involving floating point.

BOB63
Posts: 58
Joined: Sat Jul 25, 2015 8:24 pm
Location: Monza , Italy

Re: ExtInt not working as expected.

Post by BOB63 » Thu Aug 13, 2015 9:14 am

Hi Dave ,
yes my idea was to have a real interrupt service routine , as I do with the PIC , inside the callback function.
Considering that the frequency of LED flashs to be monitored is lower than 1 Hz , I'll try to manage inside the callback just the setting of some flags to be used into the main loop.
Let see what can i do ... :)
BTW, is there any plan to upgrade micropython so to permit memory allocation inside the callback , or is something not possible for other reasons ?
Thank for now .. also today I've my home work to do. :D
Thanks. Roberto

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

Re: ExtInt not working as expected.

Post by dhylands » Thu Aug 13, 2015 2:14 pm

Currently, the heap/garbage collector is non-reentrant. The general way that the heap works is that you allocate things and don't free them, so you eventually run out of memory and have to do a garbage collection. This winds up freeing all of the memory that isn't used.

If an interrupt were to occur while it was garbage collecting, and then try to allocate more memory, then this is where things could go awry. That allocation in the interrupt handler may also require a garbage collection.

So to prevent that, the heap is disabled while interrupts are being called, which is why you can't allocate memory during an interrupt handler.

BOB63
Posts: 58
Joined: Sat Jul 25, 2015 8:24 pm
Location: Monza , Italy

Re: ExtInt not working as expected.

Post by BOB63 » Sat Aug 22, 2015 9:17 am

Dave,
thank you for the explanation.
I've found a way to manage the callback so to set flags used in the rest of code. As soon as I've completed the project I'll post here.
Thanks again Bob.
Thanks. Roberto

Post Reply