smart-leds: WS2812 and similar LEDs with Rust

Posted on

Rust is now running on lots of things and that also means we need to blink LEDs.

To do that with Rust on MCUs can be a bit complicated, depending on the circumstances.

For Rust we (sajattack and me) have written smart-leds with interchangeable output crates for multiple LEDs & platforms and a common trait connecting them all.

The smart-leds crate is intended for you to use in your application code. It contains things like common color definitions, gamma correction as well as other helper functions, and additionally also re-exports all of the needed traits & common types.

All the driver crates only rely on the smart-leds-trait, so we can do more breaking changes in the end-user-facing smart-leds crate and not suffer from a fragmented ecosystem from something that only needed changing in the application-facing side.

For Dotstar/APA102 LEDs, which are using standard SPI, you can just use the apa102-spi-rs driver. That driver should work on everything and has no special requirement, needing only a SPI port. If you don't have one or can't use the one you have for whatever reason, bitbang-hal also works to emulate it with some GPIO pins.

The common WS2812/Neopixel LEDs have pretty tight timing requirements, which are hard to achieve generically only building on abstractions that embedded-hal provides. Taking a look at other libraries, like FastLED, they usually hardcode the output code per platform with assembly loops, but that's pretty hard to maintain across the various hals.

So the situation for these Neopixel/WS2812 LEDs is a bit more complicated, with a few options to choose from. This is explored in the next Post: "WS2812 vs. Rust".

To help you get started, we have written a few examples in the smart-leds-samples repo. The atsamd-rs repo also includes examples for Adafruit boards with Neopixels or Dotstars onboard.