czech english

Řízení serva

pokročilejší programování jednočipů

Jakkoli užitečné blikání s LEDkou je, tak samo o sobě nám s robotem nepohne. Při výběru pohonné jednotky našimi základními požadavky zůstávají lehká dostupnost a snadné řízení pomocí jenočipu. Těmto požadavkům nejlépe vyhovuje modelářské servo. Na jeho příkladu si ukážeme jak generovat signál (tj. jak měnit napětí na výstupním pinu v závislosti na čase). Při té příležitosti si také ukážeme, k čemu jsou dobré složitější moduly jednočipu jako třeba časovač, a také jak za pomoci přerušení řešit několik úkolů najednou.

Servo
Servo
Modelářské servo je krabička (nejčastěji černá ), která má na vstupu tři vodiče a jejímž výstupem je osa, která se otáčí v rozsahu cca. 90° resp. 180°. Na vstupní vodiče je třeba připojit zem, +5V a řídící signál. Servo se standardně ovládá 1-2ms dlouhými pulzy s frekvencí 50Hz (pozn. většina serv reaguje v širším rozsahu od 0.5ms do 2.5ms a rozsah otáčení pak může být až 180°). Šířka pulzu přímo úměrně odpovídá natočení výstupní osy. Tedy pokud budeme generovat pulz o šířce 1.5ms, přesune se servo do střední polohy. Změnou délky pulzu pak můžeme pootočit osou doleva či doprava. Krajním polohám natočení pak odpovídají krajní délky pulzů.
Černá krabička serva v sobě obsahuje kromě vlastního motoru i převodovku a silovou elektroniku, díky které nám stačí pro jeho řízení generovat pouze logický řídící signál. Generovat řídící signál a tedy řídit servo můžeme několika způsoby. Víme-li, na jaké frekvenci běží náš čip (to bychom asi měli vědět tak jako tak) a kolik tiků trvá vykonání jedné instrukce, můžeme délku příslušných intervalů přepočítat na počet vykonaných instrukcí. Například pro procesor běžící na 1MHz zpracovávající jednu instrukci každý tik, potřebujeme pro vyčkání 1.5ms vykonat 1500 instrukcí (za předpokladu, že jedna instrukce trvá 1us — ve skutečnosti některé trvají déle a v horším případě tento čas závisí ještě na stavovém registru či způsobu adresace). Kód pro generování příslušných 1.5ms pulzů by mohl v jazyce C vypadat přibližně takto:
while (1)
{
    output = 1 ;
    for (i = 0; i < 1 500; i)
        ;
    ""output"" = 0 ;
    for (i = 0; i < 18 500 ; i)
        ;
}
Nicméně, nic není tak jednoduché, jak se může na první pohled zdát. Kód zde napsaný opravdu inkrementuje proměnnou i 1500 krát, ale není na první pohled jasné, kolik se vlastně provede instrukcí. Dostupnější jednočipy bývají typicky 8-bitové, což znamená, že mají instrukce pro manipulaci s 8-bitovými hodnotami. Protože už ani 1500 (o 18500 ve druhé smyčce ani nemluvě) se do jednoho bytu nevejde, přeloží kompilátor kód pomocí sekvence těchto jednoduchých instrukcí. Abychom dosáhli totální kontroly nad počtem instrukcí vykonaných v každé smyčce, museli bychom kód psát v asembleru (tj. psát přímo instrukce daného procesoru) a do toho se jako začátečnící rozhodně nechceme pouštět .

Timer, časovač

