LusoRobótica - Robótica em Português
Robótica => Discussão geral sobre robótica => Tópico iniciado por: Capeleiro em 14 de Março de 2011, 21:13
-
Gostaria que alguém me desse umas ideias de como controlar um servo com o timer0 do ATmega328.
Digo isto porque o que não falta por é informação de como o fazer para o timer1, e isso já consegui, mas precisava de fazer o mesmo para o de 8 bits.
No timer de 16 bits eu escolho o modo "Phase and Frequency Correct" ou "Fast PWM" e tenho o registo ICR1 que controla o TOP (e que faz variar a frequencia) e o OCR1x que faz variar a largura do pulso (e faz variar assim a posição do servo), mas no timer0, pelo que consegui perceber, só existe o OCR0x , ou então estou a ver as coisas mal.
Há alguma forma de fazer isto por hardware e com este timer?
-
Todos os timers têm o TOP, BOTTOM e o OCRxx.
Mas podes perder alguma resolução pelo que li pelas internets.
Se meteres no google avr servo timer 0 ou timer 2 vais encontrar um milhão de exemplos.
-
Boas Capeleiro
Eu uso isto num pic, o registo do timer é de 8 bits logo deve ser igual
Eu uso os 8 bits para ter resolução máxima, ou seja esses 8bits são para ir desde 0.5ms a 2.2ms.
O resto eu chamo de dead_servo_time que calculei para ser cerca de 0.5ms.
duty é o dutycycle que é deste 1 a 255 que equivale a 0.5ms a 2.2ms
while(1){
TMR2 = 1; //inicializa registo do timer
PR2 = dead_servo_time; //poe no periodo 0.5ms
PWM0 = 1; //poe o canal pwm0 a 1
TMR2IF = 0; //clear interrupt flag
while(!TMR2IF); //espera que tempo "morto" esteja completo
PR2 = (duty); //carrega o valor do pwm0
TMR2IF = 0; //clear interrupt flag
while(!TMR2IF); //espera tempo a on
PWM0 = 0; //apaga canal pwm
PR2 = (256 - duty); //espera tempo restante para fazer 2.2ms de periodo
TMR2IF = 0; //clear interrupt flag
while(!TMR2IF); //espera tempo a on
wait(20ms-duty(em ms)-dead_servo_time(em ms)
//esta funcao é imaginario, n tenh isto implementado mas é facil perceberes o que faz
//basicamente espera-te o resto do tempo para perfazer os 20ms de periodo do servo
}
Espero ter ajudado
Cumps
-
Boas Capeleiro
Eu uso isto num pic, o registo do timer é de 8 bits logo deve ser igual
Eu uso os 8 bits para ter resolução máxima, ou seja esses 8bits são para ir desde 0.5ms a 2.2ms.
O resto eu chamo de dead_servo_time que calculei para ser cerca de 0.5ms.
duty é o dutycycle que é deste 1 a 255 que equivale a 0.5ms a 2.2ms
while(1){
TMR2 = 1; //inicializa registo do timer
PR2 = dead_servo_time; //poe no periodo 0.5ms
PWM0 = 1; //poe o canal pwm0 a 1
TMR2IF = 0; //clear interrupt flag
while(!TMR2IF); //espera que tempo "morto" esteja completo
PR2 = (duty); //carrega o valor do pwm0
TMR2IF = 0; //clear interrupt flag
while(!TMR2IF); //espera tempo a on
PWM0 = 0; //apaga canal pwm
PR2 = (256 - duty); //espera tempo restante para fazer 2.2ms de periodo
TMR2IF = 0; //clear interrupt flag
while(!TMR2IF); //espera tempo a on
wait(20ms-duty(em ms)-dead_servo_time(em ms)
//esta funcao é imaginario, n tenh isto implementado mas é facil perceberes o que faz
//basicamente espera-te o resto do tempo para perfazer os 20ms de periodo do servo
}
Espero ter ajudado
Cumps
Muito bem!
Mas, o que acontece se houver uma prota série associada, e acabar de chegar uma string de 10 bytes ? ups... não é possivel ler.
WHILE (x); é um entrave num programa normal. Ou seja, o CPU fica PARADO/ESTÁTICO/MORTO, à espera que algo acabe de respirar.
Se estamos a falar de um PIC10, que a unica coisa que faz é controlar um servo, então menos mal. No entanto, será necessário dar info de qts Graus queremos.
TRABALHO DE CASA LOL ;D
------------------------
vamos converter esse código em interrupções. Vamos a ver o MAIN completamente livre! :)
8)
-
Obrigado pelas respostas, eu estava a tentar saber como controlar o valor do TOP, como fazia com o outro timer, mas percebi que não dá, mas posso dar a volta a isso: então aproveitando a ideia do FET_Destroyer, posso configurar uma ISR para uma interrupção de overflow do timer2 e configurar o mesmo primeiro para (por exemplo) 1ms e depois para 19ms (20ms - 1ms), quando se der a primeira interrupção coloco o pino LOW e quando se der a segunda coloco o pino HIGH. É isto, asena?
-
É isso mesmo.
E recarregas o PR2 com o valor que tu queres correspondente.
Crias as duas variaveis para o ON e o OFF, e no teu MAIN alteras os valores que lhes queres dar.
Assim, qd a tua ISR for chamada, os valores que carregares no PR2 são os novos.