0

memory allocation failed for neopixel
Moderators: adafruit_support_bill, adafruit

Forum rules
Adafruit MicroPython is currently EXPERIMENTAL and BETA - Please visit https://learn.adafruit.com/category/micropython and http://forum.micropython.org/ in addition to our section here!
Please be positive and constructive with your questions and comments.

memory allocation failed for neopixel

by Mummel on Wed Oct 11, 2017 4:55 pm

Hi,

I am running the file:

https://github.com/Meresmata/NeoText/bl ... X_short.PY

on a Trinket M0 with CurcuitPython 2.0.0. For 4 Neopixels matrixes chained together, to have the maximum 256 leds per pin.

When I can the run function I get following error message:

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "MAINX_short.py", line 138, in run
File "libraries/drivers/neopixel/neopixel.py", line 200, in show
File "libraries/drivers/neopixel/neopixel.py", line 200, in <listcomp>
MemoryError: memory allocation failed, allocating 4096 bytes


When the function is called afterwards, all works normal. Does anyone know where this error is comming from and why. What can be done against it?

Mummel
 
Posts: 18
Joined: Sun Aug 23, 2015 9:12 am

Re: memory allocation failed for neopixel

by tannewt2 on Wed Oct 11, 2017 9:27 pm

You are using a ton of neopixels!

Its complaining about running out of memory when calling show because it has to copy all of the data to factor in brightness. Try only using brightness 1.0 and adjusting your color values instead. That should use less memory.

tannewt2
 
Posts: 427
Joined: Thu Oct 06, 2016 8:48 pm

Re: memory allocation failed for neopixel

by Mummel on Thu Oct 12, 2017 3:12 pm

Ok! It was strange, to get the error message only for the first call and then seeing it work properly.
I think, it is also due to large library that is imported. In the last try, I had 20 letters, accepted. But there are some more printable ascii symbols... How can this problem be overcome. I would try, to change the tuple of an tuple into an byte array of an byte array, or tuple of bytes? ( Can this work?)... Which should be preferred? How much space can I save per integer? How do I meassure the size of the used data type and and the used ram of that library? sys.getsizeof... does not work?
Hallo and thanks from Germany!

Mummel
 
Posts: 18
Joined: Sun Aug 23, 2015 9:12 am

Re: memory allocation failed for neopixel

by tannewt2 on Thu Oct 12, 2017 4:21 pm

I'm not sure what you mean by tuples and bytes.

I'm not exactly sure on the byte counts of objects. I added a `uheap` module a while back that can be enabled with a custom compile. I'm not sure how accurate it is.

I also added a heap trace mechanic using a J-Link that is documented here: https://github.com/adafruit/circuitpyth ... ctivity.md

I hope that helps. Hello back from Seattle!

tannewt2
 
Posts: 427
Joined: Thu Oct 06, 2016 8:48 pm

Re: memory allocation failed for neopixel

by Mummel on Fri Oct 13, 2017 1:22 pm

Hi,

I currently tried to import heap or uheap. In the support matrix the entrance for for uheap is... DEBUG... But I could not find out what that means.

Concerning my last message: The overall question was, how to lower ram usage be achieved... For example to reduce the footprint of my tupels...

is it better to unpack my tupels from ((1, 2), (3, 4)) to (1,2,3,4), or to use bytearray or array as inner or or what can I do. Are all typels of my function in the ram,, or only that in the which in that if/elif that is evaluated to true...

if X = 1
X = ((1,2), (3, 4), (4, 5))
elif X = 2
X = ((1,2), (3, 4), (4, 5))
.
.
.
Are all the tupels in the ram, or only one? How can this be changed?

Are all removed from ram, after

run(){
for pixel in pixels:
functionwithmanytupels()
neopixels.show()
}
functionwithmanytupels() returns to the scope of the for loop, after the for loop has ended. If it is not so/not shure can I change this with a call of the garbace collector?

Mummel
 
Posts: 18
Joined: Sun Aug 23, 2015 9:12 am

Re: memory allocation failed for neopixel

by danhalbert on Fri Oct 13, 2017 2:06 pm

Did you set brightness to 1.0 as Scott suggested (or just omit the argument: 1.0 is the default). That will halve the memory needed for the pixels.

All the data objects are in RAM, not flash. I'm not sure you're using all that much memory for the tuples. You could use bytearrays, which might or might not save you space. You'll need to do some experimentation.

To find out the current heap use:
Code: Select all | TOGGLE FULL SIZE
import micropython, gc
gc.collect()             # clean up any garbage
micropython.mem_info()   # prints heap info

Insert this wherever you want to see the current heap usage.

Since you reassign tuple each time through the big if statement, the old tuples become garbage and can be collected. You can insert `gc.collect()` statements at judicious points, but it's supposed to be automatic.

danhalbert
 
Posts: 226
Joined: Tue Aug 08, 2017 12:37 pm

Re: memory allocation failed for neopixel

by Mummel on Sat Oct 14, 2017 10:49 am

Thank,

very much for your answer.

I tried to call

micropython.mem_info()

Then I got the error:

AttributeError: 'module' object has no attribute 'mem_info'

Have a nice weekend.
Problem help(micropython) returns:

object <module 'micropython'> is of type module
__name__ -- micropython
const -- <function>
opt_level -- <function>
heap_lock -- <function>
heap_unlock -- <function>
kbd_intr -- <function>

This is why unforutately.

Following your reply and:
http://circuitpython.readthedocs.io/en/ ... t=mem_info

it should be included...

Mummel
 
Posts: 18
Joined: Sun Aug 23, 2015 9:12 am

Re: memory allocation failed for neopixel

by danhalbert on Sat Oct 14, 2017 11:24 am

Sorry, I forgot: we took it out of the Trinket M0, Gemma M0, and Feather M0 Basic/Adalogger versions of CircuitPython to save space. We may be able to put it back in the next release. In any case, you can try not specifying brightness and see if you get memory errors.

danhalbert
 
Posts: 226
Joined: Tue Aug 08, 2017 12:37 pm

Re: memory allocation failed for neopixel

by Mummel on Wed Oct 18, 2017 4:48 pm

Short report:

leaving out the brightness and using the garbage collect, was not enough. Because I have many tupels of the sort ((1, 2), ...(2, 3))
I had to rewrite them to array.array("B", (1, 2, ..., 2, 3)). Which makes the file runnable again... Due to the changes I some bugs... (Wrong number of LEDs, with wrong addresses).

I searched for a way to create frozen modules. But only found one for the esp. You probably have to change the virtual machine, but how?

Thank you.

Mummel
 
Posts: 18
Joined: Sun Aug 23, 2015 9:12 am

Re: memory allocation failed for neopixel

by danhalbert on Wed Oct 18, 2017 5:09 pm

`bytearray(1, 2, 2, 3, 3, 4, ...)` will also work.

You can compile the .py file to a .mpy file, but currently we don't supply `mpy-cross`, the compiler, pre-built. We don't have a version that runs on Windows (yet). You could build `mpy-cross` yourself but it takes some effort. Importing a `.mpy` file will still use up as much RAM after importing as a `.py` file will. But it saves the compilation step, which may need more RAM than is available.

It is also possible to make an "internal frozen module" which is part of the CircuitPython firmware. That does not use up RAM when imported. I'd like to write up how to do this at some point. It is similar to what is described in the ESP8266 guide you looked at. https://github.com/adafruit/circuitpyth ... igboard.mk shows how some modules are internally frozen into the Circuit Playground Express firmware. But you need to be comfortable doing makefile builds on Linux or MacOS to do this.

danhalbert
 
Posts: 226
Joined: Tue Aug 08, 2017 12:37 pm

Re: memory allocation failed for neopixel

by Mummel on Sun Oct 22, 2017 8:03 am

Hi,

with the array("B", (...)) I could read in the uppercaseletters only... no smaller case, no numbers, no smaller case... is it possible to circumvent this problem with the nvm of the microcontroller module, or would that not reduce the the ram usage? What is the sizelimitation?

@danhalbert Has there been some kind of error in your byte declaration?
I could only use bytearray("\0x1, \0x2, ..."). Is one preferable over the other (array of byte vs bytearry) and why?

By the way Enums are included in Curcuitpython, Micropython?

My next step, (when most symbols work) would be to use a timerinterrupt, to let the text scroll over the display. But the writing interupt handler section of the documentation only works for the pyboard, or am I wrong. I thought I could use Timer.MATCH? But the description of the timer class in the docu is not realy detailt. How would I use timer interrupts in curcuitpython? Also the micropython.alloc_emergency_exception_buf() is not usable, although mentioned on both sites of the docu.

Mummel
 
Posts: 18
Joined: Sun Aug 23, 2015 9:12 am

Re: memory allocation failed for neopixel

by tannewt2 on Sun Oct 22, 2017 11:46 pm

Mummel wrote:Hi,

with the array("B", (...)) I could read in the uppercaseletters only... no smaller case, no numbers, no smaller case... is it possible to circumvent this problem with the nvm of the microcontroller module, or would that not reduce the the ram usage? What is the sizelimitation?

@danhalbert Has there been some kind of error in your byte declaration?
I could only use bytearray("\0x1, \0x2, ..."). Is one preferable over the other (array of byte vs bytearry) and why?


For storing bytes I'd recommend bytearray() or even bytes() if its immutable. To instantiate it you don't need the commas. bytearray("\0x1\0x2...") This of it like a string.

Mummel wrote:By the way Enums are included in Curcuitpython, Micropython?


I don't believe so. We do have some classes that mimic it (like digitalio.Direction and Pull).

Mummel wrote:My next step, (when most symbols work) would be to use a timerinterrupt, to let the text scroll over the display. But the writing interupt handler section of the documentation only works for the pyboard, or am I wrong. I thought I could use Timer.MATCH? But the description of the timer class in the docu is not realy detailt. How would I use timer interrupts in curcuitpython? Also the micropython.alloc_emergency_exception_buf() is not usable, although mentioned on both sites of the docu.


Interrupts aren't handled in CircuitPython's hardware API yet. They are a low priority for us because they are an advanced topic. What are you using it for?

(We do have some volunteers working on removing parts of MicroPython docs that no longer apply.)

Hope that helps! Thanks!

tannewt2
 
Posts: 427
Joined: Thu Oct 06, 2016 8:48 pm

Re: memory allocation failed for neopixel

by danhalbert on Mon Oct 23, 2017 8:52 am

`bytearray(1, 2, 2, 3, 3, 4, ...)` will also work.

Apologies for the incorrect code above. I keep wanting for bytearray to be easily initializable. You can do
Code: Select all | TOGGLE FULL SIZE
bytearray('\0x03...')

as tannewt points out, or more easily
Code: Select all | TOGGLE FULL SIZE
bytearray([3,4,5,2])

danhalbert
 
Posts: 226
Joined: Tue Aug 08, 2017 12:37 pm

Re: memory allocation failed for neopixel

by Mummel on Sun Nov 05, 2017 10:27 am

Hi,
I just tried to safe some values in the nvm. I thought that this might circumvent the ram size problem. Question a) How large is the nvm of the trinket?

b) don't get the error message of the following code:

Code: Select all | TOGGLE FULL SIZE
"""
test module for multiline bytearray in curcuit python
"""

import microcontroller

def test():
    """
    @param: none
    @return: none
    """
    microcontroller.nvm = bytearray(
        [1, 2, 3] + #Zeile1
        [4, 5]      #Zeile2
    )
    for i in microcontroller.nvm:
        print(i)

if __name__ == "__main__":
    test()


That is:

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "test.py", line 14, in test
AttributeError: 'module' object has no attribute 'nvm'


while help(mircrocontroller) returns:

object <module 'microcontroller'> is of type module
__name__ -- microcontroller
cpu -- <Processor>
delay_us -- <function>
disable_interrupts -- <function>
enable_interrupts -- <function>
nvm -- None
Pin -- <class 'Pin'>
pin -- <module ''>
Processor -- <class 'Processor'>


So mircrocrontoller.nvm should be know... But what than is the problem? Do I have to safe the list for every sole index? But, even if it all were possible. The internally gerated list properly would be to long for the ram.



Have a nice start in the new week!

Mummel
 
Posts: 18
Joined: Sun Aug 23, 2015 9:12 am

Re: memory allocation failed for neopixel

by danhalbert on Sun Nov 05, 2017 10:50 am

The nvm is only 256 bytes, so it's not really useful for what you want. Could you post or attach your current code?

Are you running out of memory when you import your module or when it runs?

The `mpy-cross` compiler is now available for you to download, so you can precompile your .py into a .mpy: https://github.com/adafruit/circuitpyth ... ses/latest. Run `mpy-cross` on your .py file, copy the .mpy to your Adafruit board, and then you can import it. Remove the .py file that starts with the same name because it will take precedence over the .mpy: for instance `foo.py` will be used if both `foo.py` and `foo.mpy` exist.

danhalbert
 
Posts: 226
Joined: Tue Aug 08, 2017 12:37 pm

Please be positive and constructive with your questions and comments.