Page 1 of 1

Timer callback ADC memory error

Posted: Thu Dec 18, 2014 10:35 pm
by ulrich
Good evening!

I'm experiencing a strange behaviour, wher I'd like to ask for your help! I want to start a timer which triggers a measurment with the ADC every second.

I run the following code on the board:
import pyb
from pyb import Pin, ADC, Timer
def getstrength(tmp):
import pyb
from pyb import Pin, ADC
blue = pyb.LED(4)
blue.on()
adc = ADC(Pin('X20'))
blue.off()


tim = Timer(1, freq = 1) #gives a trigger every 1 second
tim.callback(getstrength)

This results in:
uncaught exception in Timer(1) interrupt handler
MemoryError:

(There is nothing after the memory error)
If I run "getstrength(False)" by itself I do not obtain the error message.
If I run exactly the same except I do not include the adc = ADC(PIN....) , it works fine as well...

Anyone got a clue? Any hint is very much apprechiated!

Cheers,

Ulrich

Re: Timer callback ADC memory error

Posted: Thu Dec 18, 2014 10:57 pm
by dhylands
Hey ulrich,

Currently, you're not allowed to allocate any memory from with ISR callbacks (ans the timer callback is an ISR callback).

You can get more details about exactly where the allocation is occuring by adding the following to your code:

Code: Select all

import micropython
micropython.alloc_emergency_exception_buf(100)
Even the exception handler can't allocate memory during an ISR, so its unable to report where the error occurred.

Adding the above call pre-allocates some memory that the exception handler will use when memory allocations fail, so that you can get some traceback information.

Re: Timer callback ADC memory error

Posted: Thu Dec 18, 2014 11:01 pm
by dhylands
Calling adc = ADC(...) does, in fact, try to allocate memory.

So, the fix for this would be to do the allocation in the main part of your code. This would make adc be a global.

If you're averse to using globals, then you can also use a class. Here's an example:
https://github.com/dhylands/upy-example ... eat_irq.py

It allocates the led object in the Heartbeat constructor, and the callback just refers to the already allocated object.

Re: Timer callback ADC memory error

Posted: Fri Dec 19, 2014 6:24 pm
by ulrich
Hi,

Thanks a lot for the fast reply and this valuable hint!! - I manage to read the adc from within the callback function!

Unfortunately, this immediately triggers the next problem....

The memory allocation constraint seems to me to be quite heavy and renders timers almost useless as it now seems that performing even the most basic "math", triggerst a memory exception.

E.g. adding to the callbackfunction of your heartbeat example simply the line "self.k = 3 * 2/34" causes it to die... self.k = 3 alone seems to be possible. It seems to me that any division requires memory allocation (even if globally initialized variables are used).

Your command "micropython.alloc_emergency_exception_buf(100)" allows to allocate memory for some purpose, could this be generalized? I don't need to do too much math etc, but some basic division is needed...

Cheers,

ulrich

Re: Timer callback ADC memory error

Posted: Fri Dec 19, 2014 6:26 pm
by dhylands
You can do integer arithmetic // = integer divide, / = floating point divide.

Re: Timer callback ADC memory error

Posted: Fri Dec 19, 2014 8:06 pm
by ulrich
Thanks for the hint!

While this might get me one step further, I'll not get around using floats at some point further in the routine.

I see some projects using the pyboard to e.g. control multicopter - how do they manage this kind of stuff? I'd had thought that they use some timers to regualrily check e.g. the accelerometer and then correct to stabilize it etc...

Luckily my application is by itself very simple and precise timing is not a real issue, so I guess I'll just keep a loop running and use delays.

Re: Timer callback ADC memory error

Posted: Fri Dec 19, 2014 11:56 pm
by dhylands
Normally you would use the ISR to trigger an event, which the main process would then pick up.

For example, you can simulate multi-threading by using generators, and the ISR might change a flag which causes one of your threads to run.

So the ISR wouldn't do the work, it would just determine when the work needs to be done.

Re: Timer callback ADC memory error

Posted: Sat Dec 20, 2014 9:45 am
by ulrich
Thanks again!

This sounds quite interesting. I knew that my programming skills are still quite limited - I'll have to have a look into this. Do you happen to know of a simple example for this/website explaining this concept further?

Re: Timer callback ADC memory error

Posted: Sat Dec 20, 2014 4:58 pm
by dhylands
A very basic example was given here:
http://forum.micropython.org/viewtopic. ... &t=15#p208

There is also a method based on asyncio, which there is some support for in micropython, but I haven't played with it myself. There has been several discussions about it on this forum.