Ночник под полкой на двенадцати пикселях я собрал за полчаса, а цвет подбирал два вечера. Хотелось тёплого света, как у лампочки накаливания. Первым делом записал CRGB(255, 255, 255) — белый же. Получился операционный стол: свет холодный, стерильный, сидеть под ним не хочется. Тогда я начал крутить три канала вручную и записывать удачные тройки на клочке бумаги: подниму зелёный — уходит в болото, добавлю синего — становится больничным. К вечеру второго дня на клочке было одиннадцать строк, и половина из них на глаз не отличалась от соседних.
Проблема была не в ленте и не в глазах, а в том, что я не понимал, с чем работаю: что вообще такое CRGB, за что отвечает каждый из трёх байтов и почему белый цвет оказался самым дорогим по току. В этом уроке разберём структуру цвета в FastLED, именованные константы вроде CRGB::Red, функцию fill_solid для заливки всей ленты одним вызовом — и посчитаем миллиамперы. Ночник мы добьём: в симуляторе ниже он будет гореть тёплым, а не стерильным.
CRGB — три байта на пиксель
CRGB — это структура из трёх полей: r, g и b. Каждое — один байт, значения от 0 до 255: ноль — кристалл выключен, 255 — горит на полную. Итого 24 бита на пиксель, ровно столько и передаётся в провод при каждом обновлении. Пишется цвет прямым присваиванием: leds[4] = CRGB(255, 0, 0) зальёт пятый пиксель красным — нумерация с нуля, как у всех массивов. В первом уроке раздела мы подключали ленту и выяснили, что массив leds — буфер в памяти: цвета можно переписывать хоть каждый проход loop(), а на ленту они попадут только после FastLED.show().
Второй способ задать цвет — именованные константы: CRGB::Red, CRGB::Green, CRGB::White и другие. Это просто заранее готовые тройки чисел с человеческими именами: CRGB::Red — та же (255, 0, 0), только читается мгновенно и не даёт опечататься в каналах. В настоящей библиотеке таких имён несколько сотен — почти вся HTML-палитра, от AntiqueWhite до YellowGreen. В симуляторе курса доступен компактный набор, который я собрал в таблицу ниже, — для учебных задач его хватает с запасом. Больше всего я ценю в константах не краткость, а честность: CRGB::Red везде красный, а вот «красный» из трёх чисел на памяти — неизвестно какой.
| Константа | Каналы R-G-B | Где пригождается |
|---|---|---|
| CRGB::Red | 255, 0, 0 | тревога, индикация ошибки |
| CRGB::Orange | 255, 96, 0 | закаты, «жаркие» акценты |
| CRGB::Yellow | 255, 255, 0 | предупреждение |
| CRGB::Green | 0, 255, 0 | «всё в порядке» |
| CRGB::Cyan | 0, 255, 255 | лёд, вода, холодный акцент |
| CRGB::Blue | 0, 0, 255 | тёмный фон, ночь |
| CRGB::Purple | 128, 0, 128 | декор, приглушённый декор |
| CRGB::White | 255, 255, 255 | максимум света — следите за током |
| CRGB::Black | 0, 0, 0 | выключенный пиксель |
Кстати, тот же цвет на обычном RGB-светодиоде мы собирали в уроке про RGB-светодиод — тремя вызовами analogWrite на три пина. С адресной лентой механика та же, только FastLED упаковывает тройку в одно присваивание, а широтно-импульсную модуляцию делает чип внутри пикселя, без участия вашего скетча. Отсюда и практический вывод: тройка чисел в CRGB — это не «три отдельных огонька», а пропорция, в которой смешаются три кристалла внутри одного корпуса.
Теперь ток, и тут белый — рекордсмен. Один пиксель WS2812B на полной яркости белым берёт до 60 мА: горят все три кристалла сразу. Двенадцать пикселей моего ночника в режиме (255, 255, 255) и setBrightness(255) просили до 0,72 А — для USB-порта Arduino уже на грани. Но это верхняя граница, а не норма: тот же белый на setBrightness(40) берёт примерно в шесть раз меньше — около 120 мА на всю дюжину. Тёплый белый экономнее по построению: тройка (255, 147, 41) означает, что красный кристалл горит на полную, зелёный на 58 процентов, синий на 16 — а каждый выключенный кристалл ток не ест вовсе. Подробную арифметику питания больших лент мы считали в уроке про закон Ома, здесь достаточно пропорций.
Моё правило для ночников: синий канал вообще не поднимаю выше 60 — глубокий синий плюс красный даёт «лампочку», а не «монитор». Граница правила: если подсветка рабочая — под ней нужно паять или читать, — синий возвращаю к 100–120, иначе цвет уходит в янтарный и краски на столе искажаются. Собрать свой оттенок из трёх каналов можно и руками: ниже — интерактивная песочница, покрутите ползунки R, G и B и посмотрите, как из трёх чисел собирается один цвет и как переворачивается пропорция при общем аноде.
Три канала R/G/B смешиваются в цвет — как в скетче analogWrite().
Подгружаем интерактив…
fill_solid: вся лента одним вызовом
#include <FastLED.h> #define LED_PIN 6#define NUM_LEDS 12 CRGB leds[NUM_LEDS]; void setup() { FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS); FastLED.setBrightness(40); fill_solid(leds, NUM_LEDS, CRGB(255, 147, 41)); FastLED.show();} void loop() { // цвет стоит: ночник не мигает и ничего не анимирует}fill_solid(leds, 12, CRGB(255, 147, 41)) принимает три аргумента: куда красим, сколько пикселей и чем. Внутри — самый обычный цикл, тот самый, который вы писали бы руками из урока про циклы: перебрать индексы и присвоить цвет каждому. FastLED просто спрятал его в функцию с говорящим именем — скорость та же, а строка одна и читается сразу. До вызова FastLED.show() заливка живёт только в буфере — это правило из первого урока, и оно не меняется никогда.
Рядом с fill_solid стоит запомнить FastLED.clear(): это тот же fill_solid, только чёрным цветом — буфер обнуляется, и после show() лента гаснет целиком. А вот залить участок ленты — пиксели с четвёртого по одиннадцатый, скажем, — fill_solid не умеет: у функции нет аргумента «с какого индекса начать». Участки красят циклом с границами: for (int i = 4; i < 12; i++) leds[i] = ... Это не недоделка, а честная простота: буфер — обычный массив, любая «умная заливка» под капотом всё равно цикл. Когда граница участка нужна на глазах в коде — цикл даже нагляднее функции.
Маяк выше показывает, как fill_solid, clear и один пиксель работают в связке, а порядок в loop() здесь принципиален: сначала clear (обнулили буфер), потом один пиксель (нарисовали поверх), потом show (вывели кадр целиком). Переставьте clear и show местами — и маяк превратится в красную змею из старых кадров: буфер не чистится, точка не гаснет, а наслаивается. Три задачи на закрепление, все решаются в симуляторах выше за десять минут. Первая: сделайте «светофор» на участке — пиксели с 0 по 5 залейте красным, с 6 по 11 зелёным, всё через циклы с границами. Вторая: плавная «зарядка» — в цикле поднимайте общий уровень заливки от чёрного к зелёному, меняя не setBrightness, а сам цвет: CRGB(0, i * 17, 0) по счётчику. Третья: соберите ту же плавность через общий множитель — заливка зелёным стоит на месте, а setBrightness ходит от 20 до 200 с шагом в loop(); в уроке про ШИМ и яркость мы делали то же с обычным светодиодом, здесь механика перенесётся один в один.
Что дальше: тройки чисел — это ещё не конец удобства. В уроке про HSV-цвета мы уже пробовали CHSV по верхам; тёплый белый, которого я добивался два вечера, там записывается одним числом оттенка 25 при насыщенности около 190 — и подбор троек вам больше не понадобится. Следующий урок раздела как раз про это колесо цвета.
- CRGB — структура из трёх байтов r-g-b по 0–255; 24 бита на пиксель; присваивается любому элементу буфера leds[i]
- Именованные константы CRGB::Red и другие — готовые честные тройки; в симуляторе курса доступен компактный набор из таблицы
- fill_solid(leds, N, цвет) — вся лента одним вызовом; FastLED.clear() — тот же fill_solid чёрным; участки — циклом с границами
- Белый — самый дорогой цвет: до 60 мА на пиксель при яркости 255; тёплый белый (255, 147, 41) экономит по построению — синий кристалл почти выключен
- setBrightness — глобальный множитель на всю ленту; канал b в тройке — локальная ручка оттенка белого
- 1. Сколько байтов занимает один пиксель в буфере CRGB и на что они уходят?
- 2. Что сделает fill_solid(leds, 16, CRGB::Green)?
- 3. Один пиксель залит белым на яркости 255, второй — чистым красным на той же яркости. Кто ест больше тока?
- 4. FastLED.clear() — это то же самое, что…
- 5. Как залить только пиксели с 4-го по 11-й включительно?
Частые вопросы по теме урока
- Сколько байтов занимает один пиксель в буфере CRGB и на что они уходят?
- 24 бита на пиксель — три канала по восемь бит. Ровно столько байтов уходит в провод при каждом FastLED.show(). Три — по одному байту на каналы R, G и B
- Что сделает fill_solid(leds, 16, CRGB::Green)?
- Три аргумента: буфер, сколько пикселей, чем красить. Физически лента поменяет цвет после FastLED.show() — как всегда. Зальёт зелёным все 16 пикселей буфера
- Один пиксель залит белым на яркости 255, второй — чистым красным на той же яркости. Кто ест больше тока?
- Белым горят все три кристалла — до 60 мА, красным один — до 20 мА. Именно поэтому тёплые оттенки белого ещё и экономят питание. Белый — примерно втрое больше
- FastLED.clear() — это то же самое, что…
- clear обнуляет буфер — заливает его чёрным цветом. setBrightness(0) лишь множит яркость на ноль, буфер остаётся заполненным. fill_solid(leds, N, CRGB::Black)
- Как залить только пиксели с 4-го по 11-й включительно?
- У fill_solid нет аргумента «с какого индекса», участки красят обычным циклом с границами. Буфер — обычный массив, и цикл здесь нагляднее. Циклом: for (int i = 4; i < 12; i++) leds[i] = C