Страница 1 из 1

прерывания таймеров-баги с ритмом

Добавлено: Пн июн 03, 2013 19:53:50
andrikll
Сделал схему с таймерами т0 и т2 частота обоих 976 Гц поставил прерывания по переполнению и OCR2A но диод повешенный на выход который шимится программно не просто регулируется по яркости но и непонятно помаргивает . Чтобы не объяснять как диод выделывается прикладываю видео. шим стоит на минимуме, регулирется нормально если отбросить моргания. http://www.youtube.com/watch?v=sRPU13E85L4
Спойлер#include <mega48.h>
flash char port_d[9]={0,1,2,4,8,10,20,40,80};
char serv_num=1, count, old_reg, new_reg, reg=127;

// Timer 0 overflow interrupt service routine
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
count++;
if (serv_num==8) {serv_num=1;} else {serv_num++; }
}

interrupt [TIM2_OVF] void timer2_ovf_isr(void)
{
PORTB.0 = 1;
}

// Timer 2 output compare interrupt service routine
interrupt [TIM2_COMPA] void timer2_compa_isr(void)
{
PORTB.0 = 0;
OCR2A = reg;
}

void regul (void) {
if (old_reg==0) {if(new_reg == 2) reg++; if(new_reg == 1) reg--; }
}

void main(void)
{
// Declare your local variables here

// Crystal Oscillator division factor: 1
#pragma optsize-
CLKPR=0x80;
CLKPR=0x00;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif

// Input/Output Ports initialization
// Port B initialization
// Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out
// State7=0 State6=0 State5=0 State4=0 State3=0 State2=0 State1=0 State0=0
PORTB=0x00;
DDRB=0xFF;

// Port C initialization
// Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTC=0x00;
DDRC=0x00;

// Port D initialization
// Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out
// State7=0 State6=0 State5=0 State4=0 State3=0 State2=0 State1=0 State0=0
PORTD=0xC0;
DDRD=0x3F;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 0,976 kHz
// Mode: norm
// OC0A output: Disconnected
// OC0B output: Disconnected
TCCR0A=0x00;
TCCR0B=0x05;
TCNT0=0x00;
OCR0A=0x00;
OCR0B=0x00;

// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: 0,976 kHz
// OC2A output: Disconnected
// OC2B output: Disconnected
ASSR=0x00;
TCCR2A=0x00;
TCCR2B=0x07;
TCNT2=0x00;
OCR2A=0x7D;
OCR2B=0x00;

// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// Interrupt on any change on pins PCINT0-7: Off
// Interrupt on any change on pins PCINT8-14: Off
// Interrupt on any change on pins PCINT16-23: Off
EICRA=0x00;
EIMSK=0x00;
PCICR=0x00;

// Timer/Counter 0 Interrupt(s) initialization
TIMSK0=0x01;
// Timer/Counter 1 Interrupt(s) initialization
TIMSK1=0x00;
// Timer/Counter 2 Interrupt(s) initialization
TIMSK2=0x03;

// Global enable interrupts
#asm("sei")

while (1)
{
new_reg = 2*!PIND.6+!PIND.7;
if (old_reg!=new_reg) regul();
old_reg=new_reg;
}; }

Re: прерывания таймеров-баги с ритмом

Добавлено: Пн июн 03, 2013 20:53:05
blackx
Объявите глобальные переменные как volatile.

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

volatile char serv_num=1, count, old_reg, new_reg, reg=127;

Re: прерывания таймеров-баги с ритмом

Добавлено: Вт июн 04, 2013 07:25:55
andrikll
Ну чтож, моргания стали более редкими. Теперь нет в морганиях ритмичного рисунка. Почитал про волатил-интерсно, буду знать, все равно спасибо за совет.
Что еще можно сделать? понимаю что это программный вывод, но может есть еще способы что то улучшить (убрать сбои с морганиями)

Re: прерывания таймеров-баги с ритмом

