Прошу Вас помочь мне. Решил сделать приборную панель с полноцветной подсветкой. До этого с программированием не имел ни какого дела. Посидел, по читал по программированию на языке Си в CAVR. И найдя в сети учебный код по управлению RGB светодиодами от энкодера, решил попробовать. написал три раздельных кода (чтоб каждый код было проще проверить на работо способность в протеусе) для плавного включения светодиодов, регулировки яркости с помощью энкодера и выбор политры цвета также на энкодоре но с применением кнопки. Раздельно коды работают как и должны, а вот начал объеденять все в единый код и начался хаос. плавное включение и регулировка яркости при объединении работает нормально, но стоит добавить выбор политры и полная ерунда с кнопкой и энкодером. Вот код для плавного включения и регулировки яркости: Спойлер
Код:
Chip type : ATmega8 Program type : Application AVR Core Clock frequency: 8,000000 MHz Memory model : Small External RAM size : 0 Data Stack size : 256 *****************************************************/
#include <mega8.h> #include <delay.h>
volatile int pwm_counter,R,G,B,scena=1,i;
interrupt [EXT_INT0] void ext_int0_isr(void) { //Обработка событий вращения экодера delay_us(50); if((PIND&(1 << PORTD2))==0) { delay_us(50); if((PIND&(1 << PORTD0))==0) { //Уменьшение яркости LED RGB R-=17; if(R < 1) R = 1; G-=17; if(G < 1) G = 1; B-=17; if(B < 1) B = 1; } else { //Увеличение яркости LED RGB R+=17; if(R > 255) R = 255; G+=17; if(G > 255) G = 255; B+=17; if(B > 255) B = 255; } } GIFR = (1<<INTF0); // очищаем флаг внешнего прерывания return; }
// Timer 0 overflow interrupt service routine interrupt [TIM0_OVF] void timer0_ovf_isr(void) { // программный ШИМ if (pwm_counter++ > 255) { PORTB = 0x00; pwm_counter = 0; } if (pwm_counter > R) PORTB |= (1 << PORTB0); if (pwm_counter > G) PORTB |= (1 << PORTB1); if (pwm_counter > B) PORTB |= (1 << PORTB2); }
Chip type : ATmega8 Program type : Application AVR Core Clock frequency: 8,000000 MHz Memory model : Small External RAM size : 0 Data Stack size : 256 *****************************************************/
#include <mega8.h> #include <delay.h>
volatile int pwm_counter,R,G,B,scena=1,i,button;
interrupt [EXT_INT0] void ext_int0_isr(void) { //Обработка событий вращения экодера delay_us(50); if((PIND&(1 << PORTD2))==0) { delay_us(50); if((PIND&(1 << PORTD0))==0) { //Уменьшение яркости LED RGB R-=17; if(R < 1) R = 1; G-=17; if(G < 1) G = 1; B-=17; if(B < 1) B = 1; if(button==0) { if (scena == 1) {if(G<255) G+=15; else scena = 2;} if (scena == 2) {if(R>0) R-=15; else scena = 3;} if (scena == 3) {if(B<255) B+=15; else scena = 4;} if (scena == 4) {if(G>0) G-=17; else scena = 5;} if (scena == 5) {if(R<255) R+=17; else scena = 6;} if (scena == 6) {if(B>0) B-=17; else scena = 1;} } } else { //Увеличение яркости LED RGB R+=17; if(R > 255) R = 255; G+=17; if(G > 255) G = 255; B+=17; if(B > 255) B = 255;
За написание кода не ругайте. Как писал ранее я первый раз пишу программным языком, да ещё для мк. Я не электронщик и много в этой области не знаю, могу толко собрать готовую схему в DIP Trace развести для этого плату, да лутом её сделать, ну пару раз недавно прошил два мк. Да прошу к Datasheet не отсылать с англиским полный ноль, помогите с кодом или примерами кода, думую, что голова не совсем дурная, как нибуть разбирусь. И ещё подскажите, как реализовать плавного гашение светодиодов при выключении питания и занесение данных в память при выключении питания при условии что были сделаны изменения в настроках политры и яркости и они отличаются от тех, что уже имеются в памяти мк. На форуме я уже читал по поводу отслеживания напряжения на порте AIN, но не совсем все понял, если можно пример кода на основе моего примера выше.
_________________ "Жизнь человека - это короткое мгновение во вселенной, и не стоит её тратить на обиды, оскорбления и выяснение отношений."
Чего-то со скобками напутано 100 пудов. Покажите пожалуйста отдельно все 3 куска,а то чего-то недопонимаю,куда какая скобка должна относиться
_________________ В первый раз меня ударило током - и я подумал что ни черта не соображаю в электричестве. Во второй раз был аккуратнее и меня не ударило - теперь я возомнил из себя крутого микроэлектронщика.
В протеусе вместо светодиодов у меня стоит осцилограф на выходах. Что касается скобок проверка синтаксиса в CAVR дает отсутствие ошибок. Т.к. рабочий код для плавного включения и регулировки яркости я ранее выкладывал, то вод отдельный рабочий код по выбору политры цвета:
Код:
Chip type : ATmega8 Program type : Application AVR Core Clock frequency: 8,000000 MHz Memory model : Small External RAM size : 0 Data Stack size : 256 *****************************************************/
И в чем, в коде не правельно с обработкой нажатия кнопки т.к. вы описывакте так и реализовано, а то, что стоит кол-во нажатий 10, то просто код писал с дальнейшим развитием программы для других операций. А вобще мои не да чет, наверно я не правильно поставил вопрос. Как обеденить выбор политры и регулировку яркости на одном энкодоре, а именно при вращении энкодера влево-вправо регулируется яркость при нажатии кнопку вращение энкодера влево-вправо позволет выбирать политру цвета, повторное нажатие на кнопку запоминает выбраный цвет в ОЗУ. Так вот по раздельности код регулировки яркости энкодером работает и выбор политры отдельно работает. а как объеденяю вместе происходит хаос.Вот в чем основная проблема. А остальное кол-во количество нажатия кнопки - это для будущей функции выбора предворительно настроенных настроенных цветов.
_________________ "Жизнь человека - это короткое мгновение во вселенной, и не стоит её тратить на обиды, оскорбления и выяснение отношений."
А если держать кнопку при установке энкодером палитры? Тогда при обработке энкодера проверяйте состояние переменной button. Если она 0 - меняем палитру, если 1 - меняем цвет. У Вас эта переменная может принимать значения только 0 и 1 (при такой обработке нажатия кнопки).
И вопрос: а зачем это в прерывании?
Код:
GIFR = (1<<INTF0); // очищаем флаг внешнего прерывания
Насчёт нажатия кнопки и вращения энкодера, вообщето не совсем удобно т.к. кнопка встоена в энкодер и попытатся нажать и удерживать кнопку и вращать одновременно энкодер, я боюсь мне придется стать "виртуозом" . А насчет
Код:
[color=#FF0000]GIFR = (1<<INTF0);[/color] [color=#0000BF]// очищаем флаг внешнего прерывания[/color]
не знаю так стояло в учебном коде по управлению энкодером RGB светодиодами, я ещё не очень разбираюсь в этом, толко начал пытася разбиратся во всем этом. Вот только что попробовал изменить расположение выполнение операций регулировки яркости и политры цвета interrupt [EXT_INT0] void ext_int0_isr(void)
Код:
{ //Обработка событий вращения экодера delay_us(50); if((PIND&(1 << PORTD2))==0) { delay_us(50); if((PIND&(1 << PORTD0))==0) { //Выбор политры цвета if (button==0) { if (scena == 1) {if(G<255) G+=15; else scena = 2;} if (scena == 2) {if(R>0) R-=15; else scena = 3;} if (scena == 3) {if(B<255) B+=15; else scena = 4;} if (scena == 4) {if(G>0) G-=17; else scena = 5;} if (scena == 5) {if(R<255) R+=17; else scena = 6;} if (scena == 6) {if(B>0) B-=17; else scena = 1;} } else //Увеличение яркости LED RGB, всех каналов { R-=17; if(R < 1) R = 1; G-=17; if(G < 1) G = 1; B-=17; if(B < 1) B = 1; } } else { //Выбор политры цвета if(button==0) { if (scena == 1) {if(G>0) G-=15; else scena = 6;} if (scena == 2) {if(R<255) R+=15; else scena = 1;} if (scena == 3) {if(B>0) B=R-15; else scena = 2;} if (scena == 4) {if(G<255) G+=15; else scena = 3;} if (scena == 5) {if(R>0) R-=15; else scena = 4;} if (scena == 6) {if(B<255) B=R+15; else scena = 5;} } else //Увеличение яркости LED RGB, всех каналов { R+=17; if(R > 255) R = 255; G+=17; if(G > 255) G = 255; B+=17; if(B > 255) B = 255; } } } GIFR = (1<<INTF0); // очищаем флаг внешнего прерывания return; }
так вот яркость стала регулировться нормально, а палитра меняется только если удерживать кнопку не трогая вращения энкодером, но это опять не то, как я писал ранее необходимо, чтобы вращая энкодер Влево-Вправо регулировалась яркость, после нажатия на кнопку и отпускания ее, снова вращая энкодер изменялась политра цвета и повторное нажатие на кнопку возвращала бы энкодеру функцию регулятора яркости.
_________________ "Жизнь человека - это короткое мгновение во вселенной, и не стоит её тратить на обиды, оскорбления и выяснение отношений."
Разница только в операндах сравнения, но проблема в том , что даже с такой обработкой нажатия кнопки программа не работает как должна, не до чёт мне кажется у обработке после нажатия кнопки события, которое должно произойти после нажатия и потом вернуться в преждее состояние по регулировке яркости. это описать я ни как не могу понять как это сделать.
_________________ "Жизнь человека - это короткое мгновение во вселенной, и не стоит её тратить на обиды, оскорбления и выяснение отношений."
phanis. все кто может помогите, голова совсем опухла , что-то получается, но не все, знаний таких как у вас в этой области у меня нет. Еще раз хочу напомнить алгорит программы котую я пытаюсь воплотить. 1. При включении питания (зажигания) rgb светодиоды плано зажигаются до установленной ранее яркости и уровня ранее выбранного цвета. 2.Вращая экодер мы регулируем яркость общую яркость вех каналов цвета. 3.При нажатии на кнопу цвет меняется на заранее заданные цвета (в моем случае сейчас это 4 цвета, красный зеленный. синий и белый, после того как получится реализовать хотя бы 4 цвета в планах добавить 14 настроек цвета) 4. При последующем нажатии кнопки мы можем выберать произвольно цвет из спектра вращая энкодер. 5.нажатие еще раз кнопки сохраняет настройки и передает управление энкодером от спектра к регуляции яркости. 6 При выключении питания светодиоды плавно гаснут. И данные о настройки цвета с яркостью записываются в EEPROM (этого пока я не совсем понимаю как сделать. хотя пробывал) Ну как то так. Есть еще один канал для монохромного светодиода но сним у меня проблем не возникло. он для плавного включения и выключения подсветки стрелок. И еще у меня почему то получилась инверсия значения цвета, т.е. вместо максимального значения яркости 255 у меня 0, и наоборот для выключенного состояния вместо 0, получается 255. Не могу понять почему. Это очень неудобно. Свой поправленный и сведенный код со схемой эмуляции в протеусе (версия прилагаю. Очень прошу откликнитесь кто нибудь, помогите, а то со времени создания темы так ни кто толкового ничего и не сказал. Если в коде, что -то написал не так как положено подскажите как надо, я писал что я в первые програмирую и тем более еще и для микроконтроллера, а сделать данный девайс в машину, признаюсь чесно очень хочется. Но с такими темпами я еще год, а то и два могу писать, а с подсказками знающих и мудрых котов, надеюсь смогу разобратся и сделать гораздо быстрее.
Код:
#include <mega8.h> #include <delay.h> //=========Обявление переменных====================== volatile unsigned int pwm_counter,R,G,B,C,scena=0,button; //==========Обявление функций===== void min (void); void max (void); void color (unsigned int cRi,unsigned int cGi,unsigned int cBi); void btn_color (unsigned int button); void bright_max (void); void bright_min (void); void on_rgb_led (void); void off_rgb_led (void); void on_red_led (void); void off_red_led (void); interrupt [EXT_INT0] void Encoder(void) { //==================Обработка событий вращения экодера вправо - влево==================== delay_us(50); if((PIND&(1 << PORTD2))==0) { delay_us(50); if((PIND&(1 << PORTD0))==0) { if (button==4) { //Регулировка каналов по спектру min (); } else { //Уменьшение яркости LED RGB bright_min (); } } else { //Регулировка каналов по спектру if (button==4) { max (); } else { //Увеличение яркости LED RGB bright_max (); } } } // очищаем флаг внешнего прерывания GIFR = (1<<INTF0); return; } // Timer 0 overflow interrupt service routine interrupt [TIM0_OVF] void Prog_pwm(void) { //===Реализация программного ШИМ на 4 канала========= if (pwm_counter++ > 255) { PORTB = 0x00; pwm_counter = 0; } if (pwm_counter > R) PORTB |= (1 << PORTB0); //ШИМ канал для красного канала RGB LED if (pwm_counter > G) PORTB |= (1 << PORTB1); //ШИМ канал для зеленого канала RGB LED if (pwm_counter > B) PORTB |= (1 << PORTB2); //ШИМ канал для синего канала RGB LED if (pwm_counter > C) PORTB |= (1 << PORTB3); //ШИМ канал для красного монохромного LED } //===Функция выбора политры цвета из спектра======== void min (void) { if (scena == 0) {if(G<255) G=G+15; else scena = 1;} if (scena == 1) {if(R>0) R=R-15; else scena = 2;} if (scena == 2) {if(B<255) B=B+15; else scena = 3;} if (scena == 3) {if(G>0) G=G-15; else scena = 4;} if (scena == 4) {if(R<255) R=R+15; else scena = 5;} if (scena == 5) {if(B>0) B=B-15; else scena = 0;} }
void max (void) { if (scena == 0) {if(G>0) G=G-15; else scena = 5;} if (scena == 1) {if(R<255) R=R+15; else scena = 0;} if (scena == 2) {if(B>0) B=B-15; else scena = 1;} if (scena == 3) {if(G<255) G=G+15; else scena = 2;} if (scena == 4) {if(R>0) R=R-15; else scena = 3;} if (scena == 5) {if(B<255) B=B+15; else scena = 4;} } //===Функция предворительно настроенных цветов======== void color (unsigned int cRi,unsigned int cGi,unsigned int cBi) { R=cRi; G=cGi; B=cBi; } //=============Функция выбора преднастроенного цвета по нажатию на кнопку================= void btn_color (unsigned int button) { switch (button) { case 1: color (0,255,255);break; case 2: color (255,0,255);break; case 3: color (255,255,0);break; case 0: color (0,0,0);break; } } //====Функция увеличения яркости======= void bright_min (void) { if ((R<255)&&(G<255)&&(B<255)) { R=R+15; G=G+15; B=B+15; } } //=====Функция уменьшения яркости======== void bright_max (void) { if ((R>0)&&(G>0)&&(B>0)) { R=R-15; G=G-15; B=B-15; } } //====Функция плавного включение RGB LED======= void on_rgb_led (void) { { for (((R=255)&&(G=255)&&(B=255));((R>0)&&(G>0)&&(B>0));((R--)&&(G--)&&(B--))) delay_ms(10);return; } } //======Функция плавного выключения RGB LED===================== void off_rgb_led (void) { { for (((R=0)&&(G=0)&&(B=0));((R<255)&&(G<255)&&(B<255));((R++)&&(G++)&&(B++))) delay_ms(10); } } //====Функция плавного включение RED LED======= void on_red_led (void) { { for (C=255;C>0;C--) delay_ms(5); } } //=====Функция плавного выключение RED LED======= void off_red_led (void) { { for (C=0;C<255;C++) delay_ms(5); } } void main(void) { // Инициализация портов. // Инициализация выходов DDRB |= (1 << PORTB5)|(1 << PORTB4)|(1 << PORTB3)|(1 << PORTB2)|(1 << PORTB1)|(1 << PORTB0); PORTB = 0x00; // Инициализация входов DDRD |= (0 << PORTD2)|(0 << PORTD1)|(0 << PORTD0)|(0<<PORTD7); // Подключаем подтягивающие резисторы PORTD |= (1 << PORTD2)|(1 << PORTD1)|(1 << PORTD0)|(1<<PORTD7); PORTD=0x00;
// подтяжка к Vcc PORTD |= (1<<7); DDRD=0x00; // Разрешение прерывания по таймеру0 TIMSK |= (1 << TOIE0); TCCR0 |= (1 << CS00);
MCUCR |= (0 << ISC00)|(1 << ISC01);
GIFR |= (1 << INTF0); GICR |= (1 << INT0);
#asm("sei") //===================Плавное включение RED LED при вкл. питания========= on_red_led(); //===================Плавное включение RGB LED при вкл. питания========= delay_ms(5); on_rgb_led(); while (1) { //========Выбор сцены спектра политры цветов=========== if((PIND&(1 << PORTD2)|(1 << PORTD0))==0) { scena++; if (scena>=5) scena=0; }
//=====Обработка события нажатия кнопки энкодера======= if((PIND&(1 << PORTD1))==0)// если нажата кнопка { while((PIND&(1 << PORTD1))==0){} //ждем отпускания кнопки button++; delay_ms(50); if(button > 4) button = 0; //==================Выбор преднастроенных цветов политры по нажатию кнопки================= btn_color (button); } } //== выключение RGB LED при выкл. питания====== off_rgb_led(); delay_ms(5); //== выключение RED LED при выкл. питания====== off_red_led(); }
Понимаю, что большенство профессионалов как вы работают либо с асамблером либо в AtmelStudio или IAR, а не CVAVR, но все равно прошу не отказать в помощи т.к. на данном мизирно начпльном этапе в этой программе мне лично проще и понятней.
Вместо смайлека (который сейчас не уместа) в посте выше я писал восьмая версия протеуса. Но почемуто вышел смайлик. Видимо цифра восемь и скобка обозначают этот смайл. извините за офтоп. Но я обязан был поправится.
_________________ "Жизнь человека - это короткое мгновение во вселенной, и не стоит её тратить на обиды, оскорбления и выяснение отношений."
Заголовок сообщения: Re: Прошу в помощи в объединении кодов для RGB контроллера
Добавлено: Сб ноя 23, 2013 00:30:02
Модератор
Карма: 90
Рейтинг сообщений: 1432
Зарегистрирован: Чт мар 18, 2010 23:09:57 Сообщений: 4583 Откуда: Планета Земля
Рейтинг сообщения:0 Медали: 1
zero648 писал(а):
Еще как может!
Вы только в железе так ёмкости не вешайте Я имел ввиду - протеус не меняет яркость при подачи на него цифрового сигнала (ШИМ) напрямую, а не аналогового
По поводу инверсии Насколько я понял из кода -ШИМ реализован относительно питания. Т.е. на схеме нужно перевернуть светодиоды- катоды подключить в портам микроконтроллера, а аноды к питанию. Остальное посмотрю как доберусь до компа где есть протеус.
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 12
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения