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

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • 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.