Продолжаем осваивать ШИМ, на этот раз для управления цветом RGB светодиода.
По сути, RGB светодиод совмещает в себе три обычных светодиода — красный, зеленый и синий.
Соответственно у RGB светодиода 4 ножки: для управления каждым из цветов используется по одной ножке и одна общая (обычно самая длинная). Общим может быть как катод(-), так и анод(+). На схеме приведен пример, для схемы с общим анодом.
Примечательно то, что смешивая эти 3 цвета можно получить практически любой другой цвет. Если зажечь все 3 светодиода одновременно, получится белый цвет.
Теперь о реализации, мне достался светодиод с общим катодом, номинальный ток, которого по даташиту составлял 20мА. Однако, есть небольшой нюанс, у каждого цвета свой порог зажигания. Например, у красного светодиода, 20мА соответствовало напряжению 2.1В, зеленому и синему — напряжение 3.2В. В целом ножка микроконтроллера должна выдерживать такой ток, поэтому можно смело подключать через токоограничивающие резисторы к микроконтроллеру.
[spoiler]
Я же использовал pnp транзисторы, однако эту идею никому не навязываю.
[/spoiler]
У Atmega8 есть 3 канала ШИМ: два канала на таймере1(ножки PB.1 — OCR1A, PB.2 — OCR1B) и один таймере2(ножка PB.3 — OCR2). Регулируя заполнение ШИМ, мы регулируем напряжение на светодиоде, соответственно его яркость.
Создаем новый проект, настраиваем таймер2.
Так как OCR2 8-битный, а OCR1 10-битный, то максимальное значение OCR2=0хFF(255), а OCR1A/B=0х3FF(1023), т.е. в 4 раза больше. Учитываем эту особенность, поэтому чтобы каналы регулировались одинаково, настраиваем частоту таймера в 4 раза больше. Соответственно, максимальная яркость для OCR2 будет при 0xFF, а для OCR1 при 0x3FF.
Настраиваем ножки PB1-PB3 как выход. В основной цикл программы дописываем код, который плавно зажигает красный от 0 до 255, а затем плавно тушит его от 255 до 0.
while(OCR2<0xFF) { OCR2++; delay_ms(10); } while(OCR2>0x00) { OCR2--; delay_ms(10); } |
Аналогично для зеленого/синего
while(OCR1A<0x3FF) { OCR1A++; delay_ms(2); } while(OCR1A>0x00) { OCR1A--; delay_ms(2); } |
Результат:
Если нужно получить, некоторый определенный цвет, например пурпурный, открываем какой нибудь графический редактор, например Paint.net заходим в палитру нажимаем на понравившийся цвет, справа, где написано RGB отобразятся его числовые значения R=255, B=220.
Канал R у меня на OCR2, поэтому смело в OCR2 записываем 0xFF(255), канал B на OCR1A, но т.к. максимальное значение 1023, то по пропорции пересчитываем:
(220*1023)/255=882 вот его смело пихаем в OCR1A, результат довольно таки похож:
Здравствуйте,скажите пожалуста , а как сделать так чтоб совместить термометр и rgb вместе? если не хватает шим,ведь в вашем терм он тоже работает на шим и при использовании приходится выбирать между.хотел бы сделать термометр на rgb чтоб он показывал темп и светом rgb под определенную темп.
помогите если можете начинающему.
Термометр это то что измеряет, а ШИМ то что выдает напряжение, как бы вещи не связанные. Хотите совместить — легко, берете урок 12, получаете температуру, связываете ее с каналом RGB — как? Вопрос творческого подхода, например теплее — увеличиваете канал R, красный, уменьшаете синий. Холоднее — наоборот.
Скажите пожалуста а как это сделать?просто у вас в уроке обработка поджика разряда сегмента стоит в обработке под таймером , а под этими т.е. даже все свободные заняты шим для ргб , а как тогда обрабатывать поджиг разряда,просто хотел бы чтоб он работал на 7segа а не на lcd или так не получится?
Семисегментники можно подключать через сдвиговый регистр, либо использовать программный ШИМ, тогда вся обработка будет висеть на 1-2 таймерах.
admin, глянь пожалуйста, это работоспособно?
while (1)
{
//Ставим S0 и S1 в высокий уровень и кликаем. На выходе Q0-Q7 у нас фиксируется необходимый нам байт.
S1=1;
CLK=1;
CLK=0;
S1=0;
//Пропускаем пустые
CLK=1;
CLK=0;
CLK=1;
CLK=0;
//Читаем состояние ноги D5, если там 0, убавляем.
if((PINB.0==0)&&(B>0x00))
{
B=B-0x04;
}
//Кликаем
CLK=1;
CLK=0;
//Читаем состояние ноги D4, если там 0, прибавляем.
if((PINB.0==0)&&(B0x000))
{
G=G-0x010;
}
//Кликаем
CLK=1;
CLK=0;
//Читаем состояние ноги D2, если там 0, прибавляем.
if((Button==0)&&(G0x000))
{
R=R-0x010;
}
//Кликаем
CLK=1;
CLK=0;
//Читаем состояние ноги D0, если там 0, прибавляем.
if((Button==0)&&(R<0x3FF))
{
R=R+0x010;
}
}