Help Requested with LED Panel & Memory Errors

Please tell us which board you are using.
For CircuitPython issues, ask in the Adafruit CircuitPython forum.

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
User avatar
netdzynr
 
Posts: 7
Joined: Wed Apr 17, 2019 1:52 pm

Help Requested with LED Panel & Memory Errors

Post by netdzynr »

LED programming novice here, looking for help with recently purchased Metro M0 Express and an LED panel.

This is the panel: https://www.amazon.com/BTF-LIGHTING-0-2 ... 01DC0IPVU/

Using CircuitPython 3.x files and mu-editor on macOS.

Problem: constant memory errors

I have a bit of programming experience but am completely new to Python and programming LEDs in general. I'm trying to display text characters on an 256 x 8 LED panel. For lack of finding an existing library or code, I'm manually creating the character shapes, which is working to some extent, but I continue to run into memory errors. I can't tell if these are caused by my poor coding, or the limits of the Express board. And I've suddenly started getting recurring errors with the statement "pixels.show()". Every time I save code to the board, even if the code appears to run, I get some variation of the following errors in the serial console, always with the neopixel library:

Code: Select all

Traceback (most recent call last):
  File "code.py", line 97, in <module>
  File "neopixel.py", line 232, in show
  File "neopixel.py", line 232, in <listcomp>
MemoryError: memory allocation failed, allocating 4096 bytes
Also, I have two of the LED boards, and when I try to use a pixel number greater than 256, the code refuses to run, always with the result

Code: Select all

MemoryError: memory allocation failed, allocating 4096 bytes
My questions is, is the Express board just not suited to working with more than 256 LEDs or am I missing something basic in my code? My basic code is below.

Thanks in advance for for any advice/suggestions/corrections.

- Scott

Code: Select all

import board
import time
import neopixel
import random
import math

pixel_pin = board.A1
num_pixels = 256
how_bright = 0.1

pixels = neopixel.NeoPixel(pixel_pin, num_pixels, brightness=how_bright, auto_write=False)


red = (255, 0, 0)
yellow = (255, 150, 0)
green = (0, 255, 0)
cyan = (0, 255, 255)
blue = (0, 0, 255)
purple = (180, 0, 255)
orange = (240, 80, 0)
white = (255,255,255)
black = (0, 0, 0)


charA = (2,3,4,5,6,7,11,14,16,20,27,30,34,35,36,37,38,39)
charB = (0,1,2,3,4,5,6,7,8,12,15,16,19,23,24,28,31,33,34,36,37,38)
charC = (1,2,3,4,5,6,8,15,16,23,24,31,33,38)
charD = (0,1,2,3,4,5,6,7,8,15,16,23,24,31,33,34,35,36,37,38)
charE = (0,1,2,3,4,5,6,7,8,12,15,16,19,23,24,31,32,39)
charF = (0,1,2,3,4,5,6,7,12,15,16,19,31,32)
charG = (1,2,3,4,5,6,8,15,16,20,23,24,27,31,33,36,37,38)
charH = (0,1,2,3,4,5,6,7,12,19,28,32,33,34,35,36,37,38,39)
charI = (0,7,8,9,10,11,12,13,14,15,16,23)
charJ = (6,8,23,24,32,33,34,35,36,37,38)
charK = (0,1,2,3,4,5,6,7,11,12,18,21,25,30,32,39)
charL = (0,1,2,3,4,5,6,7,8,23,24,39)
charM = (0,1,2,3,4,5,6,7,14,18,30,32,33,34,35,36,37,38,39)
charN = (0,1,2,3,4,5,6,7,13,14,19,20,25,26,32,33,34,35,36,37,38,39)
charO = (1,2,3,4,5,6,8,15,16,23,24,31,33,34,35,36,37,38)
charP = (0,1,2,3,4,5,6,7,11,15,16,20,27,31,33,34,35)
charQ = (1,2,3,4,5,6,8,15,16,21,23,25,31,33,34,35,36,37,39)
charR = (0,1,2,3,4,5,6,7,11,15,16,20,26,27,31,33,34,35,38,39)
charS = (1,2,6,8,12,15,16,19,23,24,28,31,33,36,37,38)
charT = (0,15,16,17,18,19,20,21,22,23,31,32)
charU = (0,1,2,3,4,5,6,8,23,24,32,33,34,35,36,37,38)
charV = (0,1,2,3,4,5,9,23,25,32,33,34,35,36,37)
charW = (0,1,2,3,4,5,6,7,9,21,25,32,33,34,35,36,37,38,39)
charX = (0,1,6,7,10,13,19,20,26,29,32,33,38,39)
charY = (0,1,2,12,20,21,22,23,28,32,33,34)
charZ = (0,5,6,7,8,11,15,16,19,23,24,29,31,32,33,39)
char0 = (1,2,3,4,5,6,8,13,14,15,16,19,20,23,24,25,26,31,33,34,35,36,37,38)
char1 = (1,7,8,15,16,17,18,19,20,21,22,23,24,39)
char2 = (1,6,7,8,10,15,16,20,23,24,28,31,33,34,39)
char3 = (1,6,8,15,16,19,23,24,28,31,33,34,36,37,38)
char4 = (3,4,11,13,17,20,24,25,26,27,28,29,30,31,36)
char5 = (0,1,2,3,6,8,12,15,16,19,23,24,28,31,32,36,37,38)
char6 = (1,2,3,4,5,6,8,12,15,16,19,23,24,28,31,33,36,37,38)
char7 = (0,6,7,10,15,16,20,28,31,32,33,34)
char8 = (1,2,4,5,6,8,12,15,16,19,23,24,28,31,33,34,36,37,38)
char9 = (1,2,3,6,8,11,15,16,20,23,24,27,31,33,34,35,36,37,38)
charSpace = (0,1,2,3,4,5,6,7)

