Q: How Many NeoPixels Can I Control With This?
A: Buckle Up…
In Douglas Adams’ The Hitchhiker’s Guide to the Galaxy, the mind-bogglingly powerful supercomputer Deep Thought is tasked to find once and for all The Ultimate Answer to Life, the Universe and Everything. Running for 7.5 million years, Deep Thought finally issues an answer — 42, carefully checked and verified — and suggests if the result isn’t satisfactory then maybe they’re asking the wrong question.
“How many NeoPixels” is very much like that. Folks want a concrete answer, like 42, but there are so many layers of nuance it’s just not that simple.
If you’ll settle for a quick but imprecise answer, let’s say the NeoPXL8 library running on Feather RP2040 SCORPIO can reasonably manage up to about 10,000 RGB NeoPixels, or 6,000 RGBW pixels. NeoPXL8HDR, about 1/10th that — 1,000 RGB or 600 RGBW pixels. These are very round “ish” figures involving a lot of hand waving and rough napkin math, and assume the pixels are fed power from an external source, not through the board’s USB-C port. Particular situations could yield different outcomes, either more or fewer. So let’s peel back some of those layers…
By way of metaphor…consider this diagram of aerodynamic forces from every 6th grade science book.
The point of this illustration is that flight is never dictated by just one simple pass/fail number. A continual evaluation of all these changing forces determines whether the airplane takes flight…
Some of the “forces” that all play into the success (or failure) of large-scale NeoPixel projects include:
- RAM
- Signal bandwidth
- CPU speed
- Power
- Cost
- Subjective human perception
RAM
In the classic plain-vanilla Adafruit_NeoPixel library, each RGB pixel requires 3 bytes of RAM. RGBW pixels are 4 bytes each. The popular Arduino Uno microcontroller board of days past provides 1.5 kilobytes of RAM. Just keeping the Arduino “core” and user code running takes some overhead, so there’s a little over 1K free for things like NeoPixels…let’s say around 350 of the RGB variety, or 250 RGBW, to use very rounded figures.
In the Adafruit_NeoPXL8 library, pixels require at least twice the space: 6 bytes per RGB pixel, or 8 per RGBW. This is because there’s two copies of the pixel data: one in “original NeoPixel” format for speedy access, and an internal copy where all the data has been shuffled around for SCORPIO’s concurrent 8-way output. Adafruit_NeoPXL8HDR requires still more, about 5X the base amount.
All this additional data would seem like a drag, except that contemporary microcontrollers are packed with inordinate amounts of RAM! The RP2040 chip at the heart of Feather SCORPIO has 264 kilobytes. So even in the doubled-up NeoPXL8 format, there’s a theoretical potential for nearly 45,000 RGB NeoPixels, or 33,000 RGBW…way beyond our simple 10,000/6,000 answer earlier. We dial it back because at this scale, all the other “forces” play a much larger role than RAM alone…
Signal Bandwidth
A string of NeoPixels receives data at a constant rate…and not a terribly fast one. Bits are sent down the wire, bucket-brigade style, at 800,000 bits per second (800 Kbps). For most runs of modest length, this works fine, but as projects grow it can become a bottleneck. NeoPXL8 was specifically written to tackle this bottleneck by splitting the problem into 8 smaller ones…but if a project really grows in scope, we’re back to square one (or like, 8 square ones concurrently).
800 Kbps is equal to 1.25 microseconds per bit (1.25 µS/bit). Each RGB NeoPixel expects 24 bits of color data (30 µS). RGBW pixels, 32 bits (40 µS). And then, to mark the end of data, there’s a 300 µS pause with no activity on the line.
If we were to max this out to that theoretically possible 45,000 pixel figure (eight strands of 5,625 RGB NeoPixels each), every single time there’s an update, it would take 169,050 microseconds to issue that much data. Over 1/6 of a second. Meaning it could never animate anything that large faster than six frames per second (6 FPS). That’s not good. But what even is good?
Subjective Human Perception
Going out-of-sequence for a moment, let’s consider that last figure. Why is 6 FPS inadequate? It isn’t necessarily. That all depends what you’re trying to achieve…it just happens that most NeoPixel projects are aiming for smooth continuous motion.
What constitutes “smooth” is a topic of much debate, and you may have heard figures like 24, 25, 30, 50 or 60 frames per second tossed about. None of these are Sacred Golden Things handed down from Mount Olympus…just various rates standardized upon in film and TV. The hotness in gaming right now is 120 FPS monitors. Meanwhile, a lot of really top-notch traditional animation is shot “on twos,” meaning just 12 frames per second…an order of magnitude difference! It’s all so variable and in reality you don’t have to hit any of these numbers, nor even remain constant.
It’s simply subjective. What looks good? What’s smooth enough?
Since it’s been relied upon in film for close to a century now, let’s generalize that “around 24 FPS usually starts to looks nice.” More often looks better, less might be adequate, but let’s say it “looks nice.” Rounding up to a mathematically-simpler 25 FPS, each frame is then visible for 40,000 µS…and all the NeoPixel data for each frame needs to be transmitted within that time window. Subtracting the 300 µS “latch time,” and dividing by 30 µS per RGB pixel yields 1,323 pixels per strand, so 10,584 total at 25 FPS. We round to 10,000 because it’s easier to say, and because it’s really just an approximate aspirational target…it’s highly unlikely anything will actually build up quite this large, as there’s still other forces to consider. The board and code could “reasonably manage” this many NeoPixels and animate them “well enough,” so that’s the source of our answer…but really that’s just the start of an uphill climb…
CPU Speed
So you might possess 10,000+ NeoPixels, a suitable power source, and the hardware might be capable of sending all that data many times per second…but where is that data coming from? It has to be generated by your own code on the microcontroller…often by visiting every single pixel. Can you even calculate that many pixels in that short a time? It often depends on how complex the animation is.
Working to your advantage, the NeoPXL8 library uses direct memory access (DMA) to transmit all the data without CPU intervention…the transfer proceeds in the background while the CPU is totally free to calculate pixels for the next frame. This is in contrast to the classic NeoPixel library, where everything stops during these updates.
Working against you…first, a small amount of overhead is needed to “shuffle” the pixel data you generate into the format that goes down the wires. It’s not a lot of time, but it’s present. Second, a bigger factor is just the math needed to calculate the animation for all those pixels…and progressively fewer microseconds available to do this at higher frame rates. Not insurmountable, but typically either the animation complexity or the number of pixels has to give…often it’s some compromise between these. 10,000 might be optimistic, but it’s reasonable as a soft limit to toss around and answer the most frequently-asked question.
If you program some gorgeous animation but it’s just a little too complex and the frame rate is slightly less than you’d like, keep in mind that the RP2040 microcontroller is very accepting of overclocking (Tools→CPU Speed menu … even 200 MHz is usually robust, though higher speeds might get unreliable), and you can also try different compiler optimization settings (Tools→Optimize), though these often have unintended consequences.
If you have an idea for a large project but aren’t certain it can scale up due to this potential bottleneck, try writing some code as if you had all those pixels connected, but in reality nothing is there yet. Count frames and elapsed time (using millis()
) to gauge the average frame rate. Or, if you have some NeoPixels around, try connecting fewer or shorter runs (but with the code configured for full size) and see if this smaller section looks good or if animation is too choppy. If the results are encouraging, then proceed to build upward!
Power
More than anything else, this is what kneecaps really large projects. You might have all the speed and frame rate issues worked out, but just getting enough power distributed through massive NeoPixel projects (and doing it safely) can be really challenging. Without careful consideration of overall brightness and color across several thousand LEDs, this could even trip a typical house circuit breaker. This is why “10,000” is a “theoretical” maximum — we don’t actually recommend taking it that far, or even half that, but it’s possible and you asked for a number.
A couple of other guides go into more detail on this topic:
- On scaling up: 1,500 NeoPixel LED Curtain
- On scaling back: Sipping Power With NeoPixels
NeoPXL8HDR
NeoPXL8HDR takes a different approach. Rather than more and more pixels, it takes fewer pixels and pulls tricks to make them look nicer. This refreshes the NeoPixels hundreds of times per second to “dither” colors and brightness. But…as discussed in the Signal Bandwidth section above…there’s an inherent data bottleneck. Too many pixels and the effect slows down and falls apart.
This is why the recommended maximums are 1/10 as much: 1,000 RGB pixels (as eight 125 pixel runs) or 600 RGBW (8x75). But these are not actually hard limits, it’s just where the dithering effect subjectively starts to come apart. You can go higher by dialing back the precision to 11 or even 10 bits, it’s just not as satisfying. And shorter runs will always look better because they refresh (dither) faster.
Red Herring
All of this is why “How many NeoPixels” might be a distraction; the wrong question. Big numbers catch attention, and SCORPIO is capable of going there, but it’s worth further asking if those big numbers are really necessary for your art and your soul.
Funny thing…NeoPXL8, NeoPXL8HDR, SCORPIO…these weren’t really motivated by large projects, but by topologically problematic ones. Wearables, cosplay, stage costumes for example…there was a tendency for creators to wrap one massively long run of NeoPixels around a body. But given bodies’ range of motion and flexibility, breaks are nearly inevitable. Splitting this into multiple runs can’t prevent breaks, but when they happen, the problem is localized, not catastrophic…
We get it, twinkling lights elicit smiles! But this doesn’t necessarily scale linearly. 200 NeoPixels might have greater impact than 100, but it’s unlikely to be fully twice the impact. It seems the folks most impressed by massive NeoPixel projects are other folks who’ve struggled to built massive projects. Consider your audience, and how much (or little) is really needed to make them happy.
It’s funny that, as engineer types, we tend to glorify simplicity and minimalism — efficient and bloat-free code, the barebones circuit designs of Wozniak or Sinclair, the geometric purity of a Dieter Rams radio — but toss some NeoPixels in front of us and we lose all control. SCORPIO addresses some practical barriers to bigger projects, but in doing so opens doors to a new set of issues. If you find yourself unhealthily obsessing over “how many,” it might be time to challenge yourself to how few.
If anyone asks though, just tell them 10,000 NeoPixels. Saves time, sounds cool.
Text editor powered by tinymce.