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

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

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

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

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

volatile unsigned char pwm_r, pwm_g, pwm_b;

// Прерывание по переполнению Т0
ISR(TIMER0_OVF_vect)
{
static unsigned char pwm_counter;
// Если значение яркости больше значения счетчика
// включаем соответствующий вывод
if(pwm_counter < pwm_r) PORTB |= (1 << PB1);
// Иначе вывод выключен
else PORTB &= ~(1 << PB1);
if(pwm_counter < pwm_g) PORTB |= (1 << PB2);
else PORTB &= ~(1 << PB2);
if(pwm_counter < pwm_b) PORTB |= (1 << PB3);
else PORTB &= ~(1 << PB3);	
// Инкрементируем счетчик
pwm_counter++;
}

// Процедура задержки в микросекундах
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 char time)
{
for(unsigned char a = 0; a < 255; a++)
{
pwm_r = a; // Увеличение
pwm_g = 0;
pwm_b = 0;
delay_ms(time);
}     
for(unsigned char a = 255; a > 0; a--)
{
pwm_r = a; // Уменьшение
pwm_g = 0;
pwm_b = 0;
delay_ms(time);
}
}

// Зеленый цвет
void green (unsigned char time)
{
for(unsigned char a = 0; a < 255; a++)
{
pwm_r = 0;
pwm_g = a;
pwm_b = 0;
delay_ms(time);
}     
for(unsigned char a = 255; a > 0; a--)
{
pwm_r = 0;
pwm_g = a;
pwm_b = 0;
delay_ms(time);
}
}

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

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

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

int main (void) 
{
// Порты ввода/вывода
DDRB = 0xFF; // Порт B выход
PORTB = 0x00;
// Таймер 0
TCCR0 |= (1 << CS00); // Тактирование Т0 без предделителя
TIMSK |= (1 << TOIE0); // Разрешаем прерывание по переполнению Т0

sei(); // Глобально разрешаем прерывания

while(1)
{ 	
red(5); // Включаем эффекты
green(5);		
blue(5);
white(10);
  for(;;) 
  {
  rgb(100);
  }
}
}

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


Архив для статьи "Зажигаем RGB светодиод. Программный ШИМ"
Описание: Файлы проекта для AVR Studio
Размер файла: 26.71 KB Количество загрузок: 2 441 Скачать

Комментарии  

0 #21 maryana 06.03.2015 19:27
уже разобрался
Сообщить модератору
+1 #22 uuu000 26.11.2020 18:56
Можно получить подробное объяснение
функции "Процедура задержки в микросекундах" и "Процедура задержки в миллисекундах"
Для малых значений задержки используем ассемблерные вставки(две
команды по 2 цикла МК) - это я понял.
Но не вижу где используем эти функции.
Что обозначают переменные time_us и
time_ms?
Сообщить модератору
0 #23 AntonChip 27.11.2020 18:34
Значение времени в микросекундах и миллисекундах
Сообщить модератору
0 #24 uuu000 28.11.2020 10:55
Спасибо.С задержками разобрался,тем более
такие функции(или подобные) встречаются
довольно часто.
Сообщить модератору
+1 #25 uuu000 28.11.2020 11:13
Если не трудно,можно подробно объяснить
запись в цикле while(1):
red(5); // Включаем эффекты
green(5);
blue(5);
white(10);
for(;;)
{
rgb(100);
}

Спасибо.
Сообщить модератору
0 #26 uuu000 29.11.2020 04:44
Разобрался самостоятельно. Только остался один вопрос:например ,red(3). "3"-это задержка перед каждой итерацией(если я верно понимаю).В каких единицах эта задержка?
Спасибо.
Сообщить модератору
0 #27 AntonChip 29.11.2020 13:25
Это задержка между сменой скважности ШИМ, в микросекундах
Сообщить модератору
0 #28 uuu000 29.11.2020 14:34
Спасибо.
Сообщить модератору