Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.

AT90USB162 timer interupt svakih 0.1ms?

[es] :: Elektronika :: Mikrokontroleri :: AT90USB162 timer interupt svakih 0.1ms?

Strane: 1 2

[ Pregleda: 4743 | Odgovora: 22 ] > FB > Twit

Postavi temu Odgovori

Autor

Pretraga teme: Traži
Markiranje Štampanje RSS

Genie_1984
Novi Sad

Član broj: 61150
Poruke: 93



+1 Profil

icon Re: AT90USB162 timer interupt svakih 0.1ms?09.09.2011. u 22:01 - pre 153 meseci
"By default the AT90USB uses an internal osc at 8Mhz with the DIV8 fuse on (so 1MHz clock)."

To znači da ti uC radi na taktu od 1Mhz, znači u avrcalc kucaš tu vrednost kristala

kao preskaler stavi 1 a TCNT0=0x9c za interapt od 100uS. za 10uS ima grešku (tačna vrednost bude 11.11us) tako da je bolje 100us

FUSE biti se ne mogu menjati učitavanjem HEX fajla nego samo direktnim programiranjem

PS. AvrCalc koji ti koristiš brljavi. Koristi ovaj http://www.avrfreaks.net/index...=292&module=Freaks%20Tools

[Ovu poruku je menjao Genie_1984 dana 09.09.2011. u 23:40 GMT+1]
 
Odgovor na temu

endre85

Član broj: 207893
Poruke: 325



+116 Profil

icon Re: AT90USB162 timer interupt svakih 0.1ms?09.09.2011. u 22:47 - pre 153 meseci
Skontao sam to za fuse bitove, zato sam i postavio, ali izgleda da ima neka caka sa CLKPR.

Inace nece ni sad da radi. Bas je deprimirajuce. Ali mislim da negde drugde gresim (ili jos negde). Ja bih rekao da uopste ne generisem bilokakav pwm. Za _THRESHOLD = 30 i ispod diode konstantno svetle (malopre sam podizao za po jedan i prestalo je kod 36), cim predjem taj neki prag od 3X diode se nikad ni ne upale, a ni servo ne reaguje, da ima bar nekakvog pwm-a makar i pogresnog onda bi otisao skroz na jednu stranu i hteo bi da ide dalje od blokade. Ali nista, mogu slobodno da ga okrecem rukom.


Code:


const int _THRESHOLD = 30; //185
//char counter;
unsigned int counter;
int counter2;

void Timer0Overflow_ISR() org IVT_ADDR_TIMER0_OVF
{
// Reinitialize Timer 0 value
//TCNT0=0xF6;
TCNT0=0x9c;
counter++;
counter2++;

    if (counter2==200)
    {
         counter2=0;
    }
  //  if(counter==41)
   // {
   // PORTD=0xFF;
    //PORTD= ~PORTD;
  //  counter=0;
  //  }
  
  //if (counter == 10)
  //{
  //    PORTD= ~PORTD;
  //    counter = 0;
  //}

  if (counter2 >= _THRESHOLD)
 {
   PORTD = 0xFF;             // toggle PORTd
    PORTC = 0xFF;
//    PORTC.B2=1;
 }
  else
{
   PORTD = 0x00;
  PORTC = 0x00;
// /  PORTC.B2=0;
 }
}

void main() {

  //CLKSEL0.EXTE=1;
  //CLKSEL0.CLKS = 1;

   // set CLKPR bit to change clock prescaler
   //CLKPR = (1<<CLKPCE);
   // no clock prescaler
   //CLKPR = 0;


   ////////////////////////////////////////////////

  DDRD   =  0xFF;               // set PORTD as output
  DDRC   =  0xFF;
  PORTD  =  0x00;                  // clear PORTD
  PORTC  =  0x00;                  // clear PORTc

  SREG_I_bit = 1;               // Interrupt enable
  TOIE0_bit  = 1;               // Timer0 overflow interrupt enable
  //TIMSK0=0x01;                    //isto sto i gore

  TCCR0A=0x00;
  //TCCR0B=0x02;                   // Start timer with 8 prescaler
  TCCR0B=0x01;                   // Start timer with no (1) prescaler 0.1msec
  //TCNT0=0xF6;                  //za 8 mhz i 8 prescaler i 0.01msec
  TCNT0=0x9c;                    //za 1mhz i 1 prescaler i 0.1msec
  OCR0A=0x00;
  OCR0B=0x00;



  

  //TCCR0B=0x02;                   // Start timer with 8 prescaler

  counter=0;
  counter2=0;
  //da li ovde ide nesto od sledeca dva reda:
 //#asm("sei")
 //sei();
 //asm{sei};

  //sei();
  while (1)                     // Endless loop, port is changed inside Interrupt Service Routine (ISR)
    ;
}


Sto se tice kalkulatora, interesantno je da ni ovaj koji si ti preporucio ne prijavljuje gresku kada ukucam 0.01 msec, ali zato ima greske kad je 10usec. Kod ovog drugog nema ni tada. No, posto si iskusniji, poslusacu tvoju preporuku za avrcalc.
 
Odgovor na temu

endre85

Član broj: 207893
Poruke: 325



+116 Profil

icon Re: AT90USB162 timer interupt svakih 0.1ms?13.10.2011. u 18:19 - pre 152 meseci
OK, ostao sam duzan da postavim kod.

Code:

/*
 * Project name:
     LED_Blinking (Simple 'Hello World' project)
 * Copyright:
     (c) Mikroelektronika, 2010.
 * Revision History:
     20080930:
       - initial release;
 * Description:
     This is a simple 'Hello World' project. It turns on/off diodes connected to
     PORTA, PORTB, PORTC and PORTD.
 * Test configuration:
     MCU:             ATmega16
                      http://www.atmel.com/dyn/resources/prod_documents/doc2466.pdf
     dev.board:       easyavr6 -
                      http://www.mikroe.com/eng/prod...1/easyavr6-development-system/
     Oscillator:      External Clock 08.0000 MHz
     Ext. Modules:    -
     SW:              mikroC PRO for AVR
                      http://www.mikroe.com/eng/products/view/228/mikroc-pro-for-avr/
 * NOTES:
     - Make sure you turn ON the PORTA, PORTB, PORTC and PORTD LEDs (SW8.1, SW8.2, SW8.3 and SW8.4).
*/
#include <string.h> //vidi za string funkcije u ovoj bibilioteci

#define BUFF_SIZE 70 //40 da probamo sa 70 da bude velicina: 'SLOVOzaSERVO'XXX puta 17 => 4*17=68, plus karakter za kraj i jos nesto==70

char uart_rd;
int res;

unsigned char a[3];
typedef unsigned char byte;

bit t;
byte br_bajta,s,br_bajta2;
//byte output[4];
int output;
//byte dolazni;
int result;

//char SG;
int SG;
byte SG2[2];
byte SG3[2];
const char _THRESHOLD = 20;
char counter;
const int SMTH = 1250; //servo motor treshold
                       //1250*16 usec=20msec
int smcount;       //servo motor count
int j;
volatile long mer_time;

bit brzosporo;
//Pinovi na koje treba povezati odredjene servo motore
sbit ServoGLava at PORTB.B0;

sbit ServoLevaRukaRame at PORTB.B1;
sbit ServoLevaRukaLakat at PORTB.B2;
sbit ServoLevaRukaSaka at PORTB.B3;

sbit ServoDesnaRukaRame at PORTB.B4;
sbit ServoDesnaRukaLakat at PORTB.B5;
sbit ServoDesnaRukaSaka at PORTB.B6;

sbit ServoLevaNoga1 at PORTB.B7;   //neka 1 bude u torsu
sbit ServoLevaNoga2 at PORTC.B1;
sbit ServoLevaNoga3 at PORTC.B2;
sbit ServoLevaNoga4 at PORTC.B3;
sbit ServoLevaNoga5 at PORTC.B4;

sbit ServoDesnaNoga1 at PORTC.B5;  //neka 1 bude u torsu
sbit ServoDesnaNoga2 at PORTC.B6;
sbit ServoDesnaNoga3 at PORTC.B7;
sbit ServoDesnaNoga4 at PORTD.B0;
sbit ServoDesnaNoga5 at PORTD.B1;

//vrednosti pri kojima se postavlja nizak logicki nivo za zadati servo
volatile char trVrednostiFIServa[7];

volatile int glavafi;

volatile int lrrfi;   //LevaRukaRameFaktorIspune
volatile int lrlfi;
volatile int lrsfi;

volatile int drrfi;   //DesnaRukaRameFaktorIspune
volatile int drlfi;
volatile int drsfi;

/*
volatile int ln1fi;   //LevaNoga1FaktorIspune
volatile int ln2fi;
volatile int ln3fi;
volatile int ln4fi;
volatile int ln5fi;

volatile int dn1fi;   //DesnaNoga1FaktorIspune
volatile int dn2fi;
volatile int dn3fi;
volatile int dn4fi;
volatile int dn5fi;
*/
volatile char prijem[BUFF_SIZE];
volatile char brkar;
volatile char stiglaporuka;
//min fi je 34
//maks fi je 115

void initUSARTbyMIKROC();
//void initUSARTbyME( unsigned int );
void initUSARTbyME( unsigned int baud );
void initUC();
void demoBrzinaSM();
void demoBrzinaSM2();

void pocetnaPozicijaSM();
void pocetnaPozicijaSM_NIZ();

void testiranjeUART();
void ServoPosByUART();

void podesiServoPozicije();
void izvucipodatke();
void newline();

void delay_x16us(long dtime)
{
 mer_time=dtime;
 while(mer_time);
}


void UART1_Data_recive() org IVT_ADDR_USART1__RX
{
 char temp;
 temp=UDR1;
 prijem[brkar]=temp;
 brkar++;
 prijem[brkar]='\0'; //oznacava da je u pitanju string

 if(temp=='!') //to znaci da je stigao string sa ! koji odredjuje kraj korisne informacije
 {
  stiglaporuka=1;
 }

//prijem karaktera na serijski port
}

void Timer1Overflow_ISR() org IVT_ADDR_TIMER1_OVF
{
  //Interapt na svakih 16 uS
  TCNT1H = 0xff;
  TCNT1L = 0x80;


  smcount++;

  //Kratko pojasnjenje:
  //Generisemo interapt svakih 16 usec, kada i povecavamo brojace
  //glavni brojac (smcount) koji ujedno i predstavlja jednu periodu rada servo motora
  //se resetuje na otp svakih 20 msec
  //Pomocu njega odredjujemo faktor ispune odredjenih servo motora
  //u smislu da se na pinove postavlja visok logicki nivo na pocetku periode,
  //a spusta se na nizak kada se odredjena promenljiva servo motora imau
  //vrednost jednaku sa sa glavnim brojacem
 
/*
  for(j=0;j<4;j++)
  {
    if(smcount>trVrednostiFIServa[j])
    {
       switch (j)
       {
         case 0:    ServoGLava=0;
         break;
         case 1:    ServoLevaRukaRame=0;
         break;
         case 2:    ServoLevaRukaLakat=0;
         break;
         case 3:    ServoLevaRukaSaka=0;
         break;
//         case 5:
//         break;
//         case 6:
//         break;

       }
    }
  }
*/



//IMPORTANT
//Saovakvim principom rada interapta, 4 motora su otprilike maxumum za OK rad
//Prelazak na nizak nivo glave
///*
  if(smcount>trVrednostiFIServa[0])
  {
   ServoGLava=0;
  }
//*/

///*
//Prelazak na nizak nivo leve ruke
  if(smcount>trVrednostiFIServa[1])
  {
   ServoLevaRukaRame=0;
  }
   if(smcount>trVrednostiFIServa[2])
  {
   ServoLevaRukaLakat=0;
  }
  if(smcount>trVrednostiFIServa[3])
  {
   ServoLevaRukaSaka=0;
  }
//*/
/*
//Prelazak na nizak nivo desne ruke
  if(smcount>drrfi)
  {
   ServoDesnaRukaRame=0;
  }
   if(smcount>drlfi)
  {
   ServoDesnaRukaLakat=0;
  }
  if(smcount>drsfi)
  {
   ServoDesnaRukaSaka=0;
  }

*/
/*

//Prelazak na nizak nivo leve noge
  if(smcount>ln1fi)
  {
   ServoLevaNoga1=0;
  }
   if(smcount>ln2fi)
  {
   ServoLevaNoga2=0;
  }
  if(smcount>ln3fi)
  {
   ServoLevaNoga3=0;
  }
   if(smcount>ln4fi)
  {
   ServoLevaNoga4=0;
  }
  if(smcount>ln5fi)
  {
   ServoLevaNoga5=0;
  }
//Prelazak na nizak nivo desne noge
  if(smcount>dn1fi)
  {
   ServoDesnaNoga1=0;
  }
   if(smcount>dn2fi)
  {
   ServoDesnaNoga2=0;
  }
  if(smcount>dn3fi)
  {
   ServoDesnaNoga3=0;
  }
   if(smcount>dn4fi)
  {
   ServoDesnaNoga4=0;
  }
  if(smcount>dn5fi)
  {
   ServoDesnaNoga5=0;
  }
*/

  if(smcount>SMTH) //ovde brojac dostize max vrednost, pa dizemo sve na kec na pocetku novog ciklusa
  {
    smcount=0;

    ServoGLava=1;

    ServoLevaRukaRame=1;
    ServoLevaRukaLakat=1;
    ServoLevaRukaSaka=1;
/*
    ServoDesnaRukaRame=1;
    ServoDesnaRukaLakat=1;
    ServoDesnaRukaSaka=1;
*/
/*
    ServoLevaNoga1=1;
    ServoLevaNoga2=1;
    ServoLevaNoga3=1;
    ServoLevaNoga4=1;
    ServoLevaNoga5=1;

    ServoDesnaNoga1=1;
    ServoDesnaNoga2=1;
    ServoDesnaNoga3=1;
    ServoDesnaNoga4=1;
    ServoDesnaNoga5=1;
*/

  }
  
  if(mer_time>0)
   mer_time--;
  else
   mer_time=0;

}


void main() {

  char i;
  initUC();
  initUSARTbyMIKROC();
  //initUSARTbyME(9600);

  //pocetnaPozicijaSM();
    pocetnaPozicijaSM_NIZ();

/*
  SG='@';
  t=0;
  brzosporo=0;
  br_bajta=0;
  br_bajta2=1;
*/
  stiglaporuka=0;
  
  for(i=0;i<BUFF_SIZE;i++) //petlja za ciscjenje bafera
  {
   prijem[i]=0;
  }
  brkar=0;
 
  do {

      
      if(stiglaporuka)
      {
       stiglaporuka=0;
       izvucipodatke();
      }
//    demoBrzinaSM();
//    demoBrzinaSM2();
//    testiranjeUART();
//    ServoPosByUART();

     
  } while(1);            // Endless loop
}

void izvucipodatke()
{
 char fims[4];    //faktor ispune motora string
 char i;
 char fim[7];     //faktor ispune motora
 int rbm,trb;     //rbm - redni bronj motora; trb - trenutni broj
                  //pazi (prilikom slanja) da trb ne sme biti veci od 255
 char tk;         //trebalo bi da bude trenutni karakter

 for(i=0;i<7;i++) //7 motora, ima tako da upisujemo 7 vrednosti u niz
 //pre iscitavanja podataka iz bafera, upiseu nulu za svaku od 7 vrednosti
 {
  fim[i]=0;
 }
 
 for(i=0;i<BUFF_SIZE;i++)  //iscitavamo karakter po karakter iz bafera serijskog "porta"
 {
  tk=prijem[i];
  prijem[i]=0;             //optimizacija koda, odmah nakon iscitavanja odg karaktera, ovo postavljamo na nulu
  
  if(isalpha(tk))
  {
    rbm=tk-'A';                           //redni broj motora= (ASCII code trenutnog karaktera)-(ASCII code slova A); tako za A dobijemo 0, za B 1, za C 3, itd.
    //UART1_Write('s');                     //obavestenje da je stiglo slovo
    //UART1_Write(rbm+1+'0');               //provera koje slovo
    trb=0;                                //Posto je stiglo slovo, pripremamo se za prihvat brojeva koji ga slede, te trb "resetujemo"
  }
  else if(isdigit(tk))                    //ispitivanja da le je trenutni karakter broj, i ako jeste:
  {
    trb*=10;    //Zasto mnozim trb, kada je on nula??????
    trb+=tk-'0';
    fim[rbm]=trb;   //Menjamo podatke za koje je stigla nova informacija o servu
    //UART1_Write(trb);
  }
 }
 
 for(i=0;i<7;i++)
 {
  if (fim[i]>0) //mala zastita kako ne bi prepisao prethodne vrednosti na nesto nepozeljno
                //mozda cak da stavim (fim[i]>30 && fim[i]<115)
  trVrednostiFIServa[i]=fim[i];
 }
 
/*for(i=0;i<7;i++)
 {
   UART1_Write('b');
   UART1_Write(fim[i]);
 }*/
 
 brkar=0;
}

void initUSARTbyMIKROC()
{

  UART1_Init(9600);               // Initialize UART module at 9600 bps
  
  //Setuj flag koji dozvoljava USART RX interupt
  RXCIE1_bit=1;
  //Delay_ms(100);                  // Wait for UART module to stabilize
  delay_x16us(6250);                //wait for 100msec
  PORTD.B5 = ~PORTD.B5;
  UART1_Write_Text("Start");  //radi testiranja
  
  delay_x16us(32500);
  PORTD.B5 = ~PORTD.B5;
}

void initUC()
{

   //MCUSR &= ~(1 << WDRF);
   //wdt_disable();
   
  DDRD = 0xFB;           // Set direction of PD2 to be input, the rest of PORTD output
  PORTD  = 0;
  DDRB = 0xFF;           // Set direction to be output
  PORTB  = 0;

  DDRC=0b11111110;   //DAKLE PORTC.B0 MORA OSTATI ULAZ. proveri semu
                     //na taj pin je vezan KRISTAL
  //DDRC = 0xFE;           // Set direction to be output
  PORTC  = 0;
  

  CLKPR = 0x80;
  CLKPR = 0x00;

  TCNT1H = 0xff;//100us
  TCNT1L = 0x80;
  SREG_I_bit = 1;               // Interrupt enable
  TOIE1_bit  = 1;               // Timer1 overflow interrupt enable
  TCCR1B = 1;                   // Start timer with 8 prescaler

}
void demoBrzinaSM()
{


     //PORTD = ~PORTD;
     PORTD.B6 = ~PORTD.B6;
     glavafi++;
     delay_x16us(3750); //1000 --> cekanje od 16 msec
                        //1250 --> cekanje od 20 msec
                        
     if(glavafi>114) //150
     {
      delay_x16us(31250);
      glavafi=35;//10;
      //delay_x16us(25600);  //~410 msec
      delay_x16us(62500);  //1000 msec
      delay_x16us(62500);
     }

}

void demoBrzinaSM2()
{


 if (brzosporo==0)
 {
     glavafi++;
     delay_x16us(3750); //1000 --> cekanje od 16 msec
                        //1250 --> cekanje od 20 msec

     if(glavafi>114)
     brzosporo=1;
 }
 if (brzosporo==1)
 {
     glavafi--;
     delay_x16us(10); //1000 --> cekanje od 16 msec


     if(glavafi<1)
     brzosporo=0;
 }
}

void pocetnaPozicijaSM()
{
    glavafi=35;//34 je minimalna vrednost koju konta. Sve idpod toga dolazi do ove pozicije, a ako je vec u ovoj onda se mrda
    //ServoGLava=1; //logicki visok napon na pin

    lrrfi = 45;
    //ServoLevaRukaRame = 1;
    lrlfi = 55;
    //ServoLevaRukaLakat = 1;
    lrsfi = 65;
    //ServoLevaRukaSaka = 1;
/*
    drrfi = 75;
    drlfi = 85;
    drsfi = 95;
*/
/*
    ln1fi = 65;
    ln2fi = 75;
    ln3fi = 85;
    ln4fi = 95;
    ln5fi = 105;

    dn1fi = 65;
    dn2fi = 75;
    dn3fi = 85;
    dn4fi = 95;
    dn5fi = 105;
*/
//    smcount=0; //razmisli da li je bolje da ovo stavljas pred DO
}

void pocetnaPozicijaSM_NIZ()
{
   trVrednostiFIServa[0]=45;

   trVrednostiFIServa[1]=65;
   trVrednostiFIServa[2]=85;
   trVrednostiFIServa[3]=105;
}
void initUSARTbyME( unsigned int baud )
{
//iz dokumentacije:
   PORTD.B5 = ~PORTD.B5;
/* Set baud rate */
   UBRR1H = (unsigned char)(baud>>8);
   UBRR1L = (unsigned char)baud;
/* Enable receiver and transmitter */
   UCSR1B = (1<<RXEN1)|(1<<TXEN1);
/* Set frame format: 8data, 2stop bit */
   UCSR1C = (1<<USBS1)|(3<<UCSZ10);

   delay_x16us(62500);
   PORTD.B5 = ~PORTD.B5;
}

void testiranjeUART()
{
     //testiranje uart-a
     if (UART1_Data_Ready())      // If data is received,
     {
     PORTD.B5 = ~PORTD.B5;
     //delay_x16us(6250);   //cekanje od 100msec
     uart_rd = UART1_Read();      //   read the received data,
     //delay_x16us(6250);
     UART1_Write(uart_rd);        //   and send data via UART
     }
}


void ServoPosByUART()
{
//jednostavna verzija
 /*
    ServoGLava=fim[0];

    ServoLevaRukaRame=fim[1];
    ServoLevaRukaLakat=fim[2];
    ServoLevaRukaSaka=fim[3];
*/
}

void podesiServoPozicije()
{

}
void newline(){
 UART1_Write(13); // Carriage Return
 UART1_Write(10); // Line Feed
}


Nisam izbacio visak u odnosu na prekid tajmera tj. same teme, mozda nekom zatreba.

Mala napomena najmanji prekid koji se moze generisati je 10usec i tada se moze upravljati samo jednim servom. Sada se prekid desava svakih 16usec i upravlja se sa 7 serva. Tek cu videti da li sa ovim prekidom tajmera mogu izgurati i malo komplikovanije upravljanje servo motorima pomocu serijskog.

Evo ga i mali program koji savrseno funkcionise u sprezi sa gornjim uC (upravlja servo motorima preko serijskog), pisan je u C sharp 2010:
http://www.2shared.com/file/t0...SerialServoComm_13okt2011.html



Hvala svima na pomoci.

Poz.

[Ovu poruku je menjao endre85 dana 13.10.2011. u 19:34 GMT+1]
 
Odgovor na temu

[es] :: Elektronika :: Mikrokontroleri :: AT90USB162 timer interupt svakih 0.1ms?

Strane: 1 2

[ Pregleda: 4743 | Odgovora: 22 ] > FB > Twit

Postavi temu Odgovori

Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.