Skocz do zawartości

[C][ATmega128] problem z pwm na serwo


Rozwiel

Pomocna odpowiedź

Witam

Od pewnego czasu próbuję się uporać ze sterowaniem serwomechanizmem i jestem w kropce bo niby wszystko powinno być ok a serwo nie obraca się ani o milimetr. Jedyne oznaki "życia" serwo daje kiedy się je wpina do płytki ciągnącej już zasilanie.

Teoretycznie serwo powinno sie wychylić w skrajne położenie a nic się nie dzieje :/

Kabel sygnału na PB5 oczywiście, zasilanie ciągnę z programatora (ISP).

#define F_CPU 8000000L

#include <avr/io.h>
#include <util/delay.h>


int main(void) {


_delay_ms(2000);


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

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

//preskaler 8, phase&freq control

DDRB = 0b00100000;
ICR1=10000;  


for (;;)
{OCR1A = 1000;}


}

ICR1 jest ustawione na 10 k ze względu na częstotliwość procka, zakres 0-180st powinien odpowiadać OCR1A od 500 do 1000.

Byłbym bardzo wdzięczny gdyby ktoś wypatrzył co jest nie tak 😉

Edit: aha, fuse są ustawione dobrze

[ Dodano: 31-03-2011, 19:29 ]

UPDATE:

wywaliłem ORy z inta

natomiast chyba jest coś źle z ICR/OCR

przeglądam dokumentację ale nie mogę wyniuchać gdzie się co konkretnie ustawia (w sensie który licznik)

[ Dodano: 31-03-2011, 20:11 ]

#define F_CPU 8000000L 

#include <avr/io.h> 
#include <util/delay.h> 


int main(void) { 


_delay_ms(2000); 


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

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

//preskaler 8, phase&freq control 

DDRB  = 0b01000000; 
ICR1  = 10000;  
OCR1B = 500; 


}

nie wiem czemu mówiąc szczerze to działa, wydawało mi się, że ICR1 jest powiązane z OCR1A a nie B

niemniej działa 🙂

Link do komentarza
Share on other sites

ICR1 powiązane jest z OCR1A/B/C

natomiast chyba jest coś źle z ICR/OCR

przeglądam dokumentację ale nie mogę wyniuchać gdzie się co konkretnie ustawia (w sensie który licznik)

Wszystko się zgadza dla twojej konfiguracji:do ICR ładujesz wartość max a do OCR to w którym kierunku ma się przesuwać serwo. " (w sensie który licznik)" to jest jeden licznik tylko różne wartości są porównywane właśnie te OCR1A/B/C.

Jeżeli mogę coś jeszcze zasugerować to zamiast

(1<

(0<

(0<

(0<

(0<

proponuję wersję

TCCR1A= _BV(COM1B1)

procek po resecie sam ustawia wszystko na 0 więc

0<<FOC1A

nie ma sensu. Poza tym mnie czasami twoje rozwiązanie nie działa, mimo że się kompiluje.

P.S. aktualnie też dłubie na 128 konstrukcję i obsłużyłem już wszystkie peryferia także w razie pytań możesz pisać na pw, bo jestem na bierząco

Link do komentarza
Share on other sites

(0<<COM1A1)| (0<<COM1B0)| 

Z takiego zapisu się nie korzysta. Jeżeli chcesz wyzerować jakiś bit w rejestrze to robi się to w taki sposób:

TCCR1A &=~(1<COM1A0) 

Ale jak kolega esiu_ pisał po uruchomieniu mikrokontrolera wartości w rejestrach przyjmują "0" więc jeżeli chcesz skonfigurować timer do pracy w trybie PWM wystarczy, że ustawisz odpowiednie bity w rejestrach.

Ale w twoim przypadku moim zdaniem problem leży gdzie indziej. Mianowice serwem steruje się za pomocą sygnału o częstotliwości 50Hz i wypełnieniu w zależności od serwa 1-2ms. W twoim przypadku przy kwarcu 8MHz i ustawieniu ICR1=10000 i preskalerze 8 zgodnie ze wzorem f=fclk/(N*(1+ICRx)) gdzie f to częstotliwość PWM, fclk - częstotliwość taktowania,N- preskaler otrzymujesz sygnał o częstotliwości ~100Hz. Wpisanie do rejestru ICR1 20000 powinno dać 50 Hz.

Idąc dalej skoro serwem steruje sie za pomocą sygnału o częstotliwości 50Hz i wypełnieniu 1-2ms czyli wypełnieniem sygnału w granicach 10-20% wartość rejestru OCR1B można zmieniać w zakresie 2000-4000 co powinno pozwolić na sterowanie serwem w całym zakresie oczywiście zależy to też od konkretnego modelu serwa. Spróbuj i napisz jakie rezultaty.

@Edit

Przed chwilą zauważyłem, że zmieniłeś post. Rejestr ICR1 jest powiązany z OCR1A i B ponieważ należą do tego samego timera. Możesz osobno zmieniać wartości w tych rejestrach dzięki czemu na wyjściach OC1A i OC1B uzyskasz PWM o odpowiednim wypełnieniu i tej samej częstotliwości.

Link do komentarza
Share on other sites

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.