ELECTRONICS

Библиотека FastLED для адресных лент

Обновлено

В менеджере библиотек
FastLED by Daniel Garcia
Версия
3.10.8 · всего 60 версий, первая — 3.1.0
Платы
любые — автор не ограничивал
СкачатьFastLED-3.10.8.zip · 38,3 МБ

Архивы — копии из официального индекса Arduino, контрольная сумма совпадает. Сверено 19.10.2026.

Адресные ленты WS2812B, WS2811, APA102 и десятки других: цвета, палитры, эффекты, ограничение мощности.

FastLED — стандарт для адресных лент. Она знает тайминги десятков контроллеров, держит массив цветов в памяти и по команде show() выгружает его в ленту. Сверху — арифметика цветов: HSV, плавные переходы, затухание, радуга и палитры, из которых собираются любые эффекты.

Каждый пиксель занимает три байта. На UNO с её двумя килобайтами это потолок около 450 пикселей с запасом на остальной скетч — замер ниже, в граблях. ESP32 держит тысячи.

Как скачать и установить

  1. Через менеджер — самый простой путь. В Arduino IDE: Инструменты → Управлять библиотеками (Ctrl+Shift+I). Введите FastLED и найдите в списке строку «FastLED by Daniel Garcia» — одноимённых библиотек бывает несколько, отличаются они автором. Нажмите «Установить».
  2. Конкретная версия — если в чужом проекте указана не последняя. В той же карточке менеджера рядом с кнопкой есть выпадающий список версий: выберите нужную и нажмите «Установить».
  3. Из архива — если нет интернета на рабочем компьютере или менеджер не открывается. Скачайте ZIP выше, затем Скетч → Подключить библиотеку → Добавить .ZIP библиотеку и укажите файл. Распаковывать не нужно.

Файл FastLED.h отдельно не скачивают: он внутри библиотеки и появляется после установки. Если среда пишет FastLED.h: No such file or directory — библиотека не установлена или установлена не та. Как устроен менеджер и куда складываются файлы — в общей статье про библиотеки.

Строка подключения:

#include <FastLED.h>

Создание объекта — обычно до setup():

#define LED_PIN 6
#define NUM_LEDS 30
CRGB leds[NUM_LEDS];                                   // массив цветов, по одному на пиксель
FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS); // в setup(): тип ленты, вывод, порядок цветов

Подключение ленты

У адресной ленты три провода: питание, земля и данные. Данные идут с любого цифрового вывода через резистор 330 Ом на вход DIN — вход отмечен стрелками на ленте, с обратного конца лента не зажжётся.

Главное — питание. Каждый пиксель берёт до 60 мА на белом во всю яркость: 30 пикселей — почти 2 А, метр по 60 — 3,6 А. От платы можно питать только короткий отрезок, и то с setMaxPowerInVoltsAndMilliamps(5, 500). Всё, что длиннее, — от отдельного блока питания, и его землю обязательно соединить с землёй Arduino.

Схема подключения адресной ленты WS2812B к Arduino UNO: пин 6 через резистор 330 Ом к DIN, 5 В к питанию ленты, GND к земле
Схема с пояснением к каждому проводу — на странице модуля «Лента WS2812B».
WS2812B
Питание: 5 ВПорядок цветов: GRB

addLeds<WS2812B, 6, GRB>

WS2813
Питание: 5 ВПорядок цветов: GRB

addLeds<WS2813, 6, GRB> — резервный вход BIN на входе ленты соединяют с землёй

WS2811
Питание: 12 ВПорядок цветов: BRG или RGB

addLeds<WS2811, 6, BRG> — один чип на три светодиода

WS2815
Питание: 12 ВПорядок цветов: GRB

addLeds<WS2815, 6, GRB>

SK6812
Питание: 5 ВПорядок цветов: GRB

addLeds<SK6812, 6, GRB> — для версии RGBW проще Adafruit NeoPixel

APA102, SK9822
Питание: 5 ВПорядок цветов: BGR

addLeds<APA102, 11, 13, BGR> — провод данных и провод такта

Конденсатор на вход питания ленты

Электролит 1000 мкФ между плюсом и минусом ленты, у места, где приходит питание. Он гасит бросок тока при включении, от которого первые пиксели выходят из строя.

