Using Teensy 4.1 With FastLED

Got a Teensy 4.1? Want to use it with FastLED? You’ve come to the right place. The Teensy 4.1 is an incredibly powerful microprocessor at a very reasonable price, and FastLED is still one of the best libraries for driving WS2812 type addressable LEDs from Arduino type projects.

Paul Stoffregen, creator of Teensy, has a library called OctoWS2811 that provides fairly basic operations to send RGB data out to addressable LEDs. Unlike FastLED, it doesn’t have all the fancy color manipulation, palettes, fast math operations, etc… just basic “set the pixel color” type operations. But OctoWS2811 is blazingly fast and works perfectly on the Teensy 4.1. One of the reasons it is so fast is because it can drive strips using any and all GPIO pins in parallel and without using a lot of CPU time. (More about my experience here).

So what you really want to do is combine OctoWS2811 with FastLED and you will be cooking with fire. Here’s how to do that.

Step one – get the latest version of OctoWS2811 from GitHub. (Make sure you have version 3.5).

You can use OctoWS2811 directly to write to the LEDs. Here’s an example using 8 pins, numbered 33-40:

  const int numPins = 8;
  byte pinList[numPins] = {33, 34, 35, 36, 37, 38, 39, 40};
  const int ledsPerStrip = 300;
  CRGB rgbarray[numPins * ledsPerStrip];

  // These buffers need to be large enough for all the pixels.
  // The total number of pixels is "ledsPerStrip * numPins".
  // Each pixel needs 3 bytes, so multiply by 3.  An "int" is
  // 4 bytes, so divide by 4.  The array is created using "int"
  // so the compiler will align it to 32 bit memory.
  DMAMEM int displayMemory[ledsPerStrip * numPins * 3 / 4];
  int drawingMemory[ledsPerStrip * numPins * 3 / 4];
  OctoWS2811 octo(ledsPerStrip, displayMemory, drawingMemory, WS2811_RGB | WS2811_800kHz, numPins, pinList);

Now to hook this up with FastLED, you create a custom FastLED “controller” which just forwards the bits to OctoWS2811. This is the simplest possible FastLED controller; it looks like this:

#include <OctoWS2811.h>
#include <FastLED.h>
#include <Arduino.h>

template <EOrder RGB_ORDER = RGB,
          uint8_t CHIP = WS2811_800kHz>
class CTeensy4Controller : public CPixelLEDController<RGB_ORDER, 8, 0xFF>
{
    OctoWS2811 *pocto;

public:
    CTeensy4Controller(OctoWS2811 *_pocto)
        : pocto(_pocto){};

    virtual void init() {}
    virtual void showPixels(PixelController<RGB_ORDER, 8, 0xFF> &pixels)
    {

        uint32_t i = 0;
        while (pixels.has(1))
        {
            uint8_t r = pixels.loadAndScale0();
            uint8_t g = pixels.loadAndScale1();
            uint8_t b = pixels.loadAndScale2();
            pocto->setPixel(i++, r, g, b);
            pixels.stepDithering();
            pixels.advanceData();
        }

        pocto->show();
    }
};

To use this new controller:

  CTeensy4Controller<RGB, WS2811_800kHz> *pcontroller;

  void setup()
  {
    octo.begin();
    pcontroller = new CTeensy4Controller<RGB, WS2811_800kHz>(&octo);

    FastLED.setBrightness(255);
    FastLED.addLeds(pcontroller, rgbarray, numPins * ledsPerStrip);
  }

Tip: This works for Teensy 4.0, too.

Another tip: You can use any and all pins in any order. Just change numPins and pinList.

Enjoy!