Печать

Зажигаем RGB светодиод. Программный ШИМ

Автор: AntonChip Опубликовано . Опубликовано в Программирование на Си

Рейтинг:   / 12
ПлохоОтлично 

Для отображения всей палитры видимых оттенков теоретически достаточно иметь три цвета. Это — так называемый RGB-синтез (Red — красный, Green — зеленый, Blue — синий). Но в реальности трех цветов бывает недостаточно. Смешивание цветов может происходить одним из трех способов. Светодиоды могут раздельно располагаться в светильнике, а цвета смешиваются уже непосредственно на освещаемом объекте. Преимущества такого подхода — простота конструкции и высокая светоотдача. Недостаток — наличие нескольких разноцветных теней для объектов, расположенных близко к светильнику. Более сложный вариант — оптическая система, смешивающая лучи от разных светодиодов. Наконец, выпускаются специальные RGB-светодиоды, объединяющие в одном корпусе три кристалла разных цветов. Использование RGB-светодиодов позволяет создать очень тонкий осветительный прибор, дающий равномерный свет без заметных зон затенения.

RGB светодиод в выводном корпусе

Схема управления RGB светодиодом

Аноды RGB светодиода подключаем  к линиям 1,2,3 порта В, катоды соединяем с минусом. Чтобы получить разнообразные палитры цвета на аноды будем подавать ШИМ сигнал в определенной последовательности. В этом примере мы специально используем программный ШИМ, хотя на Atmega8 можно без проблем получить аппаратный ШИМ на 3 канала. Программный ШИМ можно использовать в случаях нехватки таймеров/счетчиков и по другим причинам. Для генерации ШИМ определенной частоты используем прерывание по переполнению 8-ми битного таймера Т0(TIMER0_OVF_vect). Так как предделитель не используем частота переполнения таймера будет равна 31250Гц. А если переменная "pwm_counter" считает до 163, то частота ШИМ будет равна 190 Hz. В обработчике прерываний исходя из значений в переменных pwm_r, pwm_g, pwm_b переключаются ножки порта В. Цветовые эффекты настраиваются с помощью функций, где задается время свечения светодиода. В тестовой программе сначала загораются красный, зеленый, синий, белый цвета, а потом начинается цикл с переходами цвета.

// Управление RGB светодиодом. Программный ШИМ
#include <avr/interrupt.h>
#include <avr/io.h>

volatile char pwm_counter,pwm_r,pwm_g,pwm_b;

// Прерывание по переполнению Т0
ISR (TIMER0_OVF_vect)
{
if (pwm_counter++ > 163) 
{
PORTB = 0x00;
pwm_counter = 0;
}
if (pwm_counter > pwm_r) PORTB |= (1 << PB1);
if (pwm_counter > pwm_g) PORTB |= (1 << PB2);
if (pwm_counter > pwm_b) PORTB |= (1 << PB3);
}

// Процедура задержки в микросекундах
void delay_us(unsigned char time_us)
{ register unsigned char i;
for(i = 0; i < time_us; i++)	// 4 цикла
{ asm (" PUSH  R0 ");		// 2 цикла
asm (" POP   R0 ");		// 2 цикла
		// 8 циклов = 1 us для 8MHz
}
}

// Процедура задержки в миллисекундах
void delay_ms(unsigned int time_ms)
{ register unsigned int i;
for(i = 0; i < time_ms; i++)
{ delay_us(250);
delay_us(250);
delay_us(250);
delay_us(250);
}
}

// Красный цвет
void red (unsigned int time)
{
 for (char a = 0; a < 165; a++)
{
pwm_r = 164 - a; //увеличение
pwm_g = 164;
pwm_b = 164;
delay_ms(time);
}     
for (char a = 0; a < 165; a++)
{
pwm_r = a; //уменьшение
pwm_g = 164;
pwm_b = 164;
delay_ms(time);
}
}
// Зеленый цвет
void green (unsigned int time)
{
for (char a = 0; a < 165; a++)
{
pwm_r = 164;
pwm_g = 164 - a;
pwm_b = 164;
delay_ms(time);
}     
        
for (char a = 0; a < 165; a++)
{
pwm_r = 164;
pwm_g = a;
pwm_b = 164;
delay_ms(time);
}
}

// Синий цвет
void blue (unsigned int time)
{
for (char a = 0; a < 165; a++)
{
pwm_r = 164;
pwm_g = 164;
pwm_b = 164 - a; 
delay_ms(time);
}     
for (char a = 0; a < 165; a++)
{
pwm_r = 164;
pwm_g = 164;
pwm_b = a; 
delay_ms(time);
}
}

// Белый цвет
void white (unsigned int time)
{
for (char a = 0; a < 165; a++)
{
pwm_r = 164 - a;
pwm_g = 164 - a;
pwm_b = 164 - a;
delay_ms(time);
}     
for (char a = 0; a < 165; a++)
{
pwm_r = a;
pwm_g = a;
pwm_b = a; 
delay_ms(time);
}
}