ESP32 и ESP8266: сигнал 3,3 В

Лента на 5 В ждёт сигнал около 3,5 В и выше; 3,3 В с ESP на грани, и первый пиксель начинает мигать случайными цветами. Помогает преобразователь уровня 74HCT125 или питание ленты от 4,5 В вместо 5.

Длинная лента тускнеет к концу

Тонкие дорожки ленты сами роняют напряжение: к концу метра белый желтеет. Питание подводят к обоим концам, а на длинных отрезках — каждые полтора-два метра.

Методы

Только то, что нужно в обычном скетче. Сигнатуры сверены с версией 3.10.8.

Запуск и вывод

FastLED.addLeds<CHIPSET, DATA_PIN, RGB_ORDER>(CRGB* data, int nLeds)

Зарегистрировать ленту с одним проводом данных. Вызывают в setup() один раз на каждую ленту — их может быть несколько на разных выводах.

CHIPSET
тип ленты: WS2812B, WS2813, WS2811, WS2815, SK6812 — таблица выше.
DATA_PIN
вывод данных. Задаётся при сборке, поэтому только числом или константой, не переменной.
RGB_ORDER
порядок цветов: GRB у WS2812B, у WS2811 бывает BRG или RGB. Перепутан — красный и зелёный меняются местами.
data
массив CRGB leds[NUM_LEDS].
nLeds
сколько пикселей.

Возвращает: контроллер ленты; обычно не нужен, но через него задают коррекцию цвета одной ленте.

FastLED.addLeds<WS2812B, 6, GRB>(leds, NUM_LEDS);

FastLED.addLeds<CHIPSET, DATA_PIN, CLOCK_PIN, RGB_ORDER>(CRGB* data, int nLeds)

То же для лент с отдельной линией такта — APA102 и SK9822. Им не нужны точные тайминги, поэтому они быстрее и не выключают прерывания.

CLOCK_PIN
вывод такта. На UNO быстрее всего аппаратный SPI: данные 11, такт 13.
FastLED.addLeds<APA102, 11, 13, BGR>(leds, NUM_LEDS);

void FastLED.show()

Выгрузить массив в ленту. Пока не вызван, лента не меняется. На WS2812B занимает около 30 мкс на пиксель, и на AVR на это время выключены прерывания.

FastLED.show();

void FastLED.clear(bool writeData = false)

Обнулить массив — все пиксели чёрные.

writeData
true — сразу и погасить ленту, без отдельного show().
FastLED.clear(true);

void FastLED.setBrightness(uint8_t scale)

Общая яркость, применяется при каждом show(). Сами цвета в массиве не меняет — можно убавить и вернуть без потерь.

scale
0–255, по умолчанию 255.
FastLED.setBrightness(80);

uint8_t FastLED.getBrightness()

Прочитать общую яркость — например, чтобы плавно её менять кнопкой.

Возвращает: 0–255.

FastLED.setBrightness(FastLED.getBrightness() / 2);

void FastLED.setMaxPowerInVoltsAndMilliamps(uint8_t volts, uint32_t milliamps)

Ограничить потребление: перед каждым show() библиотека считает ток и, если он выше бюджета, сама убавляет яркость. Лента не просаживает блок питания и не перезагружает плату.

volts
напряжение ленты: 5 или 12.
milliamps
бюджет в миллиамперах: 500 — от USB компьютера, дальше — по блоку питания с запасом.
FastLED.setMaxPowerInVoltsAndMilliamps(5, 2000);

void FastLED.setCorrection(const CRGB& correction)

Поправка цвета под ленту: без неё белый у многих лент отдаёт в синеву.

correction
TypicalLEDStrip — для обычных лент, TypicalSMD5050 — для светодиодов 5050, UncorrectedColor — без поправки.
FastLED.setCorrection(TypicalLEDStrip);

void FastLED.delay(unsigned long ms)

Задержка, во время которой библиотека продолжает обновлять ленту — нужно для сглаживания на малой яркости. Вместо обычного delay() в скетчах с лентой.

ms
миллисекунды.
FastLED.delay(20);

void FastLED.showColor(const CRGB& color)

Показать на всей ленте один цвет, не трогая массив. Удобно для вспышки поверх эффекта.

