NeoPixel Arduino Library Best Practices

The habit of “copy-and-paste programming” — taking an existing project and modifying as little as possible to get it to do a new thing — yields quick results, but applied repeatedly it can result in sub-par code that doesn’t reflect current capabilities. Here’s a few things to watch out for when using the Adafruit_NeoPixel library for Arduino. Some of this applies to the Adafruit_DotStar library as well.

Newer Capabilities That See Little Use Because They’re Not Referenced In Old (Copied-and-Pasted) Code

TIRED: wheel()

wheel() is not actually part of the library itself, but was a small helper function in the first “strandtest” example that got copy-and-pasted out of control. This accepts a single unsigned 8-bit value (0-255) representing hue, returning a 32-bit fully-saturated color.

ColorHSV() has been in the library for ages now but lacks wheel()’s copy-paste momentum. Use it! This accepts three values: hue (unsigned 16-bit; 0 to 65535), saturation (0-255) and value (brightness) (0-255)…then, an optional fourth boolean argument, if “true,” applies gamma correction to the result. This function produces a much broader range of more nuanced colors than the old wheel(). It’s documented here.

FUN FACT: recent versions of the NeoPixel and DotStar libraries also include the rainbow() function, filling a whole strip with one or more cycles of color. As much as I’d like to believe we’ve moved past such clichés, the look remains super popular, almost the Hello World of addressable LEDs…so there it is, all in one function. The new function can also accept saturation and brightness. Some of the examples still implement their own rainbow() functions and have not been updated for this new hotness yet.

Misunderstood Functions That You Might Want To Avoid Unless You Understand the Ramifications

TIRED: setBrightness() and getPixelColor()
WIRED: Math.

A huge misunderstanding is trying to use setBrightness() as an animation effect in itself, as when fading an LED strip to black. It’s really intended for one-time setup, say to tone down the overall brightness of a project, but even that is just a quick band-aid and not an ideal approach. 8-bit AVR microcontrollers were mainstream when Adafruit_NeoPixel was introduced, and doing brightness scaling as data is sent “down the wire” was too demanding…so a compromise was to “decimate” values as they’re passed to setPixelColor(), meaning you’ll rarely get the same value back from getPixelColor(). Newer 32-bit microcontrollers could handle it, but the old behavior is kept for consistency. Adafruit_NeoPixel_ZeroDMA and Adafruit_NeoPXL8 don’t suffer this because they’re exclusively for certain 32-bit chips.

setBrightness() is fine for quick-and-dirty code. You want something less bright. Easy. If you want something more predictable and controllable, render the strip “manually,” perhaps using the fill() function. Eventually I’ll write a whole guide on math-centric animation, but it’s a huge topic, too much to cover here.

Deprecated Functions Kept Around Only for Backwards Compatibility But Should Be Avoided

TIRED: updateLength() and updateType()
WIRED: C++ “new” operator.

These functions allow changing the length and type of a previously-declared NeoPixel strip, the use case being code that was reading configuration data from flash or SD, so the strip parameters aren’t known at compile time and can’t be declared globally. These were merged into the library with little forethought…and while technically they’ll work, it just replicates functionality better handled and already present in the language itself, and these run the risk of fragmenting memory and/or failing to reallocate. These are only present for a small amount of old code and will get deleted some day; they’re not even present in Adafruit_NeoPixel_ZeroDMA or Adafruit_NeoPXL8, and never will be.

Instead, the C++ “new” operator and function pointers (->) should be used.

Rather than:
Adafruit_NeoPixel strip(length, pin, type);


It would be:
Adafruit_NeoPixel *strip;

strip = new Adafruit_NeoPixel(length, pin, type);

The object pointer must be global, not declared in a function, due to the “scope” of variables and their storage.

This is pretty esoteric stuff and only needed if NeoPixel attributes aren’t known at compile-time. The “wrong” way came about because of some copy-and-paste code not wanting to change every “.” to “->” — but, sorry, that’s just the Good and Proper way it’s supposed to be done.

Interestingly, updatePin() (NeoPixel) and updatePins() (DotStar) remain with no plans to phase out. While not an ideal practice, what these can do is allow the same RAM to be re-used between multiple strips (rather than declaring multiple objects, each with their own buffer). Hacky, esoteric, and only in the most RAM-constrained situations…but valid.

Altogether Different Approaches to Consider

TIRED: Adafruit_NeoPixel? Maybe.
WIRED: FastLED, Adafruit_NeoPixel_ZeroDMA, Adafruit_NeoPXL8, Adafruit_NeoPXL8HDR, CircuitPython with the LED Animation Library.

Adafruit_NeoPixel is considered a starting point. It’s not sophisticated, not abstract…time, pixels and colors are discrete things, programmed brute-force-like. We picture folks using it for quick LED tests before graduating to something else; it’s not a whole “platform.”

FastLED conceptually works at a higher level; animation and color palettes are presented differently, with many details handled by the library and not needed in your code.

Adafruit_NeoPixel_ZeroDMA and Adafruit_NeoPXL8 & Adafruit_NeoPXL8HDR still follow NeoPixel’s non-abstract style, but take advantage of hardware in the latest microcontrollers to free up CPU cycles for better animation.

CircuitPython and the CircuitPython LED Animation Library break free of the write-compile-upload cycle…you can iterate super quick to develop ideas!

Stop breadboarding and soldering – start making immediately! Adafruit’s Circuit Playground is jam-packed with LEDs, sensors, buttons, alligator clip pads and more. Build projects with Circuit Playground in a few minutes with the drag-and-drop MakeCode programming site, learn computer science using the CS Discoveries class on, jump into CircuitPython to learn Python and hardware together, TinyGO, or even use the Arduino IDE. Circuit Playground Express is the newest and best Circuit Playground board, with support for CircuitPython, MakeCode, and Arduino. It has a powerful processor, 10 NeoPixels, mini speaker, InfraRed receive and transmit, two buttons, a switch, 14 alligator clip pads, and lots of sensors: capacitive touch, IR proximity, temperature, light, motion and sound. A whole wide world of electronics and coding is waiting for you, and it fits in the palm of your hand.

Join 35,000+ makers on Adafruit’s Discord channels and be part of the community!

Have an amazing project to share? The Electronics Show and Tell is every Wednesday at 7pm ET! To join, head over to YouTube and check out the show’s live chat – we’ll post the link there.

Join us every Wednesday night at 8pm ET for Ask an Engineer!

Follow Adafruit on Instagram for top secret new products, behinds the scenes and more

CircuitPython – The easiest way to program microcontrollers –

Maker Business — Foxconn executive discusses the dramatically scaled back project in Wisconsin

Wearables — Where should I cut on my Neopixel LED strip?

Electronics — Solder isn’t everything.

Python for Microcontrollers — Python on Microcontrollers Newsletter: 300 Adafruit CircuitPython Libraries, Pico W Projects & More! #Python #CircuitPython @micropython @ThePSF @Raspberry_Pi

Adafruit IoT Monthly — Detect Radiation, ML Baby Monitor, and more!

Microsoft MakeCode — MakeCode Thank You!

EYE on NPI — Maxim’s Himalaya uSLIC Step-Down Power Module #EyeOnNPI @maximintegrated @digikey

New Products – Adafruit Industries – Makers, hackers, artists, designers and engineers! — #NewProducts 8/3/22 Feat. LCD FeatherWing from Oddly Specific Objects! #adafruit #diyelectronics #newproducts

Get the only spam-free daily newsletter about wearables, running a "maker business", electronic tips and more! Subscribe at !

No Comments

No comments yet.

Sorry, the comment form is closed at this time.