Программый ШИМ. Вот хоть убейте не понимаю.

Вопросы настройки, программирования, прошивки микроконтроллеров и микросхем программируемой логики
Аватара пользователя
poligon
Нашел транзистор. Понюхал.
Сообщения: 160
Зарегистрирован: Вс июн 21, 2009 15:44:57

Программый ШИМ. Вот хоть убейте не понимаю.

Сообщение poligon »

Есть ATTiny45. Хочу просто плавно зажигать RGB светотиод. Решил потренироваться на обычном светодиоде. Первое что приходит на ум:

Код: Выделить всё

while (1)
      {
      PORTB.0=0;
      delay_us(10);  
      PORTB.0=1;
      delay_us(10); 
      }
Светодиод горит в полный накал. Тут приведен пример для RGB светодиода. Но он не работает толком ни в протеусе ни в железе. Попеременно просто мигает и всё. Там приведен код для ATtiny13. Понять принцип так и не смог.

Код: Выделить всё

/*****************************************************
Chip type           : ATtiny13
Clock frequency     : 9,600000 MHz
*****************************************************/
#include <tiny13>      
#include <delay>

void main(void)
{
unsigned int k, i;  
unsigned char a;
// Port B initialization
PORTB=0xFF;
DDRB=0x07;

while (1)
      {     
       k=3000;
       while(k>1){
      for(i=1; i<=k; i=i+1)
          {   
             if(a==0){
             PORTB.0=0;  
             PORTB.1=1;
             }
             if(a==1){
             PORTB.1=0;
             PORTB.2=1;
             }       
             if(a==2){  
             PORTB.2=0;
             PORTB.0=1;
             }
             delay_us(5);
          }
      for(i=k; i<3000>2)a=0;
      };
}
Как я понимаю:

пока k>1 мы 3000 раз делаем
PORTB.0=0;
PORTB.1=1;
с интервалом delay_us(5);

Затем 3000 раз
PORTB.0=1;
PORTB.1=0;

Уменьшаем k=k-10; и всё снова пока k>1. Т.е. уменьшая k мы уменьшаем длительность "горения" светодиода. Т.е. только что мы его плавно зажгли и потушили.
Дальше увеличили a++; т.е. перешли ко второму светодиоду и т.д.

У меня же светодиод с этой прошивкой просто быстро моргает И В ПРОТЕУСЕ И В ЖЕЛЕЗЕ. Частота 8 МГц (внутр.) по дефолту для ATTiny45 (и в протеусе и в железе).

1. Как зажечь светодиод в полнакала? 1/4?
2. Как плавно менять?


Изображение

P.S. Посмотрел datasheet на ATTiny45 там говорится про аппаратный 2-х канальный шим. Но пока не будем об этом (у меня ещё есть и ATTiny15, там нет такого)
Вложения
Shim.rar
Протеус и CVAVR
(15.62 КБ) 242 скачивания
Последний раз редактировалось poligon Вс авг 30, 2009 21:30:05, всего редактировалось 1 раз.
Реклама
Аватара пользователя
-==MAXCELERON==-
Встал на лапы
Сообщения: 96
Зарегистрирован: Сб авг 15, 2009 07:31:56
Откуда: г. Кемерово

Сообщение -==MAXCELERON==- »

Попробуй так :

Код: Выделить всё

void main(void) 
{ 

PORTB=0x00; 
DDRB=0xff; 

while (1) {
     
             PORTB=0xff;
             delay_us(5);
             PORTB=0x00;
            delay_ms(10); 
            }
    
}
Реклама
ps1x
Первый раз сказал Мяу!
Сообщения: 22
Зарегистрирован: Вт окт 07, 2008 10:31:41
Откуда: Московская область
Контактная информация:

Сообщение ps1x »

Дело в том что у светодиодов "очень нелинейная характеристика" (гкхм...). То есть постоянно включенный светодиод и светодиод 50% шима на глаз выглядят почти одинаково.
Аватара пользователя
-==MAXCELERON==-
Встал на лапы
Сообщения: 96
Зарегистрирован: Сб авг 15, 2009 07:31:56
Откуда: г. Кемерово

Сообщение -==MAXCELERON==- »

Да, именно поэтому нужно держать ноль намного дольше единицы :idea:

"1" держим 5 мксек, "0" - 5 мили :idea: сек
Реклама
Эиком - электронные компоненты и радиодетали
Аватара пользователя
ibiza11
Поставщик валерьянки для Кота
Сообщения: 1900
Зарегистрирован: Сб фев 21, 2009 13:11:40
Откуда: Москва

Сообщение ibiza11 »

Человеческий глаз определяет яркость по люменам, чем больше люмен, тем ярче . Яркость светодиода зависит от протекающего тока. вот характеристики яркости двух светодиодов в зависимости от тока :
Изображение
Ставим плюсы: )
Реклама
Аватара пользователя
WandererSc
Друг Кота
Сообщения: 4077
Зарегистрирован: Вс мар 22, 2009 17:31:41

