Лента светилась зелёным. Я просил красный — в коде стоял CRGB::Red, я три раза перепроверял провод данных, перекидывал землю с клеммы на клемму, а WS2812 упорно горела зелёным, как новогодняя ель в июле. Полтора часа я подозревал брак, потом блок питания, потом себя. Виноват оказался один аргумент в одной строке: порядок каналов цвета. У WS2812 он не RGB, а GRB — зелёный идёт первым, и лента, которой скормили «красный», честно показывала зелёный. Об этой ловушке рассказываю первым делом, чтобы вы на неё не наступили.
В этом уроке мы подключим адресную ленту WS2812B к Arduino по одному проводу данных, поставим библиотеку FastLED, разберём, чем она отличается от Adafruit NeoPixel и когда какая уместна, зажжём первые пиксели — сплошной заливкой и по отдельности. Всё это можно повторить прямо здесь, в симуляторе: лента на 16 пикселей уже распаяна на виртуальном пине 6.
Чем адресная лента отличается от обычной RGB
Обычная RGB-лента — это три параллельные цепочки светодиодов с общим питанием: подали на красный канал — горит вся лента красным, вся и сразу. Управлять отдельным участком нельзя в принципе. Адресная лента устроена иначе: в каждом светодиоде (или в каждой группе из трёх) спрятан крошечный чип, который принимает 24 бита цвета — по восемь на канал, — забирает «свои» три байта, а всё остальное передаёт дальше по цепочке. Команда бежит по ленте, как эстафета: первый пиксель съел свой цвет, остальное выбросил на выход — второму, тот поступил так же, и так до конца.
Практически из этого следуют три вещи. Первая: проводов всего три — 5V, GND и DI (data in), причём у ленты есть направление: DI принимает данные со стороны стрелки на подложке, DO (data out) отдаёт следующему куску. Перепутаете сторону — лента молчит, и это не брак. Вторая: резать ленту можно в любом месте линии разреза и спаивать сколько угодно кусков — контроллер в каждом пикселе это позволяет. Третья: вместо «залить всё красным» вы говорите «пиксель 0 — красный, пиксель 1 — тёмно-синий», и именно поэтому адресные ленты и матрицы стоят везде: от подсветки аквариума до экранов стадионов.
Про маркировку: WS2812B — самый ходовой чип, 5 вольт, один провод данных, 800 килобит в секунду по линии. Ленты выпускают по 30 и по 60 пикселей на метр; для первых опытов я советую 30 — ток меньше, глаза не слепит, отладка спокойнее.
Теперь неприятная часть — ток. Один пиксель WS2812B ест до 60 мА, но только при условии, что он залит белым цветом на полной яркости 255: тогда горят все три кристалла сразу. Шестнадцать таких пикселей — почти ампер. Метр 60-пиксельной ленты, залитый белым на максимум, — до 3,6 А, и это уже не «питание от пина Arduino», это отдельный блок питания на 5 вольт с запасом. Если же вы залили ленту спокойным синим на яркости 80, реальный ток будет в несколько раз меньше — ни ленту, ни USB-порт жалко не будет.
Практическое правило для старта: до 16 пикселей питайтесь от Arduino, как в симуляторе. Дальше — внешний источник 5 В, и его землю соединяют с землёй Arduino обязательно: без общей земли данные читаются как шум, и лента начинает показывать «снег» из случайных цветов.
FastLED или Adafruit NeoPixel: что выбрать
Библиотек две, и поиск по запросу «ws2812 arduino» выдаст обе. Adafruit NeoPixel — официальная библиотека компании, которая популяризировала эти ленты: простая, с образцовыми примерами и очень аккуратной документацией. FastLED — сторонняя, но де-факто стандарт для всего серьёзного: быстрее укладывает данные в провод, знает цветовое пространство HSV и палитры, умеет калибровать цвет под конкретную партию лент, поддерживает десятки моделей чипов — WS2811, SK6812, APA102 с тактовым проводом и другие — и активно развивается.
Моё мнение с оговоркой: если вы собираете разовую поделку на десять пикселей, чтобы «мигнуть и забыть», — обе библиотеки равнозначны, берите любую. Если проект дальше гирлянды — плавные цвета, эффекты, больше сотни пикселей — я бы сразу ставил FastLED: переучиваться с NeoPixel потом всё равно придётся, а привычки HSV и кадровой анимации, которые даёт FastLED, пригодятся во всех будущих проектах. В этом курсе мы работаем с FastLED.
Насчёт «библиотека fastled скачать»: скачивать архивы с сайтов вручную не нужно. В Arduino IDE откройте Скетч → Подключить библиотеку → Управлять библиотеками, наберите в поиске FastLED и нажмите Установить — менеджер сам подтянет последнюю версию вместе с примерами. То же самое делает Platformio одной строкой в платформе проекта.
Первый скетч: четыре строки, которые зажигают ленту
#include <FastLED.h> #define LED_PIN 6#define NUM_LEDS 16 CRGB leds[NUM_LEDS]; void setup() { FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS); FastLED.setBrightness(80); fill_solid(leds, NUM_LEDS, CRGB::Red); FastLED.show();} void loop() { // лента уже горит красным; менять нечего}Разберём построчно, потому что здесь прячутся три понятия, на которых держится весь FastLED. Строку #include в симуляторе писать не нужно — он знает FastLED без неё; в Arduino IDE она обязательна.
CRGB leds[16] — массив из шестнадцати «пиксельных» переменных. Это буфер в памяти Arduino: вы пишете цвета сюда, и пока не вызван show(), лента ничего не знает о ваших планах. Хотите пятый пиксель жёлтым — пишете leds[4] = CRGB(255, 255, 0), нумерация с нуля.
FastLED.addLeds<WS2812B, 6, GRB>(leds, 16) — паспорт подключения: чип WS2812B, данные на пине 6, порядок каналов GRB, буфер — наш массив, пикселей 16. Угловые скобки выглядят пугающе, но это просто три константы, зашитые при компиляции, — за то FastLED и быстр: никаких проверок в рантайме.
FastLED.setBrightness(80) — общая яркость от 0 до 255. fill_solid(leds, 16, CRGB::Red) заливает весь буфер одним цветом. И наконец FastLED.show() — единственный момент, когда байты физически уходят в провод: 24 бита на пиксель, по 30 микросекунд на каждый при 800 кГц, 16 пикселей — полмиллисекунды. До show() можно менять цвета хоть в каждом проходе loop() — на ленте всё это время стойко горит предыдущий кадр.
Тупик, ради которого всё затевалось: GRB вместо RGB
Возвращаюсь к истории из начала урока. Протокол WS2812 исторически гонит байты в порядке G-R-B: сначала зелёный канал, потом красный, потом синий. Если сказать библиотеке «порядок RGB» и скормить ленте CRGB::Red — то есть (255, 0, 0), — байты уйдут по wire в порядке 255-0-0, лента прочитает их как G=255, R=0, B=0. Вот вам зелёный вместо красного, при том что код формально «работает» и компилятор молчит. FastLED решает это третьим аргументом шаблона: GRB для WS2812B. Написали один раз — и забыли; не написали — получаете сюрреалистичные цвета.
Как диагностировать, если лента досталась без документации: зажгите чистый красный. Горит зелёным — вам нужен GRB. Горит правильно — RGB. Синий с зелёным при этом обычно не перепутать, поэтому красный — идеальный тест. Клоны лент с маркетплейсов иногда требуют и BRG — метод тот же: переберите три варианта, один совпадёт. На это уходит минута, а не полтора часа, как у меня.
Эксперименты для закрепления
Адресная лента щёлкает только тогда, когда вы сами пощупали индексы буфера. Три задачи, все решаются в симуляторе выше за десять минут, без паяльника и без риска что-то спалить.
- Зажгите каждый четвёртый пиксель белым (0, 4, 8, 12), остальные оставьте чёрными. Подсказка: цикл
for (int i = 0; i < 16; i = i + 4). - Соберите градиент от чёрного к красному: в цикле
leds[i] = CRGB(i * 17, 0, 0). Объясните себе, почему именно 17 — подсказка: шестнадцать шагов до 255. - Сделайте «светофор»: пиксели 0–5 красные, 6–10 жёлтые — CRGB(255, 150, 0), 11–15 зелёные. Затем добавьте мигание жёлтого участка по таймеру millis() — и вы морально готовы к третьему уроку раздела.
- WS2812B — адресная лента: три провода (5V, GND, DI), 24 бита на пиксель, чип внутри каждого светодиода
- FastLED быстрее и богаче NeoPixel (HSV, палитры, десятки чипов); для разовой поделки разницы нет
- Буфер leds[] живёт в памяти; на ленту всё уходит только по команде FastLED.show()
- У WS2812B порядок каналов GRB — третий аргумент addLeds; тест — зажечь чистый красный
- Резистор 300–500 Ом в линию данных, конденсатор 1000 мкФ у входа, подпитка каждые ~1 м при полной яркости
- Пиксель ест до 60 мА на максимуме; 16 пикселей — можно от Arduino, метр 60-пиксельной ленты — отдельный блок питания
- 1. Сколько информационных проводов нужно WS2812B для управления (не считая питания)?
- 2. В каком порядке пиксель WS2812B ждёт байты цвета?
- 3. Когда пиксели физически поменяют цвет?
- 4. Зачем резистор 300–500 Ом в линию данных?
- 5. Сколько тока потребляет один пиксель при полной яркости белым?
- 6. Чем FastLED выгодно отличается от Adafruit NeoPixel?
Теперь у вас есть лента, которая слушается по одному проводу, и вы знаете главную ловушку раздела — GRB. Следующий логичный вопрос: как красить пиксели не «три числа наугад», а осмысленно — делать закаты, радугу, плавные переливы без часов подбора. Для этого в FastLED есть цветовое пространство HSV, и это самый приятный инструмент библиотеки. Встретимся там.
Частые вопросы по теме урока
- Сколько информационных проводов нужно WS2812B для управления (не считая питания)?
- 5V и GND — питание, а цвет идёт одной линией DI. Тактовый провод нужен другим чипам (например APA102), у WS2812 тайминги зашиты в сам сигнал. Один — линия данных
- В каком порядке пиксель WS2812B ждёт байты цвета?
- Порядок GRB — зелёный, красный, синий. Отсюда третий аргумент шаблона: FastLED.addLeds<WS2812B, 6, GRB>. G-R-B
- Когда пиксели физически поменяют цвет?
- leds[] — буфер в памяти. Только show() выталкивает 24 бита на пиксель в провод, по 30 микросекунд на пиксель. После вызова FastLED.show()
- Зачем резистор 300–500 Ом в линию данных?
- Резистор стоит последовательно с данными у входа ленты и гасит выбросы при длинных проводах и паразитных наводках — первый пиксель остаётся жив. Чтобы защитить вход первого пикселя от выбросов и помех
- Сколько тока потребляет один пиксель при полной яркости белым?
- 60 мА — максимум при белом цвете и яркости 255, когда горят все три кристалла. Реальный ток зависит от цвета и setBrightness. До 60 мА
- Чем FastLED выгодно отличается от Adafruit NeoPixel?
- NeoPixel проще и с образцовой документацией, но FastLED быстрее, богаче математикой цвета и поддерживает больше моделей лент. HSV-цвета, палитры, выше скорость, поддержка десятков чипов