Добавлено: Вт июн 04, 2013 07:54:38
Kavka
Касательно vilatile - не обязательно все переменные объявлять volatile. Точно надо объявлять те, которые используются и в обработчике прерывания и в основной программе.
С ходу не понял логики изменения reg. Но возникло предположение, что оно меняется очень часто и намного чаще чем частота ШИМа.

Re: прерывания таймеров-баги с ритмом

Добавлено: Вт июн 04, 2013 08:30:27
blackx
Я вот тоже не понял алгоритма работы, хоть убейте :kill:
Упростите свою программу, постарайтесь сначала без всяких дополнительных счетчиков запрограммировать определенную скважность сигнала (например, 30%), и убедиться, что ничего не мерцает. А у вас судя по поведению светодиода где-то постоянно перезаписывается регистр сравнения неверным значением.

Re: прерывания таймеров-баги с ритмом

Добавлено: Вт июн 04, 2013 09:02:15
andrikll
Ясно. Даю доплнительные объяснения. Никакие счетчики не работают в данный момент. Reg это переменная инкрементного энкодера который каи видно из программы задает оср2 (скважность шим) Режим самого шим выбран "нормал" то есть счет полный от 0 до 255. в момент съемки шим не меняет значения. Для отображения величины шим установил 5 диодов указывающих верхние биты величины оср2 (все стоит на месте и никуда не считает, не бежит). В переполнении счетчика задаем 1 на светодиод в прерываниипо оср2 задаем сброс. при этом если шим на максимуме то обратная картина, диод горит ярко и моргает провалами свечения.....спустя 10 мин.... сделаю сейчас так, удалю основную часть проги (отображение диодами величины оср2, на листинге не показано) удалю все и оставлю только 2 прерывания на частоте 976 Гц (проц 1 мГц)....отпишусь

Прошли долгие 2 минуты ну что же похоже на равномерное 3- герцовое подергивание яркости при оср2а=0f (976/256=3,81 Гц) все кажись в норме теперь... только голая программа то мне не нужна. что делать? Проблемма явно с присвоением оср2а значений. Пробую добавить программу и не трогать оср....

Спустя несколько часов Вобще какая то ерунда. оср2а не регулируется но каждый поворот энкодера это то ярче то бледнее диод. и счет reg стоит на месте.

Re: прерывания таймеров-баги с ритмом

Добавлено: Чт июн 06, 2013 17:48:32
andrikll
Вобщем с каким либо текстом основной программы еще не моргало, с функциями начало моргать. (может и не зависит так четко, но так было мной замечено)

Re: прерывания таймеров-баги с ритмом

Добавлено: Пн июн 10, 2013 11:39:44
andrikll
ау? эни бади?

Re: прерывания таймеров-баги с ритмом

Добавлено: Пн июн 10, 2013 12:44:42
ibiza11
вот хэппенд, дюд?

Re: прерывания таймеров-баги с ритмом

Добавлено: Пн июн 10, 2013 16:45:32
andrikll
ай нид хэлп бат ай э литл стьюпед.

Re: прерывания таймеров-баги с ритмом

Добавлено: Вт июн 11, 2013 08:09:58
Kavka
:) Ok. It's clear now that you are smart enough to accept critics. So, reread again all comments above and write down flow diagram (or algorithm) of your task. Then think again. And then we will talk in russian. :))

Re: прерывания таймеров-баги с ритмом

Добавлено: Вс янв 05, 2014 00:16:10
andrikll
Не знаю что там не работало, заработало после полного переосмысления и написания программки заново.
Спойлер

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

#include <mega48.h>
volatile char portB_sost[8]={0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}, ocra0_servo[8];
unsigned char servo_n, old_reg, new_reg, i;
unsigned int sechenie_soplo, soplo_sum;
 
 
 void port_b (void) 
{  
PORTB=portB_sost[i];   
OCR0A=ocra0_servo[i];  
i++;  
soplo_sum+=ocra0_servo[i];
if (i>8) {i=1; soplo();  sechenie_soplo=soplo_sum; soplo_sum=0;} 
}    
 
void port_b0 (void)
  {
   PORTB=0x00;
  }


 
