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

Комментарии 18

Ееее. Ура HSV на светодиодах!
Когда делал лампу настроения, по одной из статей, ужаснулся коду на выбор цвета и количеству условий в RGB. Перешел на HSV и код стал значительно проще.
Я правда не стал все так круто продумывать и сделал Hue-0...360, Sat-0...255, Val-0...255 и арифметика была не целочисленная. Но я по контроллерам не спец и оптимизация там не понадобилась. Заработало и хорошо.
Я когда делал HSV сделал Hue 0..1530 (255 * 6) и получилась целочисленная арифметика. Основная идея была такая: 6 участков показывает рост и спад вторичных цветов, если они будут расти 0..255 и спадать 0..255, то мало того что будут получаться целые числа, так ещё и плавность повысится.

P.S. Я делал с S = 255, V = 255, т. е. менять можно было только оттенок, но переделать не очень сложно.
void set_led_color(unsigned int hue)
{
    // sector specifies which colors are primary and secondary
    unsigned char sector = hue / 0xff;

    // primary color is always full
    const unsigned char primary = 0xff;

    // calculate secondary color value from hue
    unsigned char secondary = abs(sector % 2 * 0xff - hue % 0xff);

    // тут идёт 6 кейсов sector и установка PWM на полученные значения
}
Описанный вами случай подходит и под HSL при L = Lmax/2, S = Smax.

Действительно, при S = 255, V = 255 удобно.

По поводу кода:
Странно, что у вас вместо byte используется unsigned char.
Вместо sector % 2 можно использовать (sector & 1), вместо hue % 255 — byte (hue).

По поводу «переделать несложно»:
На самом деле при этом возникают неприятные эффекты. V — это то значение на которое идёт домножение primary и secondary. Как только оно не 255 — появляется дополнительное деление/умножение в secondary. Более того, если вы начнёте уменьшать S — третья компонента цвета будет расти пропорционально (255-S)*V/255, и это же слагаемое появится и в secondary, а то что там было придётся домножать на S/255. В общем, при любом минимальном понижении S и V такое высокое разрешение по тону станет ненужным. А под конкретную задачу — реализация удачная, не спорю :)

Не берусь сходу дописать код для HSV, но там могут случиться небольшие потери значений при делении.
У HSL есть та же проблема, что и у HSV но в два раза сильнее: в HSL три стороны куба проецируются на конус, а три — на круг, образуя его основание, а у HSL — два конуса. Фактически, у вас две зоны (в окрестностях L = 0 и L = Lmax), где будет много слабо отличающихся друг от друга значений.
TeX-коды в топик включил в порядке эксперимента. Если есть способ делать это удобнее или правильнее — намекните в ПМ.

Что такое ПМ я не знаю, но если уж вы используйте TeX, то желательно соблюдать математические традиции вместо программерского жаргона типа двоеточия для диапазона и звёздочки для умножения.

__attribute__ ((__packed__)) — лишние. Eсли вам нужна оптимизация по размеру, то разумно так и указать это в опциях для компилятора. «Пакование» структур в явном виде применяется в более специфичных случаях (например, когда нужно обеспечить бинарную переносимость структуры в независимости от опций компилятора).

В-третьих, причём тут привязка к AVR и, тем более, Arduino?

Ну это я попридирался просто. Сама идея использования пространства HSV вместо RGB в некоторых случаях разобрана и, надеюсь, защитит многих от изобретения своих велосипедов.
ПМ это личное сообщение — private message.

С математическими традициями у меня проблема — и тройка в дипломе, и с FFT уже месяц разбираюсь, чтобы понять. Но попробую учесть Ваш совет.

__attribute__ ((__packed__)) для RGB_t прописан для совместимости вот с этим кодом — ассемблерной вставкой для time-critical вывода значений на светодиодную ленту (см. также).

Arduino упомянут как самый популярный девайс на хабре, использующий AVR.
Собственно, я не уверен что тот же код будет актуальным для контроллеров на ARM — вряд ли там есть необходимость экономить память, циклы процессора, отказываться от float-point и делений (из того же блога — про скорость деления на AVR).

Arduino упомянут как самый популярный девайс на хабре, использующий AVR [...]

Ваш код — на чистейшем С (не считая __attribute__), поэтому совершенно ни к чему не привязан, да и мир не заканчивается на AVR и ARM. А FPU лишены большинство микроконтроллеров.

__attribute__ ((__packed__)) для RGB_t прописан для совместимости вот с этим кодом [...]

Опять же — какая разница для чего вы его там используете, если в статье к этому привязки нет. Код у вас просто демонстрирует переход от HSV к RGB модели c целочисленной арифметикой.

Короче, зачем искусственно ограничивать общность статьи?
Исправил заголовок топика и убрал packed, спасибо за замечание.
А нельзя ли осветить железную часть проекта? Схему? Фото? И возможно ли собрать это дома? Я так понимаю, что у Arduino три аналоговых вывода, которые усиливаются транзисторами, но я, например, никогда не смогу спроектировать такую схему (с обвязками и разделением по питанию). По этому было бы интересно посмотреть и другую сторону.
Так как электротехник из меня слабый — схем нет, я ничего не монтирую. Проводами соединена Arduino, радиомодуль nRF24L01+, метр ленты на WS2811 и питание.

Фото будет, даже видео, но вряд ли на хабре — светодиодный жонглёрский реквизит тема очень узкая, мне кажется фаер-шоу и похожие искусства вряд ли будут интересны хабровчанам.
Не стоит недооценивать хабр :) Если там будут интересные технические решения, то такие узкоспецифические проекты вызывают еще больший интерес.
Из интересных технических решений осталось использование в качестве альтернативной цветовой модели давно забытых Web-safe colors и градиентов на их основе, они пришлись ко двору :)
Там сразу несколько реализаций. Первые две (_360, _384) используют double и деление, _Binary — только деление, _Adv и _Adv1 — чистые, _Adv2 — снова деление.
Adv и Adv1 можно дооптимизировать по точности, коду и скорости разом, но если вас они устраивают — особой нужды в этом нет :)
А как насчёт цветовой модели YCbCr? Подойдёт ли она для решения вашей задачи? Она более стандартная и используются как в аналоговой части, так и в кодировке цифрового видео. Там преобразования в RGB и обратно намного проще.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории