I want to get the values of a cosine function in small steps and a regular interval.
To not calculate all values in advance and overfill the memory, I use a generator.
To get a regular value I use a timer as trigger.
Now my problem is, if I call next value in the callback function, I get the following error:
[code]
Traceback (most recent call last):
File "<stdin>", line 13, in get_cos_value
File "<stdin>", line 6, in cosine_generator
MemoryError: memory allocation failed, heap is locked
[/code]
My code:
[code]
import pyb
import math
from math import pi
def cosine_generator(n):
dx = 2*pi/(n-1)
for i in range(n):
yield math.cos(i*dx)
cos = cosine_generator(3000)
def get_cos_value(timer):
print(next(cos))
tim = pyb.Timer(3)
tim.init(freq=10)
tim.callback(get_cos_value)
[/code]
Call next() from a callback
Re: Call next() from a callback
Because interrupts run at an unknown point innthe Python VM's cycle, they disable memory allocation (otherwise the GC would have to be reentrant). Unfortunately, the generator needs to do an allocation (I'm unsure if this is related to the floating point calculation or the generator itself).
The easiest way around this is to use micropython.schedule from the interrupt handler to set a callback (a "soft" interrupt) that will be executed by the VM between instructions ASAP. These soft handlers can do everything that normal code can do.
See https://docs.micropython.org/en/latest/ ... rules.html for more info
The easiest way around this is to use micropython.schedule from the interrupt handler to set a callback (a "soft" interrupt) that will be executed by the VM between instructions ASAP. These soft handlers can do everything that normal code can do.
See https://docs.micropython.org/en/latest/ ... rules.html for more info
- pythoncoder
- Posts: 5956
- Joined: Fri Jul 18, 2014 8:01 am
- Location: UK
- Contact:
Re: Call next() from a callback
Floating point operations always allocate and are therefore not allowed in interrupt handlers.
Peter Hinch
Index to my micropython libraries.
Index to my micropython libraries.
Re: Call next() from a callback
Thanks for your quick reply.jimmo wrote: ↑Fri Aug 02, 2019 10:02 pm...
The easiest way around this is to use micropython.schedule from the interrupt handler to set a callback (a "soft" interrupt) that will be executed by the VM between instructions ASAP. These soft handlers can do everything that normal code can do.
See https://docs.micropython.org/en/latest/ ... rules.html for more info
My quick and dirty solution was to set a flag in the callback and look after it and call next() afterwards from the outside.
But that does not feel right
These soft handlers could fix several issues
I'll try it asap.