FastLED.showColor(CRGB::Red);

Цвет пикселя

CRGB(uint8_t r, uint8_t g, uint8_t b)

Цвет по красному, зелёному и синему, каждый 0–255. Есть именованные: CRGB::Red, CRGB::Orange, CRGB::Black и ещё полторы сотни.

leds[0] = CRGB(255, 80, 0);
leds[1] = CRGB::Blue;

CHSV(uint8_t h, uint8_t s, uint8_t v)

Цвет через оттенок, насыщенность и яркость. Для эффектов удобнее RGB: меняете один оттенок — получаете радугу.

h
оттенок по кругу 0–255: 0 красный, 32 оранжевый, 64 жёлтый, 96 зелёный, 128 голубой, 160 синий, 192 фиолетовый, 224 розовый.
s
насыщенность: 255 — чистый цвет, 0 — белый.
v
яркость 0–255.
leds[i] = CHSV(160, 255, 200);

CRGB& setRGB(uint8_t r, uint8_t g, uint8_t b)

Задать цвет существующему пикселю по компонентам.

leds[i].setRGB(0, 255, 0);

CRGB& setHSV(uint8_t hue, uint8_t sat, uint8_t val)

Задать цвет существующему пикселю через оттенок.

leds[i].setHSV(96, 255, 255);

CRGB& nscale8(uint8_t scaledown)

Убавить яркость одного пикселя: каждый канал умножается на scaledown/256.

scaledown
0 — чёрный, 128 — вдвое тусклее, 255 — почти без изменений.
leds[i].nscale8(128);

CRGB& fadeToBlackBy(uint8_t fadefactor)

Притушить один пиксель — обратное к nscale8: fadefactor/256 убирается.

leds[i].fadeToBlackBy(64);

Арифметика цветов

leds[i] += color

Сложить цвета по каналам с насыщением: канал упирается в 255, а не переваливает через ноль, как у обычных чисел. Так искры накладываются друг на друга, не превращаясь в мусор. -= — вычитание, упирается в 0.

leds[i] += CHSV(hue, 200, 255);
leds[i] -= CRGB(20, 20, 20);

leds[i] *= k

Умножить каждый канал на число с насыщением — сделать ярче. /= — разделить, сделать тусклее.

k
целое 0–255.
leds[i] *= 2;
leds[i] /= 4;

leds[i] %= scale

Убавить яркость до scale/256, как nscale8(), но по «видео»-правилу: канал, который светился, не гаснет до нуля. На малой яркости цвет не пропадает, а лишь чуть сдвигается оттенок.

scale
0–255.
leds[i] %= 64;   // четверть яркости

leds[i] == color

Сравнить два цвета по всем трём каналам. Есть и !=.

Возвращает: true — цвета совпадают.

if (leds[i] == CRGB(CRGB::Black)) leds[i] = CRGB::Blue;

-leds[i]

Инвертировать цвет: каждый канал становится 255 минус он сам. Красный превращается в голубой, чёрный — в белый.

Возвращает: новый цвет CRGB, сам пиксель не меняется.

leds[i] = -leds[i];

CRGB blend(const CRGB& p1, const CRGB& p2, uint8_t amountOfP2)

Смешать два цвета в заданной пропорции. Если каждый кадр подмешивать чуть-чуть второго цвета, первый плавно в него перетекает — так гаснут звёзды в эффекте мерцания ниже.

amountOfP2
доля второго цвета из 256: 0 — только первый, 255 — почти только второй.

Возвращает: смешанный цвет.

leds[i] = blend(leds[i], CRGB::Black, 16);

Заливки и эффекты ленты

void fill_solid(CRGB* leds, int numToFill, const CRGB& color)

Залить пиксели одним цветом.

numToFill
сколько с начала массива.
fill_solid(leds, NUM_LEDS, CRGB::White);

void fill_rainbow(CRGB* leds, int numToFill, uint8_t initialhue, uint8_t deltahue = 5)

Радуга: у каждого следующего пикселя оттенок сдвинут на шаг.

initialhue
оттенок первого пикселя. Меняйте со временем — радуга поползёт.
deltahue
шаг между соседями. 255 / NUM_LEDS — ровно одна радуга на всю ленту.
fill_rainbow(leds, NUM_LEDS, millis() / 10, 255 / NUM_LEDS);

