Timer callback ADC memory error
Timer callback ADC memory error
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
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
Last edited by ulrich on Fri Dec 19, 2014 6:26 pm, edited 1 time in total.
Re: Timer callback ADC memory error
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:
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.
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)
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
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.
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
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
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
You can do integer arithmetic // = integer divide, / = floating point divide.
Re: Timer callback ADC memory error
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.
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
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.
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
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?
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
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.
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.