Как стать автором
Обновить

Использование цветовых пространств в ATTiny13a для WS2811

Время на прочтение 6 мин
Количество просмотров 18K
image

И вновь приветствую, Хабр!


Моя новая идея посвящена использованию цветовых пространств в микроконтроллерах.
То что моя новость кому-то таковой не покажется, я нисколько не удивлюсь.
Однако я предлагаю метод и его реализацию, подобных которому я не встречал.

Немного вступления, с чего все началось. Совсем недавно закончился год и в наследство от него у меня осталось около 300 светодиодов ws2811. Почему-то руки до них так и не доходили, но после празднования нового года у родственников я заметил, что у тётки стояла маленькая сувенирная ёлочка из стекла, которую она очень любит. Но она в этот раз совсем не сверкала и не искрилась по весьма банальной причине… сели батарейки. Вспомнив про свой набор светодиодов, пообещал сделать маленькую гирлянду для этой ёлочки, чтобы устранить эти недостатки раз и навсегда и сделать еще одного близкого мне человека хоть немного счастливее.

Разработка вертится в голове, постепенно ускоряясь, иногда превращаясь в вихрь мыслей, но до этих дней с места так и не сдвинулась. Останавливало то, что все те идеи, которые касались программы эффектов и их переключений, выглядели в голове очень громоздкими и страшно неудобными, при реализации их в цветовом пространстве RGB, к тому же я никак не мог из-за этого определиться, какой контроллер использовать. Но благодаря моему небольшому опыту работы дизайнером, я имею знания и о других пространствах, что натолкнуло меня на мысли о HSL и HSV. Изобретать новое смысла не было, реализаций полно нужно, лишь поискать… но я так и не нашел. Нет, я конечно нашел много интересных решений, и многие из них были Вашими, представленными прямо здесь, на Хабре, и за что я всем Вам бесконечно благодарен, Вы дали пищу для ума.

В итоге было решено остановиться на HSL, исключив из него одну компоненту S (Saturation), оставив ее константной (так как в реализации ЦДУ, этот параметр лишний), а контроллер решил использовать ATMega8U.

Набросав код и испытав прошивку, я понял что чего-то не хватает. И не хватило мне маленького несоответствия реалу.
Каждый охотник желает знать… И вновь я возвращаюсь к этому вопросу, и вновь осознаю, что нет его…
Нет оранжевого цвета в природе, как ни крути, он всего лишь оттенок.

Это и стало корнем и стержнем моей идеи, благодаря чему я полностью переписал код и придумал метод использования компактного описания цветового пространства, причем это уже совсем не HSL, HSV и не RGB, потому что я расширил диапазон оранжевого и вынес его в отдельный пространственный сектор.

Теперь только по-сути


Пространство можно представить как поверхность цилиндра в случае если оно замкнуто, с расположенными в углах, смещенными на 60 градусов базовыми цветами, между которыми заполнено градиентными переходами от одного базового цвета к другому:

image

Где высота цилиндра — это яркость, которая так же является составляющей градиента оттенков.
То же самое пространство представляет прямоугольник со сторонами «A x B», где «А» это угол определяющий базовый цвет и его оттенок, а «B» — яркость, в случае если пространство не замкнуто или развернуто из цилиндра.

Для поставленной задачи я решил использовать квадрат со стороной 256 х 256, тем самым уложившись в тип байт, где для угла, значения изменяются в пределах 0..255 (байт), а яркость: -127..127 (знаковый байт), благодаря этому получил возможность использования 8-ми базовых цветов и 32 градаций оттенков для каждого.

Пространство описывается как массив с RGB — компонентами базовых цветов, а градиенты оттенков рассчитываются на лету.
Пример описания:

{0,128,0}, {64,128,0}, {128,128,0}, {128,0,0}, {128,0,128}, {0,0,128}, {0,128,128}, {0,128,0}

здесь описана последовательность базовых цветов, назовем ее просто — радуга, где порядок компонент изменен согласно даташиту ws2811 (GRB), а последний — красный цвет, служит для замыкания пространства, выглядит это так:

image

Теперь, если взять некоторый индекс цвета, например 183, то можно сделать его отображение в пространство RGB таким образом:
Индекс базового цвета = 183 / 32 = 5 (синий, или {0,0,128})
Смещение оттенка = 183 % 32 = 23
Теперь вычисляем разницу между компонентами полученного базового цвета ({0,0,128}) и следующего за ним {0,128,128}, чтобы вычислить приращение (назовем его дельтой):
dG = 0 - 0 = 0,   dR = 128 - 0 = 128,   dB = 128 - 128 = 0;

Так как между цветами 32 градации, необходимо выполнить разбиение разности компонент:
dG= 0 / 32 = 0,   dR= 128 / 32 = 4,   dB= 0 / 32 = 0;

Теперь необходимо полученную дельту домножить на смещение оттенка и прибавить к компонентам текущего базового цвета ({0,0,128}):
G = 0 + 0 * 23 = 0,   R = 0 + 4 * 23 = 92,     B = 128 + 0 * 23 = 128;

Получили {0,92,128}, к которому теперь можно прибавить яркость, например 50: {50,142,178} — искомый цвет.

Как видно из примера, ничего сложного нет. В случае если дельта принимает отрицательное значение, то смещение оттенка при умножении даёт отрицательное дополнение, которое в сумме даст разность с конечной компонентой, это произойдет в случае, когда компонента градиента идет на спад.

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

Таким образом полученное пространство дает возможность использования 256 * 256 = 65536 оттенков.