def do_reset():
    pixels.fill(black)
    pixels.show()

def do_sleep():
    time.sleep(0.001)

def get_rand():
    return random.randint(0, 255)

def display_word(pWord,pColor):
    pixelCharWidth = 0
    charOffset = 0
    theColor = pColor
    wordLength = len(pWord)
    for c in range(wordLength):
        if pWord[c].isspace():
            #SPACE
            pixelCharValues = charSpace
            theColor = black
        else:
            #CHARACTER
            pixelCharValues = eval("char" + pWord[c])
            theColor = pColor
        # RENDER CHARACTER
        for i in range(len(pixelCharValues)):
            pixels[pixelCharValues[i]+charOffset] = theColor
        #
        # ADD CHARACTER WIDTH TO OVERALL PIXEL STRING WIDTH
        charOffset += (int(pixelCharValues[len(pixelCharValues) - 1]/8 + 2) * 8)

while True:

    display_word("TEST",black)
    pixels.show()
    
    # do_reset()
Attachments
IMG_4591.JPG
IMG_4591.JPG (366.17 KiB) Viewed 411 times

User avatar
adafruit_support_mike
 
Posts: 67446
Joined: Thu Feb 11, 2010 2:51 pm

Re: Help Requested with LED Panel & Memory Errors

Post by adafruit_support_mike »

The basic problem is that you're running out of RAM. Each NeoPixel consumes about 3 bytes of memory, and that adds up fast.

You can clear some space by declaring all your arrays as 'const', which will store them in the microcontroller's program memory instead of RAM. It's generally a good idea to leave things in program memory unless you know you'll need to modify them.

User avatar
netdzynr
 
Posts: 7
Joined: Wed Apr 17, 2019 1:52 pm

Re: Help Requested with LED Panel & Memory Errors

Post by netdzynr »

Thanks for the response Mike. I've tried to implement what you suggest, but my lack of experience with Python is preventing me from making any progress.

I'm not sure what to declare as a constant. I've tried to use 'const' with the letter and color sets (arrays?) but I get a syntax error in mu that says a constant must be an integer. Maybe I should ask, is a variable like this something that should be declared as constant? X = (1,2,3,4,5)

I also tried saving the character sets into an external file and using "constant.CHAR_A" for example but I still seem to get the same memory errors.

I fully accept I need to get a better grip on CircuitPython, but I'll throw my original question out again: Is the Metro Express just not suited to handling LED arrays of this size?

I really want to figure out how to get things working here -- thanks in advance for your response!

User avatar
adafruit_support_mike
 
Posts: 67446
Joined: Thu Feb 11, 2010 2:51 pm

Re: Help Requested with LED Panel & Memory Errors

Post by adafruit_support_mike »

I was thinking of C as I wrote that, and I’m not sure how well the advice transfers over to Python.

A 256x8 panel has 2048 pixels, and consumes about 6k of RAM. That’s fairly big, but the Metro M0’s microcontroller has 32k of RAM.. more than enough for a buffer that large, at least in C where you have control over the memory allocation.

The CircuitPython interpreter requires its own RAM to operate, so there’s a chance you might be hitting a practical limit. Let me check with some of the folks who know CircuitPython’s internals better.

User avatar
netdzynr
 
Posts: 7
Joined: Wed Apr 17, 2019 1:52 pm

Re: Help Requested with LED Panel & Memory Errors

Post by netdzynr »

[bump] Any update on this Mike or other Adafruit staff? Thanks for looking into options.

User avatar
adafruit_support_carter
 
Posts: 29166
Joined: Tue Nov 29, 2016 2:45 pm

Re: Help Requested with LED Panel & Memory Errors

Post by adafruit_support_carter »

[EDIT] What version of CP are you running?

You're hitting a known issue related to using brightness control. There's a brief mention of it here:
https://learn.adafruit.com/circuitpytho ... n-neopixel
But it also looks like you're using less than the quoted limit. We'll double check that.

For now, you could probably get this running by just removing brightness control:

Code: Select all

pixels = neopixel.NeoPixel(pixel_pin, num_pixels, auto_write=False)

User avatar
tannewt
 
Posts: 3304
Joined: Thu Oct 06, 2016 8:48 pm

Re: Help Requested with LED Panel & Memory Errors

Post by tannewt »

In addition to the brightness control, I suggest using a byte literal for each character instead of a tuple. The tuple will use four bytes per object inside of it instead of just the one you'd need for your values. It's a bit uglier but will save space. Note the values are now in hex. (One of the M4 boards would be better suited for many pixels because it has much more RAM.)

Here is a simple conversion function you can use in a python REPL:

Code: Select all

>>> def to_byteliteral(value_tuple):
...   print("b\'", end='')
...   for value in value_tuple:
...     print("\\x{:x}".format(value), end="")
...   print("'")
...
>>> to_byteliteral((0,6,7,10,15,16,20,28,31,32,33,34))
b'\x0\x6\x7\xa\xf\x10\x14\x1c\x1f\x20\x21\x22'
Then you would do this swap:

Code: Select all

# old: char7 = (0,6,7,10,15,16,20,28,31,32,33,34) new below
char7 = b'\x0\x6\x7\xa\xf\x10\x14\x1c\x1f\x20\x21\x22'
Hope that helps!

Locked
Please be positive and constructive with your questions and comments.

Return to “Metro, Metro Express, and Grand Central Boards”