Для начала напомню как работает ШИМ в устройствах управления: есть определённый промежуток времени, который называется периодом, в течение этого времени включается и отключается нагрузка, чем больше время включения, тем ярче светится диод (быстрее вращается вентилятор, больше напряжение и тд.), это врямя в процентном отношении к периоду называется скважностью, допустим если скважность =10%, а напряжение 12 вольт, то нагрузка будет работать как при подаче 1,2 вольт.
Как это всё работает в RGB: период одинаковый для всех каналов, диоды включаются одновременно, а отключаются в зависимости от требуемого цвета, например если нужен чисто зелёный, то включаем канал G на весь период, остальные каналы не включаем, если нужен оранжевый, то включаем каналы RG, B-канал не включаем и тд.
Теперь о моём алгоритме в микроконтроллере.
Для упрощения программы я пошёл немного иным путём, так как в программе кроме контроля RGB больше ничего нет, я решил по очереди включать-отключать каналы, текущий цвет будет зависеть от времени включения каждого канала как и в обычном ШИМ, сразу задаёмся периодом, пусть это будет 128 (чем меньше период, тем выше частота, но уменьшится количество цветов), далее нужно определиться с цветами, у меня их получилось 94, в это количество нужно вместить весь спектр, у меня получилось с шагом 16, (больше шаг-меньше цветов, и наоборот), далее складываем значения цветов, допустим для стандартного голубого это будет R(0)+G(255)+B(255) = 510-это число принимаем за 100% и далее пропорцией вычисляем значения константы задержки (в данном случае не трудно догадаться что это будет 0-64-64), так как величина константы не может быть равной нулю (кто хоть раз программировал задержку в МК поймёт о чём я говорю) принимаем нулевые значения за 1, так делаем для каждого цвета. Сразу оговорюсь: это не обязательно делать, но если просто так наставить числа, то частота будет постоянно плавать от цвета к цвету в пределах примерно 500-1000 Гц.
Существенный недостаток предложенного способа: невозможность добиться 100% скважности для каждого цвета, максимум 50, поэтому для увеличения яркости придётся подбирать резистор в цепь светодиода с вдвое меньшим сопротивлением (я на своей макетке подключил светодиод вообще без резистора: полёт нормальный).
Далее возникла мысль о кнопочной регулировке яркости, для этого нужно после цикла вкл-выкл каналов RGB добавить временную задержку, при этом получится чем больше задержка, тем меньше яркость и наоборот. Опять же вернёмся к частотам: при максимальной яркости частота в устройстве примерно равна 1800 гц. если же добавлять задержку, то при минимальной яркости частота будет опускаться до 60 гц, если делать большее разрешение для цветов, то будет заметно моргание диодов (проверено: моргает). Так как все действия выполняются в цикле, эта задержка будет влиять на время срабатывания по нажатию кнопок, например при минимальной яркости цвета меняются медленно, а при максимальной яркости — быстро.
Далее на свободную ножку я повесил кнопку ВКЛ-ВЫКЛ, это не полное отключение энергии, а просто гашение всех диодов, при этом устройство работает и при следующем нажатии оно оживает.
Теперь по схеме: 2 ножка-вкл-выкл, 3 ножка- яркость (перебор от максимума к минимуму), 4 ножка — цвет (односторонний перебор всего спектра), 5-7 ножка RGB каналы, 1 ножка — 5 вольт, 8 ножка -масса
Фото работы устройства на макетке, (так как 3-х цветного светодиода под рукой не оказалось, проверял работу на 2-х цветном красно-зелёном)
ДОПОЛНЕНИЕ:
купил кусок RGB ленты для проверки, фото и видео ниже:
Прошивку и схему в протеусе можно скачать тут: http://meandr.org/wp-content/uploads/2013/06/1943_RGB.zip (запись в EPROM пока не реализована, поэтому при включении устройства будет выбрано начальное значение цвета)