Весь описанный метод был оптимизирован, устранены все умножения и деления, и приведен под упрощенную быструю математику, позволяет легко переписать его на ассемблер (лично меня скорость абсолютно устраивает: 200 ns между расчетами компонент для 7-и светодиодов), если нужна оптимизация для уменьшения размера кода.
В результате, первоначальное решение об использовании ATMega8u было отменено в пользу тиньки, так как полученная прошивка заняла меньше половины килобайта.

Нет, я не жлоб, я просто ленивый.

Итак, код ниже, выполняет инициализации, и содержит функцию вывода данных на линию ws2811:

image

А это код основного цикла и функция преобразования индекса пространства в цветовые составляющие с примером использования:

image

А вот видео с демонстрацией работы (правда цвета далеки от реальности):


Описывать подробней комментариев в тексте смысла нет, сам метод уже описан выше. Если есть вопросы, задавайте.

Ну вот, собственно, и все, что я хотел рассказать.

… шутка — не все!


image

Давайте теперь на секунду представим, как можно использовать данный метод. Как вам, например, такое пространство, которое показано на этой картинке:

Правильно! Можно описывать разные цвета и градиенты между ними. И кто вначале описания решил что метод не позволяет использовать оттенки серого — не прав.

В заключении — самое вкусное


Массив, описывающий в памяти пространство, занимает 32 байта (из-за выравнивания), который хранится в программной памяти. Если создать несколько таких описаний пространств, и переключаться между ними на ходу, переключая указатель на массив, то можно выбирать текущее пространство для каждого нового светодиода в очереди, а так же позволяет расширить число градаций между оттенками. И если слегка модифицировать код, и увеличить число ступеней в описании компонент до 8-ми, то 32*8 даст 256 (в моем коде 3 ступени), то использование семи массивов (0..255 красный, желтый, зеленый, голубой, синий, фиолетовый, белый) дают комбинацию в 16m оттенков «одновременно на экране»! При использовании 224 байт прошивки для хранения. А если еще немного по-потеть и чуть переписать код, то можно уложиться и в 96 байт с тем же результатом.

Плюс, благодаря оптимизации и полученной скорости обработки, можно использовать так называемый метод дизеринга ((англ. dither от старо-английского didderen — дрожать) С помощью чего, можно добиться еще большего числа оттенков (только задумайтесь: 512*512*512=134.217.728). Так же это позволяет создавать замыкания пространств друг на друга, чтобы устранить или сделать невидимыми эффекты перехода. В общем, все предложенное может быть модифицировано как Вашей душе угодно, на Ваш вкус и цвет, а может использоваться как есть, и удовольствие я Вам гарантирую!

26.02.2015: Предлагаю для скачивания исходный код в безвозмездное пользование.

27.02.2015: Доступна обновленная версия кода v1.2
Изменения такие:
1. Базовый цвет кодируется битами одного байта: 0bxxGGRRBB, массив уменьшился до 8-и байт.
2. Изменена функция преобразования в соответствии п.1., код стал немного больше (20-30 байт)
В перспективе планирую еще изменения, кому интересно — не пропустите!

28.02.2015: Последнее обновление кода до версии v2.0
Изменения:
1. Добавлена работа с подпространствами, введено пространство 8x8 (раздельный выбор 65536 оттенков для подпространств с переключением)
image

2. Добавлен пример выбора цветового подпространства (в демонстрационном примере идет переключение на следующее подпространство, при достижении нижнего порога яркости)
image
3. Размер кода еще вырос до 626 байт (64 байт — само пространство + 16 байт на указатели, итого — 80 байт, остальное — код примера: 188 байт). Таким образом доступно более 500 байт дополнительного кода для организации программы эффектов.
4. Немного оптимизирован код.
5. Профилирование не выполнялось.

ИТОГ: 5 свободных ног тиньки, позволяют применить несколько раздельных каналов для независимого отображения на линиях ws2811 цветовых эффектов, и реализовать управление ими через аппаратный ввод, либо в автоматическом режиме. Реализованный буфер (14 светодиодов) позволяет использовать линию светодиодов кратную этому числу, и передавать данные в следующую секцию, повтором передачи буфера.

Больше обновлений в этом направлении не будет, будем считать алгоритм законченным, хотя идеи кажутся неисчерпаемыми. Предлагаю Вам самостоятельно развивать разработки в этом направлении.
Например: можно реализовать плавную смену цветовых подпространств (телепортация), изменить алгоритм управления яркостью на корректный, ввести параметр насыщенности цвета, и многое другое, чего здесь не хватает.
Удачных всем изысков и свершений, с наступающей весной!

С нетерпением жду ваших комментариев, критики, вопросов и советов.
Спасибо за внимание, до новых встреч!

Использование в коммерческих проектах, перепродажа исходного кода, использование с целью наживы и любых корыстных целях, запрещено. Исходные тексты распространяются бесплатно как есть, в случае использования на других сайтах, либо в других источниках, указание автора и уведомление о размещении — обязательно.
Теги:
Хабы:
+23
Комментарии 8
Комментарии Комментарии 8

Публикации

Истории

Работа

Программист C++
121 вакансия
QT разработчик
13 вакансий

Ближайшие события

Московский туристический хакатон
Дата 23 марта – 7 апреля
Место
Москва Онлайн
Геймтон «DatsEdenSpace» от DatsTeam
Дата 5 – 6 апреля
Время 17:00 – 20:00
Место
Онлайн