Трехцветный RGB светодиод и ШИМ(PWM) на микроконтроллере ATtiny2313

Очень захотел поиграться с RGB светодиодом. Интересно было получение разных оттенков при помощи комбинации трех цветов: красного, зеленого и синего.

Алгоритм контроллера RGB светодиода:
Был разработан алгоритм, по которому микроконтроллер осуществлял плавное зажигание и гашение трех цветов таким образом, чтобы охватить полностью все оттенки от красного до синего. На графике я хочу показать принцип, по которому осуществляется работа управляющей программы. Программа была реализована на микроконтроллере ATtiny2313.

Временной график цветов RGB

На графике отображена зависимость яркости свечения того или иного из цветов RGB в определенный момент времени.
Таким образом мы получил плавный перелив от красного к зеленому и потом к синему, и так по кругу.

Как то раз на youtube увидел ролик, про трехцветную RGB подсветку LCD(ЖКИ) мониторчика. Очень понравилось, не плохая идея подумал Я. Вот кстати видео:

Принципиальная схема приведена на рис. 1
RGB PWM на ATtiny2313
Рис. 1

RGB светодиод на схеме показан как три отдельных светодиода, номинал ограничивающих резисторов 470 Ом.

  1. #include <avr/io.h>//подключаем библиотеку ввода/вывода
  2.  
  3. #define nop() {asm("nop");}//функция необходимая для реализации задержки
  4.  
  5. unsigned int i,p,pp,c,buf,ms,x;//перечисление переменных
  6.  
  7. // функция задержки
  8. void delay_ms(int ms)
  9. {
  10. for (x=ms;x>0;x--) nop();
  11. }
  12.  
  13. // функция включения красного светодиода
  14. void ledon0(int ms)
  15. {
  16. PORTD &= ~_BV(PD0); delay_ms(ms);
  17. }
  18.  
  19. // функция включения зеленого светодиода
  20. void ledon1(int ms)
  21. {
  22. PORTD &= ~_BV(PD1); delay_ms(ms);
  23. }
  24.  
  25. // функция включения синего светодиода
  26. void ledon2(int ms)
  27. {
  28. PORTD &= ~_BV(PD2); delay_ms(ms);
  29. }
  30.  
  31. // функция выключения красного светодиода
  32. void ledoff0(int ms)
  33. {
  34. PORTD |= _BV(PD0); delay_ms(ms);
  35. }
  36.  
  37. // функция выключения зеленого светодиода
  38. void ledoff1(int ms)
  39. {
  40. PORTD |= _BV(PD1); delay_ms(ms);
  41. }
  42.  
  43. // функция выключения синего светодиода
  44. void ledoff2(int ms)
  45. {
  46. PORTD |= _BV(PD2); delay_ms(ms);
  47. }
  48.  
  49. int main( void ) //главная программа
  50. {
  51. //конфигурирование на вывод порта D
  52. DDRD |= _BV(PD0);//конфигурирование битов
  53. DDRD |= _BV(PD1);//PD0, PD1 и PD2
  54. DDRD |= _BV(PD2);//на выход
  55.  
  56. PORTD = 0xFF; //включаем подтягивающие резисторы
  57.  
  58. pp=1000; //задаем скорость зажигания /гашения
  59.  
  60. for(;;) //бесконечный цикл
  61. {
  62. //Зажигаем красный светодиод
  63. PORTD &= ~_BV(PD0);
  64.  
  65. //плавное зажигание зеленого светодиода
  66. for (i = 20; i < pp; i++)
  67. {
  68. p=pp-i; ledon1(i); ledoff1(p);
  69. }
  70. //Зеленый светодиод остается гореть
  71. PORTD &= ~_BV(PD1);
  72.  
  73. //плавное гашение красного светодиода
  74. for (i = 20; i < pp; i++)
  75. {
  76. p=pp-i; ledon0(p); ledoff0(i);
  77. }
  78.  
  79. //Зеленый светодиод остается гореть
  80. PORTD &= ~_BV(PD1);
  81.  
  82. //плавное зажигание синего светодиода
  83. for (i = 20; i < pp; i++)
  84. {
  85. p=pp-i; ledon2(i); ledoff2(p);
  86. }
  87.  
  88. //Синий светодиод продолжает гореть
  89. PORTD &= ~_BV(PD2);
  90.  
  91. //Плавное гашение зеленого светодиода
  92. for (i = 20; i < pp; i++)
  93. {
  94. p=pp-i; ledon1(p); ledoff1(i);
  95. }
  96.  
  97. //Синий светодиод продолжает гореть
  98. PORTD &= ~_BV(PD2);
  99.  
  100. //постепенное зажигание красного светодиода
  101. for (i = 20; i < pp; i++)
  102. {
  103. p=pp-i; ledon0(i); ledoff0(p);
  104. }
  105.  
  106. //Красный светодиод продолжает гореть
  107. PORTD &= ~_BV(PD0);
  108.  
  109. //Плавно тушим синий светодиод
  110. for (i = 20; i < pp; i++)
  111. {
  112. p=pp-i; ledon2(p); ledoff2(i);
  113. }
  114. }
  115. }

В данной программе реализована программная ШИМ. Все этапы алгоритма работы хорошо прослеживаются, код простой и прост для понимания.

В данном цикле - for (i = 20; i < pp; i++)
начальное число 20 выбрано по причине того, что напряжение на светодиоде должно достигнуть определенного уровня, чтобы свечение светодиода стало заметным.

HEX файл прошивки RGB контроллера.

Видео работы данной программы:

//конфигурирование на вывод

//конфигурирование на вывод порта D
DDRD |= _BV(PD0);//конфигурирование битов
DDRD |= _BV(PD1);//PD0, PD1 и PD2
DDRD |= _BV(PD2);//на выход

написано на выход, а в схеме на вход

Если стоит светодиодо то

Если стоит светодиодо то какой может быть вход???

Всё это, конечно, круто, но

Всё это, конечно, круто, но одновременно три светодиода таких образом не зажечь на разных уровнях яркости, чтобы получить промежуточные цвета, будут мерцать. Есть ли какие-то мысли, как это можно организовать при помощи программного шима?

Писать на асме компактный код

Писать на асме компактный код и повышать частоту МК.

RGB-драйвер на Тини13

У меня на Тиньке 13 RGB пашет как часики, цвета меняются плавно, частота программного ШИМа 2 кГц )) ШИМ задается по прерываниям с таймера через каждые 40 тактов. и всё это занимает 446 байт ! меньше половины флеша )) Так что Асм рулит однозначно ! )) И вовсе не неделю пишется это всё ) пара вечеров, не спорю что чуть дольше чем на Си, но результат на лице так сказать )
В остальные 500 байт и три свободные ножки можно впихнуть программный UART для руления цветом )

я тут маленько оптимизировал