Re: Программый ШИМ. Вот хоть убейте не понимаю.

Сообщение WandererSc »

poligon писал(а): for(i=k; i<3000>2)a=0;
И как должна работать эта строка? Вызывает сомнения "i<3000>2"
Раз reset, два reset - полyчи на диске bad !
Тpанзистоp p-n-p. Plug-n-Play ?
У кого что сбоит, тот о том и говорит.
Реклама
Аватара пользователя
Meteor
Друг Кота
Сообщения: 3961
Зарегистрирован: Пн июл 13, 2009 14:37:39
Откуда: Московская область, наукоград.....
Контактная информация:

Сообщение Meteor »

Вообще вызывает сомнение 3 вложенных цикла 2 из которых вечные...
На начальном участке задается величина к=3000, а потом смотрится не свалилось ли оно до 0.
Аватара пользователя
sheva_s
Грызет канифоль
Сообщения: 256
Зарегистрирован: Пт апр 27, 2007 14:32:48
Откуда: Украина Кривой Рог
Контактная информация:

Сообщение sheva_s »

Вот может поможет чем то, изучал когда то 3-х канальный программный шим, меняет яркость плавно по 3 каналам , вот только на светодиодах конечно не очень хорошо видно , причину уже обьяснили.
Пытался вставку кода сделать а форум коверкает строки.
Пришлось прикрепить.

Вот простой программный ШИМ

Код: Выделить всё

while (1) 
      { 
      PORTB.0=0; 
      delay_us(8);  
      PORTB.0=1; 
      delay_us(2); 
      }     // так должен светиться еле-еле

**************************************************
это два разных примера

**************************************************

while (1) 
      { 
      PORTB.0=0; 
      delay_us(2);  
      PORTB.0=1; 
      delay_us(8); 
      }        // так должен светиться ярко

Обрати внимание на задержки в сумме они составляют одинаковое число в моем примере 10 комбинируя задержки ты получиш ШИМ главное что бы сумма осталась одинаковая. В твоем примере числа могут быть другие . В прикрепленном файле сделано немного подругому я демаю разберешся. В протеусе ты ШИМ неувидеш по горению светодиода он будет просто там мигать ШИМ в протеусе можно увидеть только по осцилографу. Твоя программа что ты выложил неправильна возьми полностью оригинал ты ее неправильно упрастил. Посмотри в том коде что у тебя есть переменная "а" которая по условию имеет разные значения но как и где она меняеться я ненашел .!
Вложения
rwm_2.rar
(678 байт) 254 скачивания
Последний раз редактировалось sheva_s Вс авг 30, 2009 21:55:38, всего редактировалось 2 раза.
Аватара пользователя
poligon
Нашел транзистор. Понюхал.
Сообщения: 160
Зарегистрирован: Вс июн 21, 2009 15:44:57

Re: Программый ШИМ. Вот хоть убейте не понимаю.

Сообщение poligon »

WandererSc писал(а):
poligon писал(а): for(i=k; i<3000>2)a=0;
И как должна работать эта строка? Вызывает сомнения "i<3000>2"
Код полностью вставляю, а сайт его почему то так обрезает. Может слишком большой для него.
Вложения
rgb.c
(1.19 КБ) 487 скачиваний
Аватара пользователя
Goodefine
Держит паяльник хвостом
Сообщения: 906
Зарегистрирован: Ср апр 16, 2008 13:22:54
Откуда: Приднестровье, Тирасполь

Сообщение Goodefine »

Давно наваял пример программного ШИМа. Яркость подсветки можно изменять с помощью двух кнопок. Код очень простой, поэтому не поясняю...

Код: Выделить всё

//....
//-----------МАКРООПРЕДЕЛЕНИЯ
#define PWM_GRADATION 10   //число градаций PWM
//задаем константу антидребезга
//при константе 100 и текущих настройках таймера
//кнопки опрашиваются примерно раз в 25мс
#define ANTI_DRB_SENCIVITY 100
#define PWM_PIN PORTB.0     //выходной пин
#define BUTTON_LIGHT_PLUS  PINB.1
#define BUTTON_LIGHT_MINUS PINB.2
//------------переменные для PWM
unsigned char pwm_value;    //текущее значение
unsigned char pwm_counter;  //счетчик
unsigned char fl_butt_pl;   //флаги для однократного инкрементирования
unsigned char fl_butt_mn;   //(декремент.) при нажатии и  удержании
unsigned char anti_drb_counter; //счетч. для антидребезга при коммутации
//...
//----------------Обработчик Т0-----------------------------------//
//Таймер настроен на тактирование 1МГц, при 8МГц тактовой (TCCR0=0x02;)
//(потребляет меньше, удобные интервалы). Частота PWM около 350Гц
//при числе градаций ANTI_DRB_SENCIVITY равным 10
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{//в обработчике делаем все:
    //---антидребезг
    if(anti_drb_counter==ANTI_DRB_SENCIVITY){
    //обработка нажатий с проверкой диапазонов и однократности нажатия    
    if(!BUTTON_LIGHT_PLUS){
        if((pwm_value<=PWM_GRADATION)&&(!fl_butt_pl)){pwm_value++;fl_butt_pl=1;}
                          }else{fl_butt_pl=0;}
        
    if(!BUTTON_LIGHT_MINUS){
        if((pwm_value)&&(!fl_butt_mn)){pwm_value--;fl_butt_mn=1;}
                           }else{fl_butt_mn=0;}  
                                            
     anti_drb_counter=0;   }else anti_drb_counter++;  
    //-----------
//если значение счетчика больше текущего значения PWM,
//устанавливаем пин в ноль, иначе в ед.
        (pwm_counter<pwm_value)? (PWM_PIN=1):(PWM_PIN=0);
//проверяем, достиг ли счетчик предельного значения градаций,
//если да - обнуляем, иначе - инкрементируем
       (pwm_counter==PWM_GRADATION)? (pwm_counter=0):(pwm_counter++);
}
//===============
Любой, заслуживающий внимания, опыт приобретается себе в убыток...
Аватара пользователя
poligon
Нашел транзистор. Понюхал.
Сообщения: 160
Зарегистрирован: Вс июн 21, 2009 15:44:57

Сообщение poligon »

sheva_s писал(а): Вот простой программный ШИМ

Код: Выделить всё

while (1) 
      { 
      PORTB.0=0; 
      delay_us(8);  
      PORTB.0=1; 
      delay_us(2); 
      }     // так должен светиться еле-еле

**************************************************
это два разных примера

**************************************************

while (1) 
      { 
      PORTB.0=0; 
      delay_us(2);  
      PORTB.0=1; 
      delay_us(8); 
      }        // так должен светиться ярко

В общем по светодиоду ничего не увидишь. Взял вольтметр и померил.

При

Код: Выделить всё

while (1) 
      { 
      PORTB.0=0; 
      delay_us(8);  
      PORTB.0=1; 
      delay_us(2); 
      }     // так должен светиться еле-еле 
3.9 вольта

При

Код: Выделить всё

while (1) 
      { 
      PORTB.0=0; 
      delay_us(2);  
      PORTB.0=1; 
      delay_us(8); 
      }        // так должен светиться ярко 
1.02 вольта

Это между PB0 и "+". Светодиод у меня катодом ("-") подключен к PB0 через резистор 220 Ом. Интересно как максимум выставить (5 В) на ножке? На светодиоде то меньше будет за счет резистора.

Так начинает проясняться.... завтра попробую на лампочке, если найду.
Goodefine, твой пример тоже завтра поподробней гляну, а то уже поздно.
Аватара пользователя
sheva_s
Грызет канифоль
Сообщения: 256
Зарегистрирован: Пт апр 27, 2007 14:32:48
Откуда: Украина Кривой Рог
Контактная информация:

Сообщение sheva_s »

Максимум будет так в этом варианте только увеличим сумму задержки до 40 что бы поднять дисретность ШИМА

Код: Выделить всё

while (1) 
      { 
      PORTB.0=0; 
      delay_us(39);  
      PORTB.0=1; 
      delay_us(1);
};

минимум так

while (1) 
      { 
      PORTB.0=0; 
      delay_us(1);  
      PORTB.0=1; 
      delay_us(39);
};


Аватара пользователя
poligon
Нашел транзистор. Понюхал.
Сообщения: 160
Зарегистрирован: Вс июн 21, 2009 15:44:57

Сообщение poligon »

sheva_s, всё правильно, работает. А вот как теперь сделать плавное изменение?
Аватара пользователя
Volly
Опытный кот
Сообщения: 702
Зарегистрирован: Пт мар 06, 2009 18:22:23

Сообщение Volly »

Примерно так:

Код: Выделить всё

unsigned int i, i2, pwm_value; 
bit pwm_bit; 

while (1) { 
   i++; 
   if (i > 1000) { 
       i = 0;
       i2++; 
       pwm_bit = 1; 
   } 
   if (i == pwm_value) pwm_bit = 0; 
   PORTB.0 = ~pwm_bit; 
   delay_us(40);
   if (i2 == 200) {
       i2 = 0;
       if (pwm_value < 1000) pwm_value++; 
       else pwm_value = 0; // если по кругу
   } 
};
Для принципа, использовать напрямую фигня получится.
Аватара пользователя
sheva_s
Грызет канифоль
Сообщения: 256
Зарегистрирован: Пт апр 27, 2007 14:32:48
Откуда: Украина Кривой Рог
Контактная информация:

Сообщение sheva_s »

Вот еще вариант должен сработать .

Код: Выделить всё

while (1)
      {
 int n,k,v;           // обьявляем переменные
 k=1;                 // значение шима
 v=255;             // максимальное значение ШИМ

while (1)
{                
 PORTB.0=1;                         //выключаем ПИНВ.0(выключаем шим)

 for(n=0; n<=v; n++)            //запускаем цикл ШИМа
 {
 if(n==k) PORTB.0=0;             //включаем ШИМ по 0 выводу
 delay_us(2);

 };                                // выход из цикла ШИМа


};

};
Меняя значение К в этой сторочке
k=1; // значение шима
от 1 до 254 регулируем ШИМ
пробуй потомпокажу как сделать что бы это значение менялось автоматом если у тебя неполучиться , код непроверял но вроде должен работать , делал когдато ШИМ по этому коду.


Вот сделал с плавным изменением яркости от нуля до максимума и покругу сделано для ТИНИ45 проверено в протеусе работает пробуй. Сравниш два кода и найдеш отличие поумеш как меняеться яркость автоматически. :))

Код: Выделить всё

#include <tiny45>
#include<delay>


void main(void)
{

#pragma optsize-
CLKPR=0x80;
CLKPR=0x00;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif

PORTB=0x00;
DDRB=0x3F;

while (1) 
      { 
 int n,k,v,s;           // обьявляем переменные 
 k=1;                 // значение шима 
 v=255;             // максимальное значение ШИМ 

while (1) 
{                
 PORTB.0=1;                         //выключаем ПИНВ.0(выключаем шим) 

 for(n=0; n<=v; n++)            //запускаем цикл ШИМа 
 { 
 if(n==k) PORTB.0=0;             //включаем ШИМ по 0 выводу 
 delay_us(2); 

 };                                // выход из цикла ШИМа 
 s++;
 if(s==100) {k++; s=0;}; //   плано уменьшаем яркость  
 if(k==255) k=0;  //    проверяем чтобі переменная невілезла за пределі регулировки ШИМА
 
}; 

};
}
прикрепил проект для кодвижен.
Вложения
RWM.rar
программный шим АТТИНИ45
(18.74 КБ) 247 скачиваний
Аватара пользователя
dosikus
Друг Кота
Сообщения: 3604
Зарегистрирован: Пн июл 28, 2008 22:12:01

Сообщение dosikus »

sheva_s
А к чему вложеные бесконечные циклы ?!????
Аватара пользователя
Goodefine
Держит паяльник хвостом
Сообщения: 906
Зарегистрирован: Ср апр 16, 2008 13:22:54
Откуда: Приднестровье, Тирасполь

Сообщение Goodefine »

Почему бы не глянуть на приведенный мною код? Там, вообще, все лишнее можно нафиг выкинуть:

Код: Выделить всё

//....
//-----------МАКРООПРЕДЕЛЕНИЯ
#define PWM_GRADATION 10   /*число градаций PWM, меньше 255*/
#define PWM_PIN PORTB.0     //выходной пин*/
//------------переменные для PWM
unsigned char pwm_value;    //текущее значение
unsigned char pwm_counter;  //счетчик
//...

//----------------Обработчик Т0-----------------------------------//
//Таймер настроен на 1МГц, при 8МГц тактовой (TCCR0=0x02;)
// Частота PWM около 350Гц
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
//если значение счетчика больше текущего значения PWM,
//устанавливаем пин в ноль, иначе в ед.
        (pwm_counter<pwm_value)? (PWM_PIN=1):(PWM_PIN=0);
//проверяем, достиг ли счетчик предельного значения градаций,
//если да - обнуляем, иначе - инкрементируем
 (pwm_counter==PWM_GRADATION)? (pwm_counter=0):(pwm_counter++);
}
Вся забота сведется к установке переменной pwm_value в нужное значение (хоть в вечном цикле), по какому угодно закону. Разумеется, не имеет смысла делать его больше, чем PWM_GRADATION... Таких программных ШИМов, можно целую кучу сделать, используя всего один обработчик...
Любой, заслуживающий внимания, опыт приобретается себе в убыток...
Аватара пользователя
sheva_s
Грызет канифоль
Сообщения: 256
Зарегистрирован: Пт апр 27, 2007 14:32:48
Откуда: Украина Кривой Рог
Контактная информация:

Сообщение sheva_s »

dosikus писал(а):sheva_s
А к чему вложеные бесконечные циклы ?!????
Да некчему делал давно так и скопировал , а вобше нужно вынести переменные в инициализацию и будет ГУД.... Просто необратил внимание.
Нужно так:

Код: Выделить всё

#include <tiny45>
#include<delay>
int n,k=1,v=255,s;           // обьявляем переменные

void main(void)
{

#pragma optsize-
CLKPR=0x80;
CLKPR=0x00;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif

PORTB=0x00;
DDRB=0x3F;




while (1) 
{                
 PORTB.0=1;                         //выключаем ПИНВ.0(выключаем шим) 

 for(n=0; n<=v; n++)            //запускаем цикл ШИМа 
 { 
 if(n==k) PORTB.0=0;             //включаем ШИМ по 0 выводу 
 delay_us(2); 

 };                                // выход из цикла ШИМа 
 s++;
 if(s==100) {k++; s=0;}; //   плавно уменьшаем яркость  
 if(k==255) k=0;  //    проверяем чтобы переменная невылезла за пределы регулировки ШИМА
 
}; 

}
Аватара пользователя
poligon
Нашел транзистор. Понюхал.
Сообщения: 160
Зарегистрирован: Вс июн 21, 2009 15:44:57

Сообщение poligon »

sheva_s, твой последний вариант кода - светодиод просто моргает.
Goodefine, что такое число градаций??? Твой код для меня совсем не понятен.

Час от часу не легче. Программатор перестал работать. STK200/300. До этого всё нормально было.

Сейчас припомимаю что вроде как то не правильно разъём подключил к программатору, светодиод тускло засветился. Я тут же вытащил и воткнул как надо. Может ещё что сгореть могло от этого???

Сегодня уже поставил новую 74НС244N и всё равно CVAVR не видит. Что ещё сгореть то могло???

Собрал по схеме Громова (+ Uniprof), но он просто ужасно работает. Прошить контроллер целая проблема. Постоянно какие то ошибки. Но контроллер видит, т.е. он живой 100% (светодиод на нём моргает).

Главное чего STK200/300 надо то????? LPT вроде нормально в диспетчере видится, без ошибок.

Ну замучился прям уже, да что ж такое, прям руки опускаются.

USB программатор что ли паять
Аватара пользователя
sheva_s
Грызет канифоль
Сообщения: 256
Зарегистрирован: Пт апр 27, 2007 14:32:48
Откуда: Украина Кривой Рог
Контактная информация:

Сообщение sheva_s »

Число градаций это - степень регулировки ШИМа - дискретность регулировки - типа того .
Если просто мигает получаеться маленькая частота ШИМа нужно поднять частоту ШИМа .
СПОСОБЫ :
1. Попробуй убрать строчку delay_us(2); - если непоможет верни назад и пробуй дальше.
2. Иправь предел ругулировки ШИМа щяс она регулируеться от 0 до 255 сделай к примеру 50 делаеться так.
исправляються строчки
int n,k=1,v=50,s; // обьявляем переменные
if(k==50) k=0;

3. если непоможет делаеш первый и второй способ одновременно, или подымаеш частоту процессора до 4 - 8 МГц.



Что бы было понятно про программный ШИМ работает так
1.Зажигаеш светодиод.
2.Делаеш ЦИКЛ с количеством повторения к примеру 50
делаеш условие в цикле при котором у тебя должен выключиться светодиод условие должно проверять число скоко раз у тебя сработал цикл с твоим числом которое отображает яркость горения светодиода (образно ) в нашем случае число от 0-50, когда цикл отработает свои 50 повторений возрат на пукнт 1.

если что напутал некричите пошел спать.
Закрыто

Вернуться в «Микроконтроллеры и ПЛИС»