void fill_gradient_RGB(CRGB* leds, uint16_t numLeds, const CRGB& c1, const CRGB& c2)

Плавный переход между двумя цветами по всей длине. Есть варианты на три и четыре цвета.

fill_gradient_RGB(leds, NUM_LEDS, CRGB::Blue, CRGB::Red);

void fadeToBlackBy(CRGB* leds, uint16_t num_leds, uint8_t fadeBy)

Притушить все пиксели разом. Вызывают каждый кадр — и за движущейся точкой остаётся гаснущий хвост.

fadeBy
сколько убрать за раз, из 256: 10 — длинный хвост, 60 — короткий.
fadeToBlackBy(leds, NUM_LEDS, 20);

void blur1d(CRGB* leds, uint16_t numLeds, uint8_t blur_amount)

Размыть: каждый пиксель смешивается с соседями. Смягчает резкие эффекты.

blur_amount
0–255, сколько брать от соседей.
blur1d(leds, NUM_LEDS, 64);

Время и случайность

EVERY_N_MILLISECONDS(N) { … }

Выполнить блок раз в N миллисекунд без delay(). Таких блоков в loop() может быть сколько угодно, у каждого свой таймер — так один эффект обновляется часто, а смена цвета идёт медленно. Есть EVERY_N_SECONDS.

N
период в миллисекундах.
EVERY_N_MILLISECONDS(20) { hue++; }

uint8_t beatsin8(uint16_t bpm, uint8_t lowest = 0, uint8_t highest = 255, uint32_t timebase = 0, uint8_t phase_offset = 0)

Синусоида по часам, с частотой в ударах в минуту. Для дыхания, покачивания, «маятника» без собственного счётчика времени.

bpm
ударов в минуту: 60 — раз в секунду.
lowest, highest
диапазон значений.
phase_offset
сдвиг фазы — чтобы две синусоиды шли не в ногу.

Возвращает: текущее значение между lowest и highest.

int pos = beatsin8(30, 0, NUM_LEDS - 1);

uint8_t beat8(uint16_t bpm, uint32_t timebase = 0)

Пила по часам: равномерно растёт от 0 до 255 и сбрасывается.

Возвращает: 0–255.

uint8_t hue = beat8(10);

uint8_t random8(uint8_t min, uint8_t lim)

Быстрое случайное число для эффектов. Есть random8() — 0–255 и random8(lim) — от 0 до lim−1; для длинных лент — random16(lim).

min
от — включительно.
lim
до — не включая.

Возвращает: случайное число в диапазоне.

leds[random16(NUM_LEDS)] = CHSV(random8(), 200, 255);

uint8_t inoise8(uint16_t x)

Шум Перлина: случайное, но плавное значение — соседние x дают близкие числа. Основа для огня, воды и облаков.

x
координата; плавно двигайте её по времени.

Возвращает: 0–255.

uint8_t v = inoise8(i * 40 + millis() / 4);

Палитры

CRGBPalette16 palette = LavaColors_p

Палитра из 16 опорных цветов, между которыми библиотека плавно переходит. Готовые: RainbowColors_p, PartyColors_p, HeatColors_p, LavaColors_p, OceanColors_p, ForestColors_p, CloudColors_p.

CRGBPalette16 palette = OceanColors_p;

CRGB ColorFromPalette(const CRGBPalette16& pal, uint8_t index, uint8_t brightness = 255, TBlendType blendType = LINEARBLEND)

Взять цвет из палитры по позиции.

index
позиция 0–255 по палитре.
brightness
яркость результата.
blendType
LINEARBLEND — плавно между опорными цветами, NOBLEND — ступеньками.

Возвращает: цвет CRGB.

leds[i] = ColorFromPalette(palette, i * 8 + beat8(20));

void fill_palette(CRGB* leds, uint16_t N, uint8_t startIndex, uint8_t incIndex, const CRGBPalette16& pal, uint8_t brightness = 255, TBlendType blendType = LINEARBLEND)

Залить ленту цветами палитры подряд — как fill_rainbow, только своими цветами.

