Call next() from a callback

The official pyboard running MicroPython.
This is the reference design and main target board for MicroPython.
You can buy one at the store.
Target audience: Users with a pyboard.
Post Reply
User avatar
jaggr
Posts: 2
Joined: Fri Aug 02, 2019 1:03 pm

Call next() from a callback

Post by jaggr » Fri Aug 02, 2019 1:38 pm

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]

User avatar
jimmo
Posts: 878
Joined: Tue Aug 08, 2017 1:57 am
Location: Sydney, Australia

Re: Call next() from a callback

Post by jimmo » Fri Aug 02, 2019 10:02 pm

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

User avatar
pythoncoder
Posts: 3697
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: Call next() from a callback

Post by pythoncoder » Sat Aug 03, 2019 6:29 am

jimmo wrote:
Fri Aug 02, 2019 10:02 pm
...I'm unsure if this is related to the floating point calculation or the generator itself)...
Floating point operations always allocate and are therefore not allowed in interrupt handlers.
Peter Hinch

User avatar
jaggr
Posts: 2
Joined: Fri Aug 02, 2019 1:03 pm

Re: Call next() from a callback

Post by jaggr » Mon Aug 05, 2019 5:03 am

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
Thanks for your quick reply.
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 :D
I'll try it asap.

Post Reply