я тут маленько оптимизировал пример, т.к. память надо экономить в процике, а то я на два RGB диода не мог сделать прошивку - она не влазила в память МК.

  1. #include <avr/io.h>//подключаем библиотеку ввода/вывода
  2. #define nop() {asm("nop");}//функция необходимая для реализации задержки
  3.  
  4. unsigned int i,p,pp,c,buf,ms,x;//перечисление переменных
  5. // функция задержки
  6. void delay_ms(int ms)
  7. {for (x=ms;x>0;x--) nop (); }
  8.  
  9. // функция ШИМ светодиода
  10. void led0(int led, int i, int p) //где led - адрес светодиода, i - время включения светодиода
  11. //p - время выключения
  12. { PORTD &= ~_BV(PD0); delay_ms(i);
  13. PORTD |= _BV(led); delay_ms(p);}
  14.  
  15. int main( void ) //главная программа
  16. {
  17. //конфигурирование на вывод порта D
  18. DDRD |= _BV(PD0);//конфигурирование битов
  19. DDRD |= _BV(PD1);//PD0, PD1 и PD2
  20. DDRD |= _BV(PD2);//на выход
  21.  
  22. PORTD = 0xFF; //включаем подтягивающие резисторы
  23. pp=1000; //задаем скорость зажигания /гашения
  24.  
  25. for(;;) //бесконечный цикл
  26. {//Зажигаем красный светодиод
  27. PORTD &= ~_BV(PD0);
  28. for (i = 20; i < pp; i++) //плавное зажигание зеленого светодиода
  29. { p=pp-i; led0(PD1,i,p); }
  30. PORTD &= ~_BV(PD1); //Зеленый светодиод остается гореть
  31. for (i = 20; i < pp; i++) //плавное гашение красного светодиода
  32. {p=pp-i; led0(PD0,p,i); } //Зеленый светодиод остается гореть
  33. PORTD &= ~_BV(PD1); //плавное зажигание синего светодиода
  34. for (i = 20; i < pp; i++)
  35. { p=pp-i; led0(PD2,i,p); }
  36. PORTD &= ~_BV(PD2); //Синий светодиод продолжает гореть
  37. for (i = 20; i < pp; i++) //Плавное гашение зеленого светодиода
  38. { p=pp-i; led0(PD1,p,i); }
  39. PORTD &= ~_BV(PD2); //Синий светодиод продолжает гореть
  40. for (i = 20; i < pp; i++) //постепенное зажигание красного светодиода
  41. { p=pp-i; led0(PD0,i,p); }
  42. //Красный светодиод продолжает гореть
  43. PORTD &= ~_BV(PD0);
  44. for (i = 20; i < pp; i++) //Плавно тушим синий светодиод
  45. { p=pp-i; led0(PD1,p,i); }
  46. }
  47. }

zvyagaaa (что-то я не могу авторизоваться на работе на вашем сайте)

Попробуй взять atmega16 и

Попробуй взять atmega16 и поиграться с пультом от телевизора, на сайте есть статья по декодеру ИК пульта.
Было озвучено пару идей по поводу совмещения двух этих проектов. Ну как-бы сделать устройство управления RGB светодиодом при помощи ИК пульта.

А не жирно mega16 на

А не жирно mega16 на управление простым диодом, пускай даже rgb?

а что делать, если код не

а что делать, если код не влезает?
вот я тоже хочу объединить термометр 1wire с таким светодиодом - чтобы он красиво моргал и манил всех вокруг, чтобы они нажали кнопку - и заработал термометр. но! (вроде бы ничего сложного)
у меня сам по себе термометр едва влез в прошивку (сейчас вот думаю, влезет ли с запоминаниями минимумов и максимумов - пока руки не доходят попробовать)

тут либо сразу кодить в ассемблере, либо систематично и методично повышать свои знания программирования на си, чтобы кодить так, чтобы максимально компактно собиралось при компилировании, но при этом все задержки для термометра соблюдались, либо плевать на все и брать микроконтроллеры с большим объемом памяти.

кстати, люблю я не в тему вопросы задавать)
а как по-простому записывать несколько двухбайтных значений в постоянную память? (сейчас пришла мысль - иметь минимумы/максимумы с момента последнего включения в сеть и вообще исторические минимумы и максимумы -прикольно же!)

1) Использовать оптимизацию,

1) Использовать оптимизацию, но сразу вылезут траблы с задержками.
2) Взять контроллер помощнее, например mega8, 16, 32 или тиню 44, 84 если фичи мег не нужны.
3) Можно все кодить и на асме, потрать неделю на написание проги для навороченного термометра, которая влезет в 1к флеша. А можно на С, потратить вечер, но прога влезет в 8к флеша. Мне свободное время дороже, чем 8к флеша и соответствующий контроллер, а тебе?

по простому писать переменную int в память -

int x;
unsigned char y;

y=(x&0xff00)>>8; - получили старшый байт
пишем;
y=x&0x00ff - получили младший байт
пишем;

Как видишь тут используется

Как видишь тут используется программная ШИМ, то есть без использования таймера-счетчика, если у тебя будет не задействованный таймер-счетчки, можешь н анем сделать. Кода меньше, а по поводу записи в EEPROM был пост на форуме.

