Комментарии 18
Ееее. Ура HSV на светодиодах!
Когда делал лампу настроения, по одной из статей, ужаснулся коду на выбор цвета и количеству условий в RGB. Перешел на HSV и код стал значительно проще.
Я правда не стал все так круто продумывать и сделал Hue-0...360, Sat-0...255, Val-0...255 и арифметика была не целочисленная. Но я по контроллерам не спец и оптимизация там не понадобилась. Заработало и хорошо.
Когда делал лампу настроения, по одной из статей, ужаснулся коду на выбор цвета и количеству условий в 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, т. е. менять можно было только оттенок, но переделать не очень сложно.
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, но там могут случиться небольшие потери значений при делении.
Действительно, при 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 однозначно привет однополчанам! Hue вы интересно считаете.
TeX-коды в топик включил в порядке эксперимента. Если есть способ делать это удобнее или правильнее — намекните в ПМ.
Что такое ПМ я не знаю, но если уж вы используйте TeX, то желательно соблюдать математические традиции вместо программерского жаргона типа двоеточия для диапазона и звёздочки для умножения.
__attribute__ ((__packed__))
— лишние. Eсли вам нужна оптимизация по размеру, то разумно так и указать это в опциях для компилятора. «Пакование» структур в явном виде применяется в более специфичных случаях (например, когда нужно обеспечить бинарную переносимость структуры в независимости от опций компилятора).В-третьих, причём тут привязка к AVR и, тем более, Arduino?
Ну это я попридирался просто. Сама идея использования пространства HSV вместо RGB в некоторых случаях разобрана и, надеюсь, защитит многих от изобретения своих велосипедов.
ПМ это личное сообщение — private message.
С математическими традициями у меня проблема — и тройка в дипломе, и с FFT уже месяц разбираюсь, чтобы понять. Но попробую учесть Ваш совет.
__attribute__ ((__packed__)) для RGB_t прописан для совместимости вот с этим кодом — ассемблерной вставкой для time-critical вывода значений на светодиодную ленту (см. также).
Arduino упомянут как самый популярный девайс на хабре, использующий AVR.
Собственно, я не уверен что тот же код будет актуальным для контроллеров на ARM — вряд ли там есть необходимость экономить память, циклы процессора, отказываться от float-point и делений (из того же блога — про скорость деления на AVR).
С математическими традициями у меня проблема — и тройка в дипломе, и с 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 целочисленной арифметикой.
Короче, зачем искусственно ограничивать общность статьи?
А нельзя ли осветить железную часть проекта? Схему? Фото? И возможно ли собрать это дома? Я так понимаю, что у Arduino три аналоговых вывода, которые усиливаются транзисторами, но я, например, никогда не смогу спроектировать такую схему (с обвязками и разделением по питанию). По этому было бы интересно посмотреть и другую сторону.
Так как электротехник из меня слабый — схем нет, я ничего не монтирую. Проводами соединена Arduino, радиомодуль nRF24L01+, метр ленты на WS2811 и питание.
Фото будет, даже видео, но вряд ли на хабре — светодиодный жонглёрский реквизит тема очень узкая, мне кажется фаер-шоу и похожие искусства вряд ли будут интересны хабровчанам.
Фото будет, даже видео, но вряд ли на хабре — светодиодный жонглёрский реквизит тема очень узкая, мне кажется фаер-шоу и похожие искусства вряд ли будут интересны хабровчанам.
Не стоит недооценивать хабр :) Если там будут интересные технические решения, то такие узкоспецифические проекты вызывают еще больший интерес.
Там сразу несколько реализаций. Первые две (_360, _384) используют double и деление, _Binary — только деление, _Adv и _Adv1 — чистые, _Adv2 — снова деление.
Adv и Adv1 можно дооптимизировать по точности, коду и скорости разом, но если вас они устраивают — особой нужды в этом нет :)
Adv и Adv1 можно дооптимизировать по точности, коду и скорости разом, но если вас они устраивают — особой нужды в этом нет :)
А как насчёт цветовой модели YCbCr? Подойдёт ли она для решения вашей задачи? Она более стандартная и используются как в аналоговой части, так и в кодировке цифрового видео. Там преобразования в RGB и обратно намного проще.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Оптимизация преобразования HSV в RGB для микроконтроллеров