startIndex
позиция палитры для первого пикселя.
incIndex
шаг между соседями.
fill_palette(leds, NUM_LEDS, beat8(10), 8, palette);

CRGB HeatColor(uint8_t temperature)

Цвет пламени по «температуре»: чёрный → красный → жёлтый → белый. На нём построен эффект огня ниже.

Возвращает: цвет CRGB.

leds[i] = HeatColor(heat[i]);

Примеры

Бегущий огонёк с хвостом

#include <FastLED.h>

#define LED_PIN   6
#define NUM_LEDS  30
CRGB leds[NUM_LEDS];

void setup() {
  FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS);
  FastLED.setBrightness(80);
  FastLED.setMaxPowerInVoltsAndMilliamps(5, 500);   // питание от платы: не больше 500 мА
}

void loop() {
  // «комета»: точка бежит, хвост гаснет
  static uint8_t pos = 0;
  fadeToBlackBy(leds, NUM_LEDS, 30);
  leds[pos] = CHSV(millis() / 20, 255, 255);
  pos = (pos + 1) % NUM_LEDS;
  FastLED.show();
  delay(25);
}
Запустить в симулятореСхема с этим скетчем — запустить в браузере

Точка меняет цвет по радуге и бежит по ленте, за ней гаснет хвост: fadeToBlackBy() каждый кадр убирает часть яркости у всех пикселей. Ограничение мощности — самая недооценённая функция: с ним лента на полной яркости не просаживает USB и не перезагружает плату.

Радуга

#include <FastLED.h>

#define LED_PIN   6
#define NUM_LEDS  30
CRGB leds[NUM_LEDS];

void setup() {
  FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS);
  FastLED.setBrightness(80);
  FastLED.setMaxPowerInVoltsAndMilliamps(5, 500);
}

void loop() {
  // вся радуга на длину ленты; начальный оттенок растёт со временем — радуга ползёт
  fill_rainbow(leds, NUM_LEDS, millis() / 10, 255 / NUM_LEDS);
  FastLED.show();
}
Запустить в симулятореСхема с этим скетчем — запустить в браузере

Вся лента — одна радуга, и она медленно ползёт. Шаг оттенка 255 / NUM_LEDS укладывает ровно один круг цветов на длину ленты; поставьте шаг больше — радуг станет несколько.

Конфетти на EVERY_N_MILLISECONDS

#include <FastLED.h>

#define LED_PIN   6
#define NUM_LEDS  30
CRGB leds[NUM_LEDS];

uint8_t hue = 0;   // общий оттенок, медленно плывёт

void setup() {
  FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS);
  FastLED.setBrightness(80);
  FastLED.setMaxPowerInVoltsAndMilliamps(5, 500);
}

void loop() {
  // два независимых таймера без delay(): каждый блок сам следит за своим временем
  EVERY_N_MILLISECONDS(20) {
    fadeToBlackBy(leds, NUM_LEDS, 10);                 // старые искры гаснут
    leds[random16(NUM_LEDS)] += CHSV(hue + random8(64), 200, 255);   // новая — в случайном месте
    FastLED.show();
  }
  EVERY_N_MILLISECONDS(50) {
    hue++;
  }
}
Запустить в симулятореСхема с этим скетчем — запустить в браузере

В случайных местах вспыхивают цветные искры и медленно гаснут, а общий оттенок плывёт по кругу. Здесь нет ни одного delay(): два блока EVERY_N_MILLISECONDS работают со своими периодами, и в тот же loop() можно добавить кнопку или датчик — они не будут ждать эффект.

Мерцание звёзд

#include <FastLED.h>

#define LED_PIN   6
#define NUM_LEDS  30
CRGB leds[NUM_LEDS];

const CRGB BACKGROUND = CRGB(0, 0, 8);   // едва заметный тёмно-синий фон

void setup() {
  FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS);
  FastLED.setBrightness(80);
  FastLED.setMaxPowerInVoltsAndMilliamps(5, 500);
  fill_solid(leds, NUM_LEDS, BACKGROUND);
}

void loop() {
  EVERY_N_MILLISECONDS(30) {
    // каждая звезда понемногу возвращается к цвету фона
    for (int i = 0; i < NUM_LEDS; i++)
      leds[i] = blend(leds[i], BACKGROUND, 16);
    // иногда в случайном месте вспыхивает новая — бледного случайного цвета
    if (random8() < 50)
      leds[random16(NUM_LEDS)] = CHSV(random8(), 80, 255);
    FastLED.show();
  }
}
Запустить в симулятореСхема с этим скетчем — запустить в браузере

На тёмно-синем фоне в случайных местах вспыхивают бледные звёзды и плавно гаснут обратно в фон. Гасит их blend(): каждый кадр к цвету звезды подмешивается немного фона. Поменяйте BACKGROUND на чёрный — получится звёздное небо, на тёплый жёлтый — гирлянда.

Огонь

#include <FastLED.h>

#define LED_PIN   6
#define NUM_LEDS  30
CRGB leds[NUM_LEDS];

// по мотивам примера Fire2012 из самой FastLED
#define COOLING   55    // как быстро остывает: больше — пламя ниже
#define SPARKING  120   // как часто вспыхивают искры внизу: 0–255

uint8_t heat[NUM_LEDS];  // «температура» каждого пикселя

void setup() {
  FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS);
  FastLED.setBrightness(80);
  FastLED.setMaxPowerInVoltsAndMilliamps(5, 500);
}

void loop() {
  EVERY_N_MILLISECONDS(16) {
    // 1. каждый пиксель немного остывает
    for (int i = 0; i < NUM_LEDS; i++)
      heat[i] = qsub8(heat[i], random8(0, COOLING * 10 / NUM_LEDS + 2));
    // 2. тепло поднимается вверх по ленте
    for (int k = NUM_LEDS - 1; k >= 2; k--)
      heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2]) / 3;
    // 3. внизу иногда вспыхивает новая искра
    if (random8() < SPARKING) {
      int y = random8(7);
      heat[y] = qadd8(heat[y], random8(160, 255));
    }
    // 4. температура превращается в цвет: чёрный → красный → жёлтый → белый
    for (int j = 0; j < NUM_LEDS; j++)
      leds[j] = HeatColor(heat[j]);
    FastLED.show();
  }
}
Запустить в симулятореСхема с этим скетчем — запустить в браузере

Лента, поставленная вертикально, горит как пламя: у основания жёлтое и белое, выше — красное, языки поднимаются и опадают. Каждый пиксель хранит «температуру»: она остывает, поднимается вверх и снизу подпитывается случайными искрами, а HeatColor() превращает её в цвет. По мотивам примера Fire2012 из самой FastLED.

На чём попадаются

FastLED.h: No such file or directory

Библиотека не установлена или установлена не та. В менеджере библиотек нужна строка «FastLED by Daniel Garcia»; установка из ZIP — Скетч → Подключить библиотеку → Добавить .ZIP.

При сборке оранжевым: pragma message FastLED version

Это не ошибка — старые версии FastLED так сообщали свой номер при каждой сборке. Скетч собран и загрузится. В 3.10 сообщение появляется, только если его попросить через FASTLED_SHOW_VERSION.

Красный и зелёный поменялись местами

Неверный порядок цветов в addLeds. WS2812B — GRB; у WS2811 бывает BRG или RGB. Проверка — залить ленту CRGB::Red: должен загореться красный.

Лента горит мусором или первый пиксель не тот

Нет резистора 330 Ом на линии данных или общей земли с блоком питания. У ESP32 и ESP8266 — ещё и сигнал 3,3 В на грани: нужен преобразователь уровня.

Скетч не собирается: не хватает памяти

Каждый пиксель — три байта. На UNO сама FastLED с простым скетчем занимает около 120 байт из 2048, лента на 450 пикселей съедает 71 % памяти. С 475 пикселей (75 %) среда предупреждает о нехватке, на 600 занято 93 %, на 650 скетч не собирается. С запасом на остальной код — около 450 пикселей. Длиннее — Mega или ESP32.

Скетч теряет данные из Serial или кнопки срабатывают через раз

Пока идёт show(), на AVR выключены прерывания — около 30 мкс на пиксель, на 300 пикселях почти 10 мс. Входящие по Serial байты за это время теряются, а millis() отстаёт. Реже вызывайте show() или берите ленту APA102: ей прерывания не нужны.

Где используется на сайте

Что дальше