а ИК декодер??? А два

а ИК декодер??? А два диода???
Я думаю гуд будет!

Если ШИМ программный - то

Если ШИМ программный - то можно смело 8-ю мегу юзать. + навешать на ее всякой радости для ИК.

а можно ли на этом

а можно ли на этом микроконтроллере замутить аппаратный шим? и на сколько каналов? каналов 6 можно ли сделать? Или к примеру 4 аппаратных 2 программных, там можно сделать? Если да, то как? А так, тема очень интересная, пошел паять :)
ПС большое вам спасибо за ваш сайт, за то, что вы не ленитесь объяснять элементарные вещи и грамотно комментировать код. (я только у вас на сайте понял, как делать программный шим, так и до аппаратного доберусь)

аппаратная ШИМ

Вот статья аппаратная ШИМ на ATmega8, но два момента:
1. Микроконтроллер надо другой, более функциональный.
2. Аппаратных ШИМ каналов на этом микроконтроллере максимально может быть 3.

И тебе спасибо за благодарность.

А 50Гц так можно

А 50Гц так можно сгенерировать?

Емм..Какие 50 Гц??

Емм..Какие 50 Гц??

Выходите на связь :)

Приветствую эмбеддеров. Мы почти соседи (у меня младший адрес IP 193, а у вас 7) :)
предлагаю познакомиться поближе, с целью обмена опытом и проектами.
С уважением, участник команды xdevs.com :)

hex файл

А где можно скачать hex файл. Я начинающий с компиляторами не дружу пока. А устройство интересное.

вопрос по компилятору

Слушай, давай ты лучше напишешь в чем именно ты не дружишь с компилятором, я напишу статью, в которой подробно расскажу что к чему и соответственно ты научишься :-) Так КПД будет максимальным.

Доброй время суток! я хотел

Доброй время суток! я хотел бы узнать у Вас какой программой Вы пользуетесь для создания *.hex файла. И если можно подскажите какой литературой вы пользуетесь для написания программ. Заранее спасибо!!!

Для написания программ, есть

Для написания программ, есть специальная среда так называемая AVR Studio. Эта среда работает совместно с компилятором Win AVR GCC, который по сути и делает из программы *.hex файл. Так что качай эти две проги, устанавливай как написано на страницах, делай новый проект, закидывай туда код с сайта(только удали нумерацию строк), выбери в проекте свой микроконтроллер и получишь файл которым прошивают микроконтроллеры.

спасибо!

За программки спасибо! все поставил- работает, компилируется а вот *.HEX файл не получается добыть, зато создались три файл с расширениями *.aps, *.aws, *.c подскажите пожалуйста что не так делаю? заранее спасибо!

Читай статью Получаем hex

Читай статью Получаем hex файл, там все расписано. Если есть вопросы - пиши!

Спасибо огромное !!! Все

Спасибо огромное !!! Все получилось

Помогите

Вы меня простите за то что прошу хекс фаил.Но япробовал сделать его и ничего не получилось

Прошивка контроллера

Специально для тебя HEX файл прошивки

А как

А как сделать так чтобы мк работала от внуреннего рц енератора и неставить кварц?

За источник тактирующего

За источник тактирующего сигнала (в данном случаи это и есть кварц) отвечают так называемые фьюз биты. Примеры конфигураций фьюз битов.

как выставить фузы для данного проекта?

очень понравилась эта статья, спасибо за разъяснения и Коментарии, но остается одно не ясным, как выставить фузы для данного проекта?
если можно приведите скрин для ( кодевижн авр ) или хотябы распишите где проставить галочки.... )))

заранее благодарен , с ув. Алексей

Конфигурация Фьюз-битов для

Конфигурация Фьюз-битов для данного проекта не критична!
Если микроконтроллер свежий, в смысле только купленный и с ним еще ничего не делали, то он настроен на работу от внутреннего генератора. Подключаешь программатор, заливаешь прошивку, отключаешь программатор и программа работает!