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

Обсуждаем контроллеры компании Atmel.
Ответить
Первый раз сказал Мяу!
Сообщения: 24
Зарегистрирован: Ср апр 24, 2013 22:27:51

Сообщение 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;
}; }
Реклама
Говорящий с текстолитом
Аватара пользователя
Сообщения: 1518
Зарегистрирован: Пт дек 28, 2012 21:56:46
Откуда: St. Petersburg

Сообщение blackx »

Объявите глобальные переменные как volatile.

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

volatile char serv_num=1, count, old_reg, new_reg, reg=127;
Изображение only pure true norwegian blackx Изображение
Реклама
Первый раз сказал Мяу!
Сообщения: 24
Зарегистрирован: Ср апр 24, 2013 22:27:51

Сообщение andrikll »

Ну чтож, моргания стали более редкими. Теперь нет в морганиях ритмичного рисунка. Почитал про волатил-интерсно, буду знать, все равно спасибо за совет.
Что еще можно сделать? понимаю что это программный вывод, но может есть еще способы что то улучшить (убрать сбои с морганиями)
Мудрый кот
Аватара пользователя
Сообщения: 1810
Зарегистрирован: Чт июн 10, 2010 08:55:35
Откуда: Сибирские Афины

Сообщение Kavka »

Касательно vilatile - не обязательно все переменные объявлять volatile. Точно надо объявлять те, которые используются и в обработчике прерывания и в основной программе.
С ходу не понял логики изменения reg. Но возникло предположение, что оно меняется очень часто и намного чаще чем частота ШИМа.
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Реклама
Эиком - электронные компоненты и радиодетали
Говорящий с текстолитом
Аватара пользователя
Сообщения: 1518
Зарегистрирован: Пт дек 28, 2012 21:56:46
Откуда: St. Petersburg

Сообщение blackx »

Я вот тоже не понял алгоритма работы, хоть убейте :kill:
Упростите свою программу, постарайтесь сначала без всяких дополнительных счетчиков запрограммировать определенную скважность сигнала (например, 30%), и убедиться, что ничего не мерцает. А у вас судя по поведению светодиода где-то постоянно перезаписывается регистр сравнения неверным значением.
Изображение only pure true norwegian blackx Изображение
Реклама
Первый раз сказал Мяу!
Сообщения: 24
Зарегистрирован: Ср апр 24, 2013 22:27:51

Сообщение 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 стоит на месте.
Реклама
Первый раз сказал Мяу!
Сообщения: 24
Зарегистрирован: Ср апр 24, 2013 22:27:51

Сообщение andrikll »

Вобщем с каким либо текстом основной программы еще не моргало, с функциями начало моргать. (может и не зависит так четко, но так было мной замечено)
Первый раз сказал Мяу!
Сообщения: 24
Зарегистрирован: Ср апр 24, 2013 22:27:51

Сообщение andrikll »

ау? эни бади?
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 1900
Зарегистрирован: Сб фев 21, 2009 13:11:40
Откуда: Москва

Сообщение ibiza11 »

вот хэппенд, дюд?
Ставим плюсы: )
Первый раз сказал Мяу!
Сообщения: 24
Зарегистрирован: Ср апр 24, 2013 22:27:51

Сообщение andrikll »

ай нид хэлп бат ай э литл стьюпед.
Мудрый кот
Аватара пользователя
Сообщения: 1810
Зарегистрирован: Чт июн 10, 2010 08:55:35
Откуда: Сибирские Афины

Сообщение 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. :))
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Первый раз сказал Мяу!
Сообщения: 24
Зарегистрирован: Ср апр 24, 2013 22:27:51

Сообщение 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-ю сервами с помощью энкодера, переключаясь между ними нажатием на энкодер или любую отдельную кнопку..
Ответить

Вернуться в «AVR»