Místo psaní asembleru s nadšením sáhneme po modulu časovače. Jednak si tím zjednodušíme život a také náš jednočip možná zvládne i něco navíc než pouze řídít jedno servo. Základní funkce časovače, timeru, spočívá v neustálém přičítání jedničky u speciálního registru. Rychlost tohoto přičítání je dána frekvencí procesoru a děličkou, tvz. prescaler, pomocí které můžeme časovač zpomalit. Náš kód pro řízení serva by potom mohl vypadat zhruba takto (konstanty T1, T2 a T3 závisí na požadované délce pulzu):
while (1)
{
    output = 1 ;
    timer = 0 ;
    while (timer < T1)
        ;
    output = 0 ;
    for (i = 0; i < T2; i++)
    {
        timer = 0 ;
        while (timer < T3)
            ;
    }
}
Graf řídícího signálu
Graf řídícího signálu
Ve smyčce vždy nejprve nastavíme výstupní pin na high (tedy 1) a čekáme, než hodnota timeru přesáhne hodnotu T1. Její úpravou měníme délku pulzu. Ve druhé části nastavíme výstup na low (0) a snažíme se vhodnou volbou hodnot T2 a T3 počkat tak dlouho, kolik nám zbývá do 20ms (protože pulzy máme generovat s frekvencí 50Hz). Je třeba mít stále na paměti, že pracujeme převážně s 8-bitovým procesorem a hodnota timeru typicky nepřesáhne 255. Pro delší čekání musíme tedy čekat několikrát.
Tento kód se od předcházející verze liší zejména v tom, že již nebudeme mít problémy s počtem instrukcí (protože je nepočítáme ). Délka aktivních čekání je odvozena pouze od rychlosti timeru (ta je dána rychlostí procesoru a děličkou). Je také třeba mít na paměti, že vlastní zapnutí timeru a jeho nastavení je třeba si nastudovat v dokumentaci od použitého čipu.

Interrupt, přerušení

Právě popsaným způsobem již budeme schopni řídit servo generováním příslušného signálu na našem jednočipu. Bohužel to ale náš jednočip zaměstná natolik, že nebude schopen dělat nic jiného. To by byla trochu škoda, protože výše uvedený kód až na dva konkrétní okamžiky nedělá nic zajímavého. V podstatě jen správně dlouhou dobu čeká. V této situaci by nám pomohl nějaký mechanismus, pomocí kterého by nás timer nějakým způsobem upozorňoval na okamžiky, které nás zajímají. Tomuto mechanismu se říká přerušení (anglicky interrupt).
Pokud nastane přerušení, tak procesor přeruší vykonávání hlavního programu a zavolá odpovídající obslužnou funkci. Většina procesorů nám umožňuje nainstalovat tzv. interrupt handler — funkci pro obsluhu příslušného přerušení. Jedno z přerušení, které můžeme takto „obsluhovat” je například přetečení 8mi bitového timeru. To nastává, když se hodnota mění z maximální 255 zpět na 0 (anglicky overflow interrupt).
Jeden ze způsobů využití obsluhy přetečení časovače může vypadat například takto:
int phase = 0;
void overflow()
{
    timer = 5;
    phase++;
    if (phase == 1)
    {
        output = 0;
    }
    else if (phase == 9)
    {
        output = 1;
        phase = 0;
    }
}
Řídící signál pro servo opět generujeme pomocí proměnné output. Místo hlavní nekonečné smyčky je nyní celá logika pro generování signálu schovaná v obsluze přerušení přetečení časovače (overflow interrupt handler). Při prvním (phase == 1) přetečení nastavíme výstup do úrovně low, kde také zůstane příštích 9 přetečení. Za povšimnutí stojí také nastavení aktuální hodnoty timeru na hodnotu 5. Tím zajistíme, že do dalšího přetečení timeru uplyne pouze 250 tiků, což může být výhodné pro měření intervalů (např. při děličce 1:8 a 1MHz frekvenci procesoru trvá 250 tiků 2ms).

Závěr

Po přečtení této kapitoly byste měli vědět, jak funguje timer (časovač) a co je to interrupt (přerušení). Vyzbrojeni těmito novými poznatky, byste měli mít představu o tom, jaké jsou principy generování jednoduchých signálů proměnlivých v čase.
Jak vypadá nějaká konkrétní aplikace pro vybraný procesor si ukážeme příště.

Odkazy

Pokud vám některá část přišla méně srozumitelná nebo jste našli chybu či nesrovnalost, ale i v případě, že se vám vše líbilo a chcete nás pouze pochválit, využijte našeho kontaktního formuláře.