// Переход цветa
void rgb (unsigned int time)
{
for (char a = 0; a < 165; a++)
{
pwm_r = a;
pwm_b = 164 - a;
delay_ms(time);
}
for (char a = 0; a < 165; a++)
{
pwm_b = a;
pwm_g = 164 - a;
delay_ms(time);
}
		
for (char a = 0; a < 165; a++)
{
pwm_g = a;
pwm_r = 164 - a;
delay_ms(time);
}
}

int main (void) 
{
DDRB |= (1 << PB3)|(1 << PB2)|(1 << PB1); // PB3,2,1 - выходы
TCCR0 |= (1 << CS00); // Без предделителя
TIMSK |= (1 << TOIE0); // Разрешение прерывания по переаолнению Т0
sei();// Глобальное разрешение прерываний

while(1)
{ 	
red(5);
green(5);		
blue(5);
white(10);
for(;;) 
{rgb(100);}
}
}

Обсуждение статьи на форуме

Файлы:
Файлы проекта для AVR Studio
Дата 23.10.2011 Размер файла 26.71 KB Закачек 1648

Комментарии  

0 #21 AntonChip 08.11.2012 21:26
Цитирую DIMAN.:
Здравствуйте!
А как бы отключить прерывание,на время выполнение другой программы,в вечном цикле.

Прерывание отключается командой cli();
Сообщить модератору
0 #22 DIMAN. 10.11.2012 01:54
Цитирую admin:
Цитирую DIMAN.:
Здравствуйте!
А как бы отключить прерывание,на время выполнение другой программы,в вечном цикле.

Прерывание отключается командой cli();


Спасибо!
Сообщить модератору
0 #23 skullhead 05.12.2013 20:57
Здравствуйте! В статье указана частота ШИМ 31250Гц. Я правильно понимаю,что это максимальная частота,то есть частота на максимальной яркости.На минимальной яркости это значение еще нужно разделить на 165?В итоге минимальная частота выходит около 190Гц.
Сообщить модератору
0 #24 Aleksey 05.12.2013 21:59
Цитирую skullhead:
Здравствуйте! В статье указана частота ШИМ 31250Гц. Я правильно понимаю,что это максимальная частота,то есть частота на максимальной яркости.На минимальной яркости это значение еще нужно разделить на 165?В итоге минимальная частота выходит около 190Гц.

Частота ШИМ не меняется!!! Меняется скважность ШИМ
Сообщить модератору
0 #25 skullhead 05.12.2013 23:08
Цитирую Aleksey:
Цитирую skullhead:
Здравствуйте! В статье указана частота ШИМ 31250Гц. Я правильно понимаю,что это максимальная частота,то есть частота на максимальной яркости.На минимальной яркости это значение еще нужно разделить на 165?В итоге минимальная частота выходит около 190Гц.

Частота ШИМ не меняется!!! Меняется скважность ШИМ


как это не меняется? если pwm_r=100,напри мер,то должно пройти 100 прерываний прежде чем pwm_counter превысит pwm_r=100 и контроллер дернет ногой.так?
Сообщить модератору
0 #26 skullhead 05.12.2013 23:16
Цитирую Aleksey:

Частота ШИМ не меняется!!! Меняется скважность ШИМ

Здесь получается как бы два таймера,один вложен в другой.переключ ение не происходит каждое прерывание от аппаратного таймера,а только через определенное число прерываний,зави сящее от переменных pwm_r и т.д.
Сообщить модератору
0 #27 Aleksey 05.12.2013 23:58
Так оно и есть. Частота ШИМ будет равна 8000000Hz/255/1 63 = 192Hz. Админ исправьте
Сообщить модератору
0 #28 mijgan 25.12.2013 19:16
Здравствуйте. Подскажите, пожалуйста: Хочу подключить к данной схеме кнопку, при нажатии на которую, отключается изменение цвета и светодиоды выдают текущий цвет. Пробовал с внешним прерыванием, но у меня (в протеусе) меняется частота ШИм (понимаю, что делаю что то не так, а вот что... - в программировани и я пока ноль). В идеале бы записать значение цвета в EEPROM, но для начала разобраться бы в этом..
Сообщить модератору
0 #29 Юлик 26.07.2014 18:09
На видео точно такой же код, как в программе? В моем протеусе каждый из трех светодиодов раз по 15 мигает с самого начала запуска, а на видео только под одному
Сообщить модератору
0 #30 AntonChip 26.07.2014 21:30
Цитирую Юлик:
На видео точно такой же код, как в программе? В моем протеусе каждый из трех светодиодов раз по 15 мигает с самого начала запуска, а на видео только под одному

Протеус не может возпроизвести ШИМ на светодиоде, вот он и мигает
Сообщить модератору
0 #31 maryana 04.03.2015 23:41
не могу скомпилировать данный код - пишет expected expression before '
Сообщить модератору
0 #32 maryana 06.03.2015 19:27
уже разобрался
Сообщить модератору

Рекомендуем посмотреть