// Timer 0 overflow interrupt service routine
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{  
port_b();
// Reinitialize Timer 0 value
}

// Timer 0 output compare A interrupt service routine
interrupt [TIM0_COMPA] void timer0_compa_isr(void)
{
port_b0();   
}

   void encoder (void)
   { 
          if (old_reg==0) {if(new_reg == 3) ocra0_servo[servo_n]++;  if(new_reg == 1) ocra0_servo[servo_n]--; } 
          if (old_reg==1) {if(new_reg == 0) ocra0_servo[servo_n]++;  if(new_reg == 3) ocra0_servo[servo_n]--; }
          if (old_reg==3) {if(new_reg == 1) ocra0_servo[servo_n]++;  if(new_reg == 0) ocra0_servo[servo_n]--; }  
          if ( ocra0_servo[servo_n]<80)  ocra0_servo[servo_n]=80;
          if ( ocra0_servo[servo_n]>253) ocra0_servo[servo_n]=253;
   }

          void regul (void)
          {
           encoder();
          if (old_reg>3)  servo_n++;
 
          switch (servo_n) {
          case 1: servo_n=1; encoder(); break;
          case 2: servo_n=2; encoder(); break;
          case 3: servo_n=3; encoder(); break;
          case 4: servo_n=4; encoder(); break;
          case 5: servo_n=5; encoder(); break;
          case 6: servo_n=6; encoder(); break;
          case 7: servo_n=7; encoder(); break;
          case 8: servo_n=8; encoder(); break;   //znacheniya povorota servo zaslonok
                           }; 
          }     
          
          

void main(void)
{
// Declare your local variables here
port_b();
// Crystal Oscillator division factor: 1
#pragma optsize-
CLKPR=0x80;
CLKPR=0x00;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif

// Input/Output Ports initialization
// Port B initialization
// Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out 
// State7=0 State6=0 State5=0 State4=0 State3=0 State2=0 State1=0 State0=0 
PORTB=0x00;
DDRB=0xFF;

// Port C initialization
// Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In 
// State6=T State5=T State4=T State3=T State2=T State1=T State0=T 
PORTC=0x00;
DDRC=0x00;

// Port D initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In 
// State7=P State6=P State5=T State4=T State3=T State2=T State1=T State0=T 
PORTD=0xC0;
DDRD=0x00;


// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 125,000 kHz
// Mode: Normal top=FFh
// OC0A output: Disconnected
// OC0B output: Disconnected
TCCR0A=0x00;
TCCR0B=0x03;
TCNT0=0x00;
OCR0A=0x90;
OCR0B=0x00;

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: Timer 1 Stopped
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x00;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;

// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer 2 Stopped
// Mode: Normal top=FFh
// OC2A output: Disconnected
// OC2B output: Disconnected
ASSR=0x00;
TCCR2A=0x00;
TCCR2B=0x00;
TCNT2=0x00;
OCR2A=0x00;
OCR2B=0x00;

// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
// Interrupt on any change on pins PCINT0-7: Off
// Interrupt on any change on pins PCINT8-14: Off
// Interrupt on any change on pins PCINT16-23: Off
EICRA=0x00;
EIMSK=0x00;
PCICR=0x00;

// Timer/Counter 0 Interrupt(s) initialization
TIMSK0=0x03;
// Timer/Counter 1 Interrupt(s) initialization
TIMSK1=0x00;
// Timer/Counter 2 Interrupt(s) initialization
TIMSK2=0x00;

// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
ADCSRB=0x00;

// Global enable interrupts
#asm("sei")  

while (1)
      {
      new_reg = 4*!PIND.5+2*!PIND.6+!PIND.7; 
      if (old_reg!=new_reg) regul(); 
      old_reg=new_reg;  
 
      }; 


}
Промежуточный вариант, но энекодером крутились сервы нормально. Угол не полный (почти уверен из за отсутствия кварца), но работает. Если будет кому интересно схемку и окончательную реализацию докину, когда можно будет управлять 8-ю сервами с помощью энкодера, переключаясь между ними нажатием на энкодер или любую отдельную кнопку..