Uwaga! Ta strona wysyła Ci "ciasteczko".
Użytkowników online:
1
Artykuły>Mikrokontrolery i PLD>Kurs AVR-GCC, Serwo modelarskie
printer_icon

Kurs AVR-GCC. Serwomechanizm modelarski

23.10.12 ABXYZ

To będzie łatwy aczkolwiek poruszający:) temat - sterowanie serwomechanizmem modelarskim. Ze względu na mnogość możliwych zastosowań serwo modelarskie może być potężną bronią w arsenale (w szufladzie) każdego domorosłego konstruktora. Na początku, dla tych, którzy jeszcze nie mieli styczności  z serwomechanizmami modelarskimi, napisałem kilka zdań wprowadzenia. Dalej tłumaczę krótko jak sterować serwem analogowym i wreszcie uruchamiamy przykładowy programik - będzie to sterownik dwunastu serw na uC atmega8.

Serwo modelarskie

Serwomechanizm modelarski to elektromechaniczne urządzenie wykonawcze, montowane w kierowanych radiem modelach samolotów, pojazdów, łódek itd.

obrazek
Tanie popularne serwo TowerPro SG5010

W modelach serwomechanizmy, zwykle z pomocą różnych dźwigni i popychaczy, poruszają powierzchniami sterowymi, kołami lub innymi ruchomymi elementami modelu. Każdy serwomechanizm zamontowany w modelu podłączony jest przewodem sygnałowym do odbiornika radiowego zdalnego sterowania.

obrazek
Typowy przykład użycia serwa modelarskiego: serwomechanizm porusza sterem wysokości modelu samolotu.

We wnętrzu obudowy serwomechanizmu modelarskiego znajdują się: silniczek DC; przekładnia redukująca obroty(wzmacniająca moment siły) z wałkiem wyjściowym; potencjometr obrotowy oraz płytka z elektroniką. Wałek wyjściowy sprzęgnięty jest z wałkiem potencjometru, dodatkowo mechaniczna blokada ogranicza kąt obrotu wałka ( 120°-150°). Elektronika serwomechanizmu stale mierzy napięcie na potencjometrze i tak steruje kierunkiem obrotów oraz mocą silnika, żeby jak najszybciej uzyskać pożądany kąt wychylenia na wałku wyjściowym. Czyli jest to układ ze sprzężeniem zwrotnym.

obrazek
Popularne Serwo TowerPro MG955
obrazek
Po zdjęciu górnej pokrywy obudowy serwa widzimy przekładnię z kołami zębatymi, przekładnia redukująca obroty(wzmacniająca moment siły) przenosi obroty z wałka silnika na wałek wyjściowy
obrazek
Zdjęta dolana pokrywa obudowy serwa - widzimy od dołu: silnik, potencjometr obrotowy i płytkę elektroniki
obrazek
Wydobyty z obudowy serwa potencjometr obrotowy. Normalnie wałek potencjometru sprzęgnięty jest z wałkiem wyjściowym serwa

Ze względu na rozmiary i siłę serwa modelarskie dzielą się na: serwa micro, standard i giga, a ze względu na zasadę działania na serwa analogowe i cyfrowe, produkowane są też specjalne serwa dla entuzjastów robotyki. Jest kilka "parametrów technicznych", które rozważa się przy ocenie serw modelarskich, ja nie będę tutaj o nich pisał, w internecie można znaleźć mnóstwo informacji na ten temat.

Sterowanie serwem

Z obudowy serwomechanizmu wyprowadzony jest kabel, trzy żyły: czarny lub brąz - masa, czerwony- zasilanie (4,8-7,2V), biały lub żółty - sygnał sterujący. Na wejście serwomechanizmu podaje się przebieg prostokąty o częstotliwości 40-60Hz, kąt wychylenia wałka serwa związany jest z szerokością impulsu, patrz rysunek poniżej. Szerokość impulsu zmienia się w zakresie od ok 0,3ms do 2,3 ms. Środkowy (centralny) kąt wychylenia wałka serwo przyjmuje dla impulsu o długości 1,5ms , dla impulsu o szerokości 1ms wałek serwa obrócony jest o ok 45° w w prawo, a dla 2ms - o 45° w lewo.

obrazek
Sterowanie serwem. Środkowy (centralny) kąt wychylenia wałka serwo przyjmuje dla impulsu o długości 1,5ms , dla impulsu o szerokości 1ms wałek serwa obrócony jest o ok 45° w prawo, a dla 2ms - 45° w lewo.

Sygnał PWM sterujący serwem możemy generować z pomącą tajmerów(peryferyjnych układów czasowy) AVRa pracujących w trybie PWM. Atmega8 ma tylko trzy kanały PWM, atmega16(32) - cztery, atmega128 i atmega88 - 6. Jak skonfigurować tajmery AVRa do sterowania serwem, znajdziesz w internecie wiele przykładów - jeśli nie, zapytaj na forum. Natomiast jeśli chcemy sterować większą liczbą serw, to pozostaje generować sygnał PWM programowo, tzn. nie timer, a program bezpośrednio steruje wyjściami PWM. Dalej w artykule uruchomimy przykładowy program dla atmega8, w którym sygnały PWM sterujące dwunastoma serwami, będą tworzone programowo.

Przykład programu sterownika dwunastu serw

Przykładowy program przeznaczony jest dla AVRa atmega8 taktowanego zegarem 16MHz - maksymalna prędkość atemaga8 jest raczej niezbędna przy programowym generowaniu sygnału PWM. Aby zmienić częstotliwość taktowania uC atmeag8 z fabrycznie ustawionego 1MHz na 16MHz, należy do atmega8 dołączyć rezonator kwarcowy 16MHz - schemat poniżej.

obrazek
Przyłączenie do AVRa rezonatora kwarcowego 16Mhz
I przeprogramować odpowiednio fuse-bity: hfuse:0xc9, lfuse:0xef. Robimy to wpisując w "wierszu poleceń" windowsa linię :
C:\>avrdude -c usbasp -p m8 -U hfuse:w:0xc9:m -U lfuse:w:0xef:m

W miejsce "usbasp" podajemy nazwę własnego programatora. Przy zmianie fuse-bitów trzeba uważać, bo drobna pomyłka może skutkować zablokowaniem układu.

Dwanaście serw zostało podłączonych do portów we/wy AVRa w następujący sposób: serwa s1-s6 - porty PD2..PD7, a serwa s7-s12 - porty PC0..PC5. Do zasilania dwunastu serw potrzeby jest odpowiedniej mocy zasilacz lub akumulator (4,8-7,2V), polecam zasilacz od komputera PC.

Przygotowałem dwie wersje programu sterownika serw. W pierwszej wersji programu, co sekundę, sterownik zmienia kąt wychylenie orczyka serw s0,s2,s4..s10 w następujący sposób: położenie centrum (1,5ms), centrum+45°, centrum-45°, centrum; zaś serw s1,s3,s5..s11 w przeciwnym kierunku. W drugiej wersji programu będziemy sterować zdalnie dwunastoma serwami z komputera PC, połączymy uC atmega8 z komputerem poprzez złącze szeregowe RS232C.

Przykładowy program sterownika działa w następujący sposób: Na początku głównej pętli programu wszystkie dwanaście wyjść, do których przyłączone są serwomechanizmy, zostają ustawione są w stan wyskoki - początek impulsu na wszystkich wyjściach. Następnie, po odpowiednim opóźnieniu, program ustawia poszczególne wyjścia w stan niski; dziej się to w pierwszej zagnieżdżonej pętli for. Czas trwania impulsu na poszczególnych wyjściach uzależniony jest od wartości odczytanej z tablicy "SERVOS". Tablica "SERVOS" zawiera dwanaście bajtów mówiących o kącie wychyleniu poszczególnych serw, wartość 0x8B odpowiada położeniu centralnemu (1,5ms), a zmiana wartości bajtu jeden powoduje obrót serwa w przybliżeniu o 1 stopień. Szerokość impulsu na wyjściach zmienia się w zakresie 0-2,4ms. Dalej w kolejnej zagnieżdżonej pętli while umieszczona jest reszta kodu programu (nie związana z generowaniem sygnału pwm), czas wykonania tego fragmentu powinien być mniejszy niż 18ms. Cały kod zawarty w głównej pętli programu wykonuje się w czasie ok 20ms - pięćdziesiąt razy na sekundę.

Opóźnienia w programie odmierzane są z użyciem 16-bitowego tajmera1, Timer1 konfigurujemy i włączamy ustawiając odpowiednie bity w rejestrze TCCR1B. Tajmer1 zostaje włączony przed główną pętlą programu, tak, że zlicza on co ósmy cykl zegara(16MHz) taktującego mikrokontroler - wybrano opcję preskaler 8. Stan timera1 odczytuje się z 16-bitowego rejestru TCNT1, a zeruje się tajmer1 zapisując wartość zero do rejestru TCNT1.

Poniżej zamieściłem pełny listing pierwszej wersji programu sterownika serw, dalej można pobrać spakowany katalog projektu z plikiem makefile.

/*
   ABXYZ
   KURS AVR-GCC, SERWO MODELARSKIE
   
   
   Steruje 12 serwami
 
   atmega8 (16MHz)
*/

#include <avr/io.h>

// Wychylenie serw
unsigned char servos[12] ;   
         

int main(void)
{
    volatile unsigned char  n,p_c,p_d,p_cc,p_dd;
    unsigned char t; 
  
    // Początkowe wychylenie 12 serw
    // centrum 1,5ms 
      for(n=0; n<12; n++) servos[n] = 0x8B;
    
    // Wyjścia PC0..PC5    i PD2..PD7 - 12 serw
    DDRC  = 0x3f;  // wyjścia PC0..PC5 - s6..s11
    DDRD  = 0xfc;  // wyjścia PD2..PD7 - s0..s5 

    // Start Timer1, preskaler 8
    // Tajmer1 zlicza co ósmy cykl zegara 
    // taktuącego uC (16MHz), czyli co 0,5us
    TCCR1B = (1<<CS11);
    
    //   GŁÓWNA PĘTLA PROGRAMU
    for(t=0;;t++) 
    {          
        p_c = 0;
        p_d = 0;
 
        // Start impulsu - wszystkie wyjścia 
        // w stan wysoki    
         PORTC |= 0x3f;
        PORTD |= 0xfc;   
        
        // Czas wykonania pętli 241*9,5us 2,3ms
        for(n=0; n<241; n++)
        {   
            TCNT1 = 0; // Zeruje Timer1 
            SFIOR = 1; // Resetuje preskaler       
      
            if(n>servos[0])  p_d |= (1<<2);   
            if(n>servos[1])  p_d |= (1<<3);
            if(n>servos[2])  p_d |= (1<<4);  
            if(n>servos[3])  p_d |= (1<<5);    
            if(n>servos[4])  p_d |= (1<<6);  
            if(n>servos[5])  p_d |= (1<<7); 
           
            if(n>servos[6])  p_c |= (1<<0);  
            if(n>servos[7])  p_c |= (1<<1); 
            if(n>servos[8])  p_c |= (1<<2);  
            if(n>servos[9])  p_c |= (1<<3);
            if(n>servos[10]) p_c |= (1<<4);  
            if(n>servos[11]) p_c |= (1<<5);

            p_cc = ~p_c;
            p_dd = ~p_d; 
            
            // Koniec impulsu     
            PORTD &= p_dd;
            PORTC &= p_cc;

            // Czeka, jeśli zawartość tajmera1 
            // jest mniejsza niż 19, czyli 9,5us od 
            // momentu zerowania tajmera1
            while(TCNT1<19 ); // 0,5 * 19 = 9,5us
        }
        
        TCNT1 = 0; // Zeruje Timer1
        SFIOR = 1; // Resetuje preskaler
       
        // Pętla wykonuje się dopóki zawartość tajmera1
        // jest mniejsza niż 35100, czyli 
        // ok 18ms od momentu zerowania tajmera
        while(TCNT1<35100)  // 0,5*3510 = 1,7550 ms
        {
        // Tutaj, w pętli, reszta programu,
        // powinien się  wykonać w czasie <18ms.
        
            if(t==1)
            {
              servos[0] = 0x5e;
              servos[1] = 0xb8;
              servos[2] = 0x5e;
              servos[3] = 0xb8;
              servos[4] = 0x5e;
              servos[5] = 0xb8;
              servos[6] = 0x5e;
              servos[7] = 0xb8;           
              servos[8] = 0x5e;
              servos[9] = 0xb8;
              servos[10] = 0x5e;
              servos[11] = 0xb8;               
            }
            else if(t==50)
            {
              servos[0] = 0x8B;
              servos[1] = 0x8B;
              servos[2] = 0x8B;
              servos[3] = 0x8B;
              servos[4] = 0x8B;
              servos[5] = 0x8B;
              servos[6] = 0x8B;
              servos[7] = 0x8B;              
              servos[8] = 0x8B;
              servos[9] = 0x8B;
              servos[10] = 0x8B;
              servos[11] = 0x8B;                                              
            }
            else if(t==100)
            {
               servos[0] = 0xB8;
               servos[1] = 0x5e;
               servos[2] = 0xB8;
               servos[3] = 0x5e;
               servos[4] = 0xB8;
               servos[5] = 0x5e;
               servos[6] = 0xB8;
               servos[7] = 0x5e;               
               servos[8] = 0xB8;
               servos[9] = 0x5e;
               servos[10] = 0xB8;
               servos[11] = 0x5e;              
            }
            else if(t==150)
            {
               t=0;
            }          
        }        
    }
    
    return 0;
}

Listing pierwszej wersji programu sterownika serw.

Druga wersja programu sterownika serw

W drugiej wersji programu sterownika serw dodałem obsługę portu szeregowego. Łączymy mikrokontroler atmega8 kablem RS232C do komputera PC i sterujemy zdalnie dwunastoma serwami z pomocą specjalnego programu uruchamianego w systemie windows. Schemat poniżej pokazuje sposób połączenia portu szeregowego atmega8 z interfejsem RS232C komputera PC. Jeśli w komputerze brak portu RS232C, to zamiast układu MAX232, stosujemy konwerter USB-RS232/TTL - kosztuje jakieś tam kilkanaście zł.

schemat
Schemat połączenia portu szeregowego AVRa atmega z interfejsem rs232c komputera PC. Kliknij w obrazek, aby powiększyć.

Stworzyłem niewielki program "serwo-demo" dla systemu Windows, w jego okienku, poruszając kontrolkami-suwakami, możemy zdalnie sterować dwunastoma serwomechanizmami, zrzut ekranu poniżej.

afasdfas
Okienko programu "serwo-demo", zdalne sterowanie serwami z komputera PC.

Obsługa programu "serwo-demo" jest oczywista. Zaczynamy od wybrania właściwego portu COMx i kliknięcia przycisku "Open". Po otwarciu portu COMx, każda ruch kontrolki-suwaka skutkuje wysłaniem do portu ramki danych, zawierającej informacje o wychyleniu dwunastu serwomechanizmów. Ostatnia wysłana portem szeregowym ramka danych pokazana jest w lewym dolnym rogu okienka programu.

Jednorazowo wysyłanych jest 13 bajtów danych, 12 bajtów to informacja o kącie wychylenia 12 serw, a trzynasty bajt to suma kontrolna. Ramka danych składa się wyłącznie z wybranych kodów ASCII, tj. z cyfr hex(0-9,A-F),ze znaku dwukropka(:) i znaku końca linii. Dane w ramce są zapisane w systemie szesnastkowym, dwa znaki (cyfry hex 0-9,A-F) na jeden bajt danych. Ramka danych rozpoczyna się od znaku dwukropka ':', następnie występuje 24 cyfry hex - wychylenie dwunastu serw, następnie dwie cyfry hex - suma kontrolna i zamykający ramkę znak końca linii.

Programik "serwo-demo" został stworzony z pomocą darmowego środowiska programistycznego "Visual C++ Express Edition 2008", jest prościuchny:) i służy jedynie do demonstracji działanie naszego sterownika serw. "Visual C++" daje możliwość szybkiego tworzenia aplikacji okienkowych dla Windows metodą wizualną, tzn. klikania, kopiowania i wklejania. Każdy, kto potrafi cokolwiek programować w C/C++, może pobrać za free "Visual C++" i w kilka chwil stworzyć program do zdalnego sterowania serwami według swoich potrzeb.

Kilka wskazówek

Programowe generowanie sygnałów PWM ma tę zaletę, że możemy do AVRa przyłączyć dowolną ilość serw - tyle, ile wolnych jest portów we/wy. W przypadku korzystaniu z tajmerów uC ATmega, możemy sterować tylko kilkoma serwami - dwa kanały PWM na jeden tajmer. Ale programowe tworzenie sygnału sterującego dla wielu serw w znacznym stopniu zajmuje mikrokontroler i może mu braknąć czasu na realizowanie innych zadań. Tak więc, jeśli mamy tylko kilka serw, to lepiej korzystać z tajmerów. Kolejną opcją jest wybór innego, lepiej wyposażonego w peryferia mikrokontrolera inż atmega. Ja polecam popularne ostatnio 32-bitowe mikrokontrolery stm32. Kolejna rzecz. My tu bawimy się w programowanie głównie w języku C, w praktyce tego rodzaju programy jak nasz sterownik serw dobrze jest napisać od początku do końca w asemblerze.

Katalog z plikami źródłowymi przykładów można pobrać klikając w link serwo_modelarskie.zip.

23.10.12 ABXYZ
legenda

Komentarze (11)

Kamdz
10.04.2017 (22:07)
gość
Pytanie do autora... Czy mógłby pan napisać jakiś prostszy program na jedno serwo bo nie mogę pojąć istoty działania tego...
reaktorAtomowy
16.02.2015 (17:47)
gość
Pytanie za 100pkt: da się sprawić żeby serwa były sterowane z 10 bitową rozdzielczością? Zapewne jest to kwestia przerobienia kilku zmiennych i poprawienie przerwania.
abxyz
19.01.2015 (01:51)
autor strony
W internecie można znaleźć mnóstwo tekstów jak programować porty szeregowe PC-ta.

Ja, ponieważ chciałem przygotować coś na szybko pod windows, zamontowałem na komputerze, środowisko programistyczne "Visual C++ Express Edition 2008" - darmowe.

W środowisku tym dostępna jest biblioteka obiektowa do programowania wizualnego,
która daje możliwość szybkiego tworzenia aplikacji okienkowych dla
Windows- między innymi dostępny jest tam komponent do obsługi portu szeregowego rs232.

Co mogę więcej doradzić...

KubioQ
17.01.2015 (08:07)
gość
A pamiętasz może, jak takie coś zrobić ? bo potrzebuje tylko kod źródłowy żeby mi te dane wysyłał na port COM resztę sobie poradzę. Podobno prosty program hah :D
abxyz
17.01.2015 (01:33)
autor strony
>>KubioQ

Niestety komputer na którym to robiłem, z Windows XP, wysypał się jakiś czas temu.
abxyz
17.01.2015 (01:09)
autor strony
>> szalonyszymek

Program oblicza sumę mod256 bajtów danych ze zmienionym znakiem. Sprawdzanie sumy kontrolnej możesz pominąć usuwając jedną linię kodu

if(!sum()) //


KubioQ
16.01.2015 (15:45)
gość
Witam

Czy jest taka możliwość zakupienia kodu źródłowego programu serwo_demo ? Robię duży projekt manipulatora sterowanych serwami przez atmegę i pada od konsoli.

Pozdrawiam
szalonyszymek
15.01.2015 (19:59)
gość
Możesz rozjaśnić jak działa tutaj suma kontrolna? Sam z programu nie mogę tego odczytać. Muszę zamiast komputera podpiąć zewnętrzny procesor ale nie wiem jak ta suma jest tutaj liczona.
Qba
02.12.2012 (21:09)
gość
kolego klakier z pytaniami to na forum, a co do aplikacji komunikującej się z mikrokontrolerem zacząłbym tutaj: http://www.teuniz.net/RS-232/
Klakier
15.11.2012 (20:13)
gość
Oczywiście wszystko w C/C++.
Klakier
15.11.2012 (20:12)
gość
Witam, ja mam pytanie jak napisać program obsługujący mikrokontroler? To ma działać na takiej zasadzie : plik wykonywalny np. dane.exe będzie sczytywał wartość np. potencjometru i będzie wyświetlał w konsolce tego programu. Da się tak zrobić ?
Artykuły>Mikrokontrolery i PLD>Kurs AVR-GCC, Serwo modelarskie
Ostatnie artykuły