Maximum number of Neopixel LEDs


#1

I am planning to chain several Unicorn Hat boards together.
What is the maximum number of LEDs the Pimoroni Neopixel driver can handle? Or is it effectively unlimited?
Thanks.


#2

You can’t easily chain Unicorn HAT unless you’re bodging copper enamel wire from the end of one pixel chain to the next. They will happily run in parallel, but then that’s just multiple sets of 64 pixels displaying the same thing.

I don’t know what the hard limits are for the number of LEDs that can be driven, but it’s far from unlimited. Users have suggested somewhere in the realm of 3000 LEDs, after which the library gives up the ghost. This is from way back in 2014 though.

One way to find out, I suppose, is to allocate 5k pixels and try to output the signal. Since WS2812s are write-only it’s irrelevant if they’re actually connected or not.

At those sort of quantities, though, power distribution is going to be a waaaay bigger problem.


#3

Thanks for the reply.

You can’t easily chain Unicorn HAT unless you’re bodging copper enamel wire from the end of one pixel chain to the next.

That was the plan yes.

One way to find out, I suppose, is to allocate 5k pixels and try to output the signal. Since WS2812s are write-only it’s irrelevant if they’re actually connected or not.

While that is true it could be that it conks out at the end of the buffer rather than at the beginning. At the moment I only have 288 LEDs in a strip so I can only test that far at the moment.

At those sort of quantities, though, power distribution is going to be a waaaay bigger problem.

Yes I am on top of that one thanks.


#4

In 2016 the original author suggests the only limit is your refresh rate: https://github.com/jgarff/rpi_ws281x/issues/109

And the calculated refresh rate at 1000 pixels is ~33FPS https://github.com/jgarff/rpi_ws281x/issues/30

Presumably to calculate that they took the LED protocol frequency of 800Khz, divided it by the number of bits per pixel, and then the number of pixels:

800000 / 1000 / 24 = 33.3333

For longer chains I’ve heard of APA102s being used, since they can handle data rates into the megahertz (Adafruit claim 32 MHz from the Pi) at which point refresh rate isn’t a concern anymore.

So I guess the answer is; it depends how fast you want to update them.


#5

Thanks, just coming back to this project. I see that I will have to hack the unicornhat.py file in the libiary, which I have done semi successfully. I needed to write a few functions to set leds on a single string basis. But the only way this will work is if I change this line of code
LED_COUNT = 240 # Number of LED pixels. Back to 64 for Just Hat

Any attempt at making a new instance of the Adafruit_NeoPixel libiary, or in fact trying to redefine the original one fail, as if the LED_COUNT variable is used somewhere else outside this file. It would be good to leave this value at 64 and make a call to set up another value but these attempts result in only the first 64 being displayed.
Any enlightenment as to why I can’t redefine this?
Thanks


#6

Unicorn HAT does some funky stuff to make sense of the display- converting its X/Y coordinates into the index of each pixel in the strip. This will totally fall apart if you add extra pixels since you’re creating a 16x8 pixel grid, or an 8x16 pixel grid.

You should probably just drop the whole Unicorn HAT library and use: https://github.com/pimoroni/rpi_ws281x-python

This, when set up, will natively expose both setPixelColor and setPixelColour RGB methods:

from rpi_ws281x import PixelStrip, Color

LED_COUNT      = 128     # Number of LED pixels.
LED_PIN        = 18      # GPIO pin connected to the pixels (must support PWM!).
LED_FREQ_HZ    = 800000  # LED signal frequency in hertz (usually 800khz)
LED_DMA        = 5       # DMA channel to use for generating signal (try 5)
LED_BRIGHTNESS = 128     # Set to 0 for darkest and 255 for brightest
LED_CHANNEL    = 0       # PWM channel
LED_INVERT     = False   # True to invert the signal (when using NPN transistor level shift)
LED_GAMMA = [
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2,
2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5,
6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 11, 11,
11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18,
19, 19, 20, 21, 21, 22, 22, 23, 23, 24, 25, 25, 26, 27, 27, 28,
29, 29, 30, 31, 31, 32, 33, 34, 34, 35, 36, 37, 37, 38, 39, 40,
40, 41, 42, 43, 44, 45, 46, 46, 47, 48, 49, 50, 51, 52, 53, 54,
55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
71, 72, 73, 74, 76, 77, 78, 79, 80, 81, 83, 84, 85, 86, 88, 89,
90, 91, 93, 94, 95, 96, 98, 99,100,102,103,104,106,107,109,110,
111,113,114,116,117,119,120,121,123,124,126,128,129,131,132,134,
135,137,138,140,142,143,145,146,148,150,151,153,155,157,158,160,
162,163,165,167,169,170,172,174,176,178,179,181,183,185,187,189,
191,193,194,196,198,200,202,204,206,208,210,212,214,216,218,220,
222,224,227,229,231,233,235,237,239,241,244,246,248,250,252,255]

ws2812 = PixelStrip(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT, LED_BRIGHTNESS, LED_CHANNEL, LED_GAMMA)

You can then figure out how you want to represent your franken-display and calculate the index to use with setPixelRGB based on that.

Bear in mind, the layout for Unicorn HAT is a snake- winding back and forth from one corner to the one opposite. We just store the layout as a 2d list and grab the right index straight from it:

HAT = [
    [7 , 6 , 5 , 4 , 3 , 2 , 1 , 0 ],
    [8 , 9 , 10, 11, 12, 13, 14, 15],
    [23, 22, 21, 20, 19, 18, 17, 16],
    [24, 25, 26, 27, 28, 29, 30, 31],
    [39, 38, 37, 36, 35, 34, 33, 32],
    [40, 41, 42, 43, 44, 45, 46, 47],
    [55, 54, 53, 52, 51, 50, 49, 48],
    [56, 57, 58, 59, 60, 61, 62, 63]
]

In your case if you had a 16x8 setup, the first row of this list might look like:

HAT = [
    [7 , 6 , 5 , 4 , 3 , 2 , 1 , 0, 71, 70, 69, 68, 67, 66, 65, 64 ],

#7

Thanks for those examples.

Yes I spotted that and totally bypassed by simply making a function that would set the strip directly
def set_strip(i, r, g, b):
if i < LED_COUNT:
ws2812.setPixelColorRGB(i, r, g, b)
Which did work very well but only if I had the LED_COUNT variable set to 240. The basic idea was to leave the unicorn functions intact and just go in addressing the strip directly.

[quote]
Bear in mind, the layout for Unicorn HAT is a snake- winding back and forth from one corner to the one opposite.[/quote]
Yes I spotted the serpentine raster arrangement as soon as I got it working. While it is faster using a list for the lookup it is quite simple to use a bit of code to do it. But what puzzles me is the fact that if I do an other instantiation of the class with a diffrent LED_COUNT value, why does it not “stick”.
By the way what icon do you use for posting code?