Stránka 1 z 2

ATmega128 - funguje mi jen jedno PWM

Napsal: 07 bře 2009, 13:11
od endthe
Zdravim snazim se udelat program pro ATmega128 pro ovladani dvou serv HS 422 pripojenych na PB5 (OC1A) a PB6 (OC1B). ovladaní je pomoci PWM rizeneho tlacitky (krokovani UP a DOWN pro kazde servo (pres interupty na portu D)). Problem je v tom ze mi jede pouze jedno PWM na OC1A a nedari se mi rozchodit druhe PWM na OC1B :( . Prikladam i zdrojak. Prosim o radu a celkem to specha. Dekuji

kod programu mam nasledujici v AVR studio 4:

Kód: Vybrat vše

/**************************************************************
Project : PWM
Version : 1.0
Date    : 21.2.2009
Author  :
Comentar: manualni PWM - melo by se dat ritit pomoci tlacitek
Pouzita serva: HS-422
Chip type           : ATmega128
Program type        : Application
Clock frequency     : 16,000000 MHz
Memory model        : Small
External RAM size   : 0
Data Stack size     : 1024
**************************************************************/
#include <avr/io.h>
#include <avr/iom128.h>
#include <avr/interrupt.h>
//#####################################################################
#define NSTEP 10
#define NDELAY 100 //bylo tu 500
int isdelay = 0;
//######################TLACITKA PRO SERVO 1################################

//###########################INT0 UP###########################
ISR (SIG_INTERRUPT0)
{

if (isdelay)
return;

PORTB=~PORTB; //pro kontrolu funce (ostatni LED na portu B blikaji)

 int tmp=(int)OCR1A;
 if ((tmp+NSTEP)<255)
   OCR1A+=NSTEP;
 else
   OCR1A=255;

   isdelay=1;
}

//###########################INT1 DOWN###########################
ISR (SIG_INTERRUPT1)
{

if (isdelay)
return;

PORTB=~PORTB; //pro kontrolu funce (ostatni LED na portu B blikaji)

 int tmp=(int)OCR1A;
 if ((tmp-NSTEP)<0)
   OCR1A-=NSTEP;
   
 else
   OCR1A=0;

   isdelay=1;
}

//######################TLACITKA PRO SERVO 2################################

//###########################INT2 UP###########################
ISR (SIG_INTERRUPT2)
{

if (isdelay)
return;

PORTB=~PORTB; //pro kontrolu funce (ostatni LED na portu B blikaji)

 int tmp=(int)OCR1B;
 if ((tmp+NSTEP)<255)
   OCR1B+=NSTEP;
   
 else
   OCR1B=255;
   
   isdelay=1;
}


//###########################INT3 DOWN###########################
ISR (SIG_INTERRUPT3)
{

if (isdelay)
return;

PORTB=~PORTB; //pro kontrolu funce (ostatni LED na portu B blikaji)

 int tmp=(int)OCR1B;
 if ((tmp-NSTEP)<0)
   OCR1B-=NSTEP;
 else
   OCR1B=0;

   isdelay=1;
}

//#####################################################################

void preruseni_init(void) // uvodni nastaveni podminek pro povoleni preruseni
{
  EICRA = 0;
  EIMSK = 0x0f;
  SREG |= (1<<SREG_I);
}

//#####################################################################

void delay(unsigned int msec);

//#####################################################################

int main(void)
{
  DDRB = 0x61; //povoleni portu PB5 a PB6 jako vystup PWM (OC1A a OC1B)
  DDRD = 0;    //Porty D jako vstupy (interupty nastavene pro tlacitka 1-4)
  PORTD = 0xff;
  preruseni_init();

//######################PWM PRO SERVO 1################################
 
ICR1=20000; //nastavenim ICR1=20000 dosahnu f=50Hz

TCCR1A|=(0<<COM1A0)|(1<<COM1A1)|(0<<COM1B0)
|(0<<COM1B1)|(0<<FOC1A)|(0<<FOC1B)|(1<<WGM11)|(0<<WGM10);
 
TCCR1B|=(0<<ICNC1)|(0<<ICES1)|(1<<WGM13)|(1<<WGM12)
| (0<<CS12)|(1<<CS11)|(0<<CS10);

//######################PWM PRO SERVO 2################################
ICR1=20000; //nastavenim ICR1=20000 dosahnu f=50Hz

TCCR1B|=(0<<COM1B0)|(1<<COM1B1)|(0<<COM1C0)
|(0<<COM1C1)|(0<<FOC1B)|(0<<FOC1A)|(1<<WGM11)|(0<<WGM10);


TCCR1C|=(0<<ICNC1)|(0<<ICES1)|(1<<WGM13)|(1<<WGM12)
| (0<<CS12)|(1<<CS11)|(0<<CS10);


//#####################################################################

  while(1) {
   if (isdelay)
    delay(NDELAY);
   };
 }

//#####################################################################

//void PWM(unsigned char motor1, unsigned char motor2)
//{
//   OCR1A = motor1; // Vystup servo 1
//   OCR1B = motor2; // Vystup servo 2
//}

//#####################################################################

void delay(unsigned int msec) {
 int unsigned i,n;
 for (i=msec;i>0;i--) {
  for (n=100;n>0;n--);
 }
 isdelay=0;
}


:arrow: administrator: přejmenováno z "ATmega128 PWM"

Napsal: 07 bře 2009, 13:30
od Andrea
V nastavení máš pomotané registry TCCR1A, B a C.

A jestli dobře počítám, tak ti to při 16MHz generuje 100Hz a ne 50.

Napsal: 07 bře 2009, 13:40
od endthe
takze by to melo jit takto:

Kód: Vybrat vše

//######################PWM PRO SERVO 1################################
 
ICR1=20000; //nastavenim ICR1=20000 dosahnu f=50Hz

TCCR1A|=(0<<COM1A0)|(1<<COM1A1)|(0<<COM1B0)
|(0<<COM1B1)|(0<<FOC1A)|(0<<FOC1B)|(1<<WGM11)|(0<<WGM10);
 

//######################PWM PRO SERVO 2################################
ICR1=20000; //nastavenim ICR1=20000 dosahnu f=50Hz

TCCR1B|=(0<<COM1B0)|(1<<COM1B1)|(0<<COM1C0)
|(0<<COM1C1)|(0<<FOC1B)|(0<<FOC1A)|(1<<WGM11)|(0<<WGM10);



//#####################################################################

Napsal: 07 bře 2009, 13:41
od endthe
endthe píše:takze by to melo jit takto:

Kód: Vybrat vše

//######################PWM PRO SERVO 1################################
 
ICR1=20000; //nastavenim ICR1=20000 dosahnu f=50Hz

TCCR1A|=(0<<COM1A0)|(1<<COM1A1)|(0<<COM1B0)
|(0<<COM1B1)|(0<<FOC1A)|(0<<FOC1B)|(1<<WGM11)|(0<<WGM10);
 

//######################PWM PRO SERVO 2################################
ICR1=20000; //nastavenim ICR1=20000 dosahnu f=50Hz

TCCR1B|=(0<<COM1B0)|(1<<COM1B1)|(0<<COM1C0)
|(0<<COM1C1)|(0<<FOC1B)|(0<<FOC1A)|(1<<WGM11)|(0<<WGM10);



//#####################################################################


ja to delal podle datasheetu

Napsal: 07 bře 2009, 13:47
od Andrea
Jestli to děláš podle datašítu, tak nevím podle kterého, protože to máš pořád stejně blbě.

Napsal: 07 bře 2009, 13:49
od endthe
Andrea píše:Jestli to děláš podle datašítu, tak nevím podle kterého, protože to máš pořád stejně blbě.



no primo od atmela ale je mozne ze sem se do toho zamotal tak porad co opravit

Napsal: 07 bře 2009, 13:58
od Andrea
endthe píše:
Andrea píše:Jestli to děláš podle datašítu, tak nevím podle kterého, protože to máš pořád stejně blbě.



no primo od atmela ale je mozne ze sem se do toho zamotal tak porad co opravit

V datašítu jsou přece ty tři registry rozkreslené na jednotlivé bity, tak do nich strkej jen co do nich patří. Nebo kde vidíš, že FOC1A a FOC1B patří do TCCR1A, že COM1B patří do TCCR1A i do TCCR1B?

Napsal: 07 bře 2009, 14:02
od endthe
ja se ridil taky pomoci http://winavr.scienceprog.com/example-a ... g-avr.html

akorad sem ty tlacitka dal na interupty

Napsal: 07 bře 2009, 14:05
od Andrea
endthe píše:ja se ridil taky pomoci http://winavr.scienceprog.com/example-a ... g-avr.html

akorad sem ty tlacitka dal na interupty

Nojo, ale cpeš to do megy128, tak musíš koukat do datašítu megy128.

Napsal: 07 bře 2009, 14:06
od endthe
to prvni PWM jede ale to druhe ne :( a uz sem z toho zoufalej zas tak moc ty atmely neumim

Napsal: 07 bře 2009, 14:13
od endthe

Kód: Vybrat vše

//######################PWM PRO SERVO 1################################
 
ICR1=20000; //nastavenim ICR1=20000 dosahnu f=50Hz

TCCR1A|=(0<<COM1A0)|(1<<COM1A1)|(0<<COM1B0)
|(0<<COM1B1)|(1<<WGM11)|(0<<WGM10);


//######################PWM PRO SERVO 2################################
ICR1=20000; //nastavenim ICR1=20000 dosahnu f=50Hz

TCCR1B|=(0<<COM1B0)|(1<<COM1B1)|(0<<COM1C0)
|(0<<COM1C1)|(1<<WGM11)|(0<<WGM10);



//#####################################################################


takze by to melo byt takto?

Napsal: 07 bře 2009, 14:19
od Andrea
Ne, podíval ses do toho datašítu ATmega128?
Kde v něm vidíš, že registr TCCR1B obsahuje bity COM1B0, COM1B1, COM1C0, COM1C1, WGM11, WGM10? Já vidím toto:

Napsal: 07 bře 2009, 14:24
od endthe

Kód: Vybrat vše

TCCR1B|=(0<<ICNC1)|(0<<ICES1)|(1<<WGM13)|(1<<WGM12)|(0<<CS12)|(1<<CS11)|(0<<CS10);


no tim padem takto

Napsal: 07 bře 2009, 14:35
od endthe
jinak uz me to nenapada :?

Napsal: 07 bře 2009, 14:43
od Andrea
No sláva a ještě co do TCCR1A.