Elektroda.pl
Elektroda.pl
X

Search our partners

Find the latest content on electronic components. Datasheets.com
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

[ATmega8515][C] - Generowanie sygnału PWM dla 6 (8) serw

sinsky_90 17 Jun 2013 13:59 1911 5
  • #1
    sinsky_90
    Level 2  
    Witam. Jak widać jest to mój pierwszy post na tym forum. Na wstępie chciałbym prosić o wyrozumiałość - jeżeli temat znalazł się w nieodpowiednim miejscu, popełniłem jakiś błąd w składni tytułu czy coś tego typy, prosiłbym moderatora o poprawkę i pouczenie jak w przyszłości uniknąć powielenia problemu.

    Jestem w trakcie pisania pracy inżynierskiej dotyczącej sterowania ręką robota. Niestety moja dotychczasowa praktyka w zakresie mikrokontrolerów ogranicza się do kilku-kilkunastu godzin spędzonych na zajęciach laboratoryjnych i trochę poza nimi. Ale do rzeczy. Ruchy palców oraz przegubu kciuka są sterowane za pomocą sześciu serw modelarskich. Sterowanie ich położeniem odbywać się będzie za pomocą ATmega8515 umieszczonego w zestawie STK-500 (takie przykazanie dostałem od promotora dla ułatwienia pracy). W trakcie pracy pojawiły się dwie koncepcje sterowania, które przedatawię w oddzielnych punktach. Niestety w obu przypadkach wystąpiły problemy.

    1. Jest to moja koncepcja. Polega ona na tym, że Timer0 działa w trybie CTC, generując przerwanie co 5ms. Na kanałach A oraz B Timera1 generowane są przebiegi PWM (w trybie fast PWM), również o okresie 5ms. Każdy kanał ma obsłużyć do 4 serw (stąd okres 5ms, nie zaś 20ms). W przerwaniu od CTC inkrementowana jest zmienna i oraz j. Odpowiadają one za wybór pinu (czyli serwa) na który dany impuls zostanie podany (również w przerwaniu od CTC). Podanie polega na sprawdzeniu wartości zmiennych i oraz j i zależnie od ich wartości w momencie pojawienia się impulsu na wyjściu kanału PWM (OC1A, OC1B) wystawieniu stanu wysokiego na odpowiedni pin portu B.
    W pętli głównej znajduje się obsługa switch'y (port A). Dwa switch'e odpowiadają za wybór numeru serwa (przy okazji zapalająć odpowiednią LEDę na porcie C dla sygnalizacji które serwo jest teraz obsługiwane), zaś dwa inne zależnie od wartości zmiennej nr_serwa za zwiększenie albo zmniejszenie szerokości impulsu (zmienne s1, s2, s3, s4, s5, s6 oraz sx z których wartości są potem przepisywane do OCR1A albo OCR1B).
    Tyle, jeżeli chodzi o ideę. W praktyce niestety wydaje się, że nic nie działa. Przy naciskaniu switch'y nie zapala się żadna LED'a. Po podłączeniu oscyloskopu pod wyjścia sprzętowego PWM (OC1A, OC1B) nie pojawiają się żadne impulsy (sygnał ciągle ma stan niski). O ile za pierwszy problem mógłbym zrzucić winę na to, że przerwania mogą odbywać się za szybko, żeby program główny coś wykonał, o tyle przecież na wyjściach OC1A/OC1B powinien być sprzętowo generowany jakikolwiek sygnał. Kod poniżej:
    Code: c
    Log in, to see the code



    2. Koncepcja mojego promotora, na razie jej opracowywanie jest w toku, ale już napotkałem na problemy. Polega ona na wykorzystaniu dwóch timerów w trybie CTC - jeden o okresie 20ms, ustawiający cały port w stan wysoki (na Tim0), drugi o okresie 10us odpowiadający mniej-więcej rozdzielczości serwa (na Tim1). Idea jest taka: pierwszy timer w przerwaniu od Compare Match ustawia cały port na 1, zaś drugi w przerwaniu inkrementuje zmienną i po osiągnięciu przez nią odpowiedniej wartości odpowiadającej zadanej szerokości impulsu serującego serwem gasi odpowiedni pin.
    Próbowałem napisać w miarę podstawowy program spełniający tę ideę, żeby móc go potem rozwijać. Niestety już w tym momencie napotkałem problemy. Chciałem na razie zasymulować przebieg na LED'ach, ponieważ nie posiadam w domu oscyloskopu (za każdym razem, kiedy chcę coś sprawdzić, muszę jechać na uczelnię). Zdaję sobie sprawę, że 50Hz to trochę mało, żeby zauważyć zapalanie i gaszenie diody, ale spodziewałem się, że chociaż diody, których stanu nie zmieniam będą ciągle się palić. Myślałem, że błąd jest w ustawieniach CTC, ale przeglądając dokumentację oraz różne znalezione w sieci programy błędu nie zlokalizowałem. Dlatego chciałbym prosić kogoś bardziej doświadczonego, aby rzucił na to okiem. Kod poniżej:

    Code: c
    Log in, to see the code


    Z góry dziękuję za pomoc w obu przypadkach!
    Pozdrowienia,
    Sinsky
  • #2
    BlueDraco
    MCUs specialist
    Ponieważ masz dużą liczbę wyjść, musisz je sterować programowo. Hybryda typu "3 sprzętowo, reszta programowo" będzie trudniejsza w realizacji.
    Potrzebujesz jednego timera o stałej długości cyklu, np. 2.5 ms i zmienianym w każdym okresie wypełnieniu (rejestr OC). Timer zgłasza dwa przerwania. W przerwaniu końca cyklu aktywujesz kolejne wyjście, programujesz rejestr OC właściwą wartością.

    W przerwaniu OC zerujesz wyjście uaktywnione uprzednio wyjście i i przesuwasz wskaźnik/indeks na następny element tablicy zawierającej bieżące nastawy wszystkich serw.

    Koncepcja Twojego opiekuna wygląda na słabo realizowalną - przerwania 100 kHz na AVR to chyba zbytni optymizm...

    A tak w ogóle to z jakiego muzeum wziąłeś ten układ? Prawie każdy współczesny uC ma potrzebną Ci liczbę wyjść PWM - nie prościej dobrać układ do projektu niż gimnastykować się z niewystarczającymi zasobami?
  • #3
    sinsky_90
    Level 2  
    BueDraco: Cóż, ATmega8515 jest na standardowym wyposarzeniu STK-500 z tego, co zdążyłem się zorientować. A mam je wypożyczone z laboratorium od siebie z uczelni. Nie ma co ukrywać - ten uC ma dosyć małe możliwości, ale promotorowi zależało właśnie na tym, żeby coś ciekawego można było napisać w pracy. Gdyby wykorzystać uC mający na pokładzie gotowe 6 wyjść to nie byłoby w tym żadnego większego problemu do rozwiązania. Z drugiej strony nie spodziewałem się, że promotor będzie kazał mi rozwiązać to sposobem, który - jak piszesz - jest nie bardzo wykonalny. Będę musiał z nim porozmawiać na ten temat. Spróbuję trochę podłubać i wykorzystać to, co mi napisałeś, bo idea - wydaje mi się - nie jest bardzo daleka od tego, co próbowałem na początku uzyskać. A jakby nie patrzeć, zawsze jest to jakieś nowe doświadczenie i materiał na kolejnych kilka stron do pracy.
  • #4
    dondu
    Moderator on vacation ...
    sinsky_90 wrote:
    Chciałem na razie zasymulować przebieg na LED'ach, ponieważ nie posiadam w domu oscyloskopu (za każdym razem, kiedy chcę coś sprawdzić, muszę jechać na uczelnię). Zdaję sobie sprawę, że 50Hz to trochę mało, żeby zauważyć zapalanie i gaszenie diody, ale spodziewałem się, że chociaż diody, których stanu nie zmieniam będą ciągle się palić.

    Dla takiej częstotliwości masz dwukanałowy oscyloskop w każdym komputerze, a jeżeli dodatkowo masz dostęp do komputera z portem LPT, to masz 8 kanałowy analizator stanów logicznych: http://mikrokontrolery.blogspot.com/2011/04/darmowy-oscyloskop-i-analizator.html
  • #5
    Tomasz Gumny
    Level 28  
    Jeśli są to zwykłe serwa modelarskie, to musisz wystawiać 6/8 impulsów 1..2ms co kilkanaście..kilkadziesiąt milisekund. Wystarczy do tego jeden timer odliczający cyklicznie czasy kolejnych kanałów. Obsługa przerwania polega na wpisaniu czas impulsu kolejnego kanału, skasowaniu wyjściu poprzedniego i ustawieniu wyjścia następnego kanału. To, że dla 8 wyjść w położeniu MIN impulsy będą się pojawiać co 8ms, a w położeniu MAX co 16ms nie ma znaczenia. W odbiornikach modelarskich RC za "rozdzielanie" impulsów na poszczególne wyjścia odpowiada 4017 - stosując go potrzebne są tylko 2 wyjścia procesora (CLK i CLR).
  • #6
    User removed account
    Level 1