Skocz do zawartości

Atmega8 sterowanie serwa na OC2


Pomocna odpowiedź

Napisano

Witam ! Muszę napisać program pozwalający mi na sterowanie serwem podpiętym do wyprowadzenia OC2 Atmegi8.

Bardzo proszę o sprawdzenie kodu, czy w ogóle zadziała. Jestem początkujący dlatego proszę o ograniczone zaufanie. Na razie skleciłem coś takiego:

#define F_CPU 1000000
#include <avr/io.h>

int main()
{


DDRB = 0xff; //konfiguracja portów

TCCR2 = (1<<CS21)I(1<<WGM20) //wyjscie ustawione na 8 bitowy PWM z korektą fazy, preskaler na 1 (nie wiem czy nie powinien być wyższy dla serwa)

ICR1 = 20000; //ustawienie okresu na 20ms(czestotliwosc 50Mz) (nie wiem czy to w ogóle tu ma być



OCR1A = 2000; //określenie czasu impUlsu

While(1)

{
//tutaj isntrukcje do sterowania serwem

}

}

__________

Komentarz dodany przez: Nawyk

Stosuj, proszę, znaczniki "code" przy pisaniu postów z kodem źródłowym

Po pierwsze wstawiaj kod w odpowiednich znacznikach. Będzie się go lepiej przeglądało.

Po drugie coś tutaj bardzo namieszałeś.

Wyjście OC2 to wyprowadzenie Timera 2. Musisz go odpowiednio skonfigurować i wprowadzić odpowiednie wartości do rejestrów ICR2 i OCR2. A Ty je wpisujesz do rejestrów Timera 1. Poza tym Timer 2 jest 8-bitowy więc musisz ustawić większy preskaler.

Jesteś początkujący, więc podam najprostsze rozwiązanie, które będzie ruszało serwem na PB3

ustaw timer: TCCR2 = 0b01101010;

Wartości ICR nie podawaj wogóle, po prostu wywal tę linię.

W pętli while podawaj wartości OCR2 oddzielone pętlą opóźniającą np:

OCR2 = 100;

_delay_ms(500);

OCR2 = 50;

_delay_ms(500);

Te wartości OCR powinny zadziałać, jednak popraw je zgodnie ze swoim serwem

Tak z innej mańki w kodzie masz błąd ortograficzny:p

Nie piszemy: (1<

Tylko: (1<

Dzięki za odpowiedź. Może jeszcze nie bardzo orientuję się w programowaniu w C, więc mogę się mylić, ale... Taką pętlę rozumiem jak działa, problem polega na tym, że w pętli while będę miał jeszcze obsługę przycisków sterujących wypełnieniem PWM'a. Szkoda, że nie napisałem tego wcześniej. Timera1 nie używam do serwa bo steruje on PWMem podwójnego mostka H l298. A potrzebuję jeszcze wysterować jakoś serwo na jednym uC. We wspomnianej pętli while są również inne instrukcje do obliczania wartości zmiennych itd. Podsumowując: W pętli while po kolei wykona się instrukcja podana przez ciebie generująca impuls do serwa, następnie program przejdzie do obsługi pozostałych instrukcji i zostawi ten impuls, a na serwo powinien on być podawany przez cały czas. Dobrze rozumuję?

Jeszcze gdybyś mógł wytłumaczyć mi co oznacza zapis: TCCR2 = 0b01101010, jeszcze się z takim nie spotkałem.

Hmm wszystkie instrukcje podane Ci przez kolegę deuther masz wpisać w funkcji main() przed pętlą while(). One się wykonują tylko raz. Te instrukcje nie generują PWM tylko ustawiają Timer 2 w odpowiedni tryb pracy. Później Timer 2 sam będzie generował impuls PWM. Na tym właśnie polega sprzętowe generowanie PWM, że nie musimy ręcznie tego robić tylko uruchamiamy i dalej już leci.

Tamten zapis o który pytasz na końcu to po prostu ustawienie odpowiednich bitów w rejestrze TCCR2. Tam gdzie jedynki do dany bit ma być ustawiony, a tam gdzie zera to ma być wyzerowany. Możesz to inaczej wpisać.

Na marginesie: w jaki sposób generujesz sygnał PWM licznikiem pierwszym do mostków, skoro nie rozumiesz sprzętowego generowania?? Robisz to programowo??

Jeszcze gdybyś mógł wytłumaczyć mi co oznacza zapis: TCCR2 = 0b01101010, jeszcze się z takim nie spotkałem.

"0b" oznacza, że jest to zapis bitowy, najpierw najbardziej znaczący bit. Mamy tutaj 8 bitów. Jeśli chciałbyś to zapisać heksadecymalnie to masz taki zapis: 0x6A albo w układzie dziesiętnym 106 🙂

Ogólnie jednak proponowałbym stosowanie takiego zapisu:

TCCR2 |= _BV(CS12) | _BV(WGM20)

Jest znacznie czytelniejszy 😉 Takie cuś ustawia bity CS12 i WGM20 w rejestrze TCCR2. CS12 i WGM20 to tak naprawdę zdefiniowane pod ładną nazwą numerki bitów, a _BV(bit) to to samo co (1<

deuther powiedz mi tylko czy to będzie działać jeśli w pętli while dalej zapiszę kolejne instrukcje np do zmiany wartości OCR2 poprzez przycisk i zmiana wartości PWM TIMERA1. Czy sterowanie serwa będzie działać poprawnie? Przecież impuls dla serwa powinien powtarzać się na okrągło (tak skrótowo myśląc). Rozumiem, że te wstrzymania _delay_ms pomiędzy OCR2 zastępują korektę częstotliwości której TIMER2 nie posiada. Bo sprzętowo z tego co mi wiadomo nie da się sterować serwa poprzez TIMER2.

Da się sprzętowo sterować serwo tmierem2, właśnie to robisz. Musisz zrozumieć jedną rzecz. Pętla while działa sobie oddzielnie i timer oddzielnie.To tak jak masz zegarek na ręce, włączasz stoper i on zaczyna zliczać, jednak główny zegar(główny program) pracuje nadal poprawnie, pokazuje Ci czas i date pomimo tego, że gdzieś "obok" napitala sobie stoper. Ważne jest to, że stoper włączyłeś gdzieś z poziomu głównego programu! I teraz tak, Twoja pętla wykonuje się co jakiś bardzo szybki czas (tym dłuższy, im dłuższe delayie powstawiasz). Pamiętając o tym, że stoper mogliśmy włączyć z poziomu programu, należy tutaj podkreślić, że parametrami JUŻ DZIAŁAJĄCEGO NIEZALEŻNIE TIMERA możesz sterować w tej głównej pętli (np zmieniając wypełnienie pwm OCR). W naszym wypadku funkcje delay nie mają nic wspólnego z częstotliwością sygnału (bo tę determinuje niezależny timer), określają one tylko czas w jakim serwo będzie w danym położeniu. Skutkiem ubocznym jest to, że ich obecność spowalnia szybkość pętli, a więc np reakcję guzików. Jeżeli zatem chcesz sterować położeniem serwa poprzez guziki, usuń sobie narazie delayie i do pętli while wstaw instrukcje z guzikami.

Jest to metoda bardzo prymitywna, jeżeli w miarę postępów przestanie Ci wystarczać, zacznij ogarniać temat przerwań😉

  • 2 tygodnie później...

Rozumiem jak to działa. Ale żebym dokładnie wytłumaczył o co chodzi musiałbym wstukać cały mój program i opisać projekt. Na razie pozostaję przy drugim uC. Przyda mi się do czegoś jeszcze. Ale do tematu wrócę. Może mi się to nie przyda w moim projekcie ale na pewno rozwinie 🙂 Teraz mam inny problem bardziej teoretyczny. Chciałbym zapytać skąd bierze się dzielenie częstotliwości pracy serwa przez 2. Teoretycznie impulsy jakie trzeba podawac na serwo wahają się w granicach od 0,3 ms do 2,7 ms. Ale w trybie PWM timera1 sterującym serwem trzeba je dzielić przez 2. Impulsy podawane powinny być co 20ms a w każdym projekcie z jakim się spotkałem czas ten wynosi 10ms. Mógłby mi ktoś wyjaśnić tę zaleźność? I drugie pytanie: Czy kąt obrotu serwa w zależności od długości podawanego ipulsu to zależność liniowa?

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