KURZ: Zvukový výstup - Možnosti praktického využití

KAPITOLY

Možnosti praktického využití

Zvukový výstup řídící jednotky LEGO MINDSTORMS NXT můžeme považovat za doplňkové zařízení. S jeho pomocí můžeme zdůrazňovat některé pasáže vytvářených programů, doplňovat pohyb námi vytvořeného robota zvuky, výstražnými signály a podobně. Vše lze realizovat poměrně jednoduše, ve většině případů pouze jedním příkazem (více v teoretické části tohoto článku).

Využití zvukového výstupu

Použití doprovodné zvukové kulisy si představíme na jednoduchém příkladu. Představme si robustní nákladní automobil, který bude představovat námi vytvořený robot. Tento nákladní automobil bude potřebovat zacouvat do postranní uličky. Mnoho z vás si již určitě všimlo toho, že při couvání některých typů větších automobilů se při couvání začne ozývat výstražný tón, který couvání oznamuje. My se nyní pokusíme tuto situaci nasimulovat. Na obrázku vidíte dráhu, kterou by měl náš robot urazit. Jeho úkolem je projet rovný úsek, na jeho konci se natočit vpravo a zacouvat do cíle. Po celou dobu couvání se bude ozývat výstražný signál.

draha couvani

NXT-G

OVLÁDÁNÍ ROBOTA PŘI PROJETÍ DRÁHOU

Při projetí vytyčenou drahou bude důležité správně používat označování příslušných motorů tak, aby nedošlo k jejich záměně. Stěžejní částí bude závěrečná část programu, kdy se pokusíme zaručit, aby robot při couvání současně couval a vydával výstražný zvuk.

Krok 1 - Pohyb vpřed

Na začátku průjezdu bludištěm musí náš robot urazit rovný úsek. Pro pohyb vpřed, do kterého budou zapojeny oba motory, tedy využijeme blok MovePaletteDragged Move (více o synchronzaci dvou a více motorů v kapitole Pohyb dvou motorů). Zvolíme příslušné porty, ke kterým jsou motory připojeny a směr otáčení vpřed. Pro potřeby programu jsme zvolili rychlost otáčení motorů 25% po dobu 5 sekund. Tento úkon není v programu rozhodující a není proto nutné, aby robot urazil příliš dlouhý úsek.

pohyb vpred

 
Krok 2 - Natočení o 90 stupňů

Poté, co robot urazí rovný úsek, budeme chtít, aby se natočil o 90 stupňů tak, že bude stát svojí zadní částí směrem k pomyslné garáži. Bude potřeba, aby se motory otočily o 180 stupňů, ale každý jiným směrem. Použijeme proto blok 

MotorDragged Motor. Pro pohyb zvolíme stejnou rychlost jako pro pohyb vpřed, tedy 25%. U obou motorů nastavíme trvání pohybu ve stupních (Degrees) a ručně zadáme hodnotu 180 stupňů. Důležité je hlavně správné nastavení opačných směrů otáčení u jednotlivých motorů. Detailní nastavení obou motorů můžete vidět na obrázku. U prvního motoru musíme odškrtnout volbu Wait for Completion. Pokud bychom tak neučinili, natočil by se nejprve první motor a až po provedení pohybu by se natočil druhý motor. Nezvolením této volby ovšem první motor (v našem případě motor B) nečeká až se dokončí příkaz pro jeho ovládání, ale umožní okamžité provádění dalšího příkazu (natočení motoru C).

natoceni motorB

natoceni motorC

 
Krok 3 - Couvání se zvukovou signalizací

Nyní se dostáváme ke stěžejnímu kroku našeho příkladu. Robot musí zacouvat do garáže a po vzoru těžkých nákladních automobilů bude během couvání vydávat výstražný tón. Využití zvuků jsme si popsali v teoretické části.

Chceme, aby řídící kostka vydávala konstantní tón, a proto v sekci Action vybereme volbu Tone. Aby nebyl zvuk příliš hlasitý, zvolili jsme hlasitost 75%. Otázkou nyní je, jak zaručit, aby se tón přehrával po celou dobu couvání robota. Pohyb robota vzad provedeme stejně jako pohyb vpřed pomocí bloku MovePaletteDragged Move. V jeho nastavení si zvolíme příslušné porty, ke kterým jsou motory připojeny, směr vzad a rychlost otáčení 20%. Zbývá zařídit, aby se přehrávání tónu a pohyb vzad prováděli stejně dlouho a oba zároveň. Řekněme si tedy, že budeme chtít, aby se couvání provádělo po dobu 5 sekund. U bloku MovePaletteDragged Move tedy v sekci Duration zvolíme možnost měření v sekundách a zadáme hodnotu 5. Stejnou hodnotu musíme zadat i v bloku SoundDragged Sound. V sekci Note zvolíme označení tónu, který se bude přehrávat a zadáme dobu přehrávání 5 sekund. Nyní již zbývá pouze zařídit, aby se oba úkony prováděly současně. Postup je stejný jako v předchozím kroku, kde jsme chtěli, aby se oba motory natáčely současně. U prvně umístěného bloku (v našem případě blok  SoundDragged Sound) odškrtneme volbu Wait for Completion. Díky tomu se nebude čekat na dokončení tohoto příkazu a okamžitě na začátku jeho provádění se začne vykonávat i příkaz další, tedy couvání.

zvukova signalizace

pohyb vzad

Pokud správně sestavíme jednotlivé kroky za sebou, měli bychom dojít ke zdárnému řešení programu.

 

Program ke stažení

Stažení ve formátu .rbt

RobotC

Ovládání robota při projetí dráhou

Pro úspěšné projetí vytyčené trasy musí robot nejprve urazit rovný úsek, poté se natočit zadní částí směrem k cíly a zacouvat do koncového bodu. Právě při závěrečném couvání budeme chtít, aby zněl varovný signál. Využijeme tedy příkazy pro synchronizaci pohybu dvou motorů (více v kapitole Pohyb dvou motorů) a dále příkaz pro zaznění zvukového signálu.

Krok 1 - Deklarace konstant

Během vytváření programu budeme opakovaně používat stejné hodnoty. Pro pohyb vpřed budeme potřebovat hodnotu, která bude vyjadřovat délku jeho trvání. Musíme také zadefinovat rychlost otáčení motorů. Každé vozidlo couvá nižší rychlostí, než se pohybuje směrem vpřed. Potřebujeme tedy také definovat hodnotu rychlosti otáčení motorů směrem vzad. Hodnoty, které si nadeklarujeme v úvodu programu a poté se na ně pouze odkazujeme pomocí jejich názvu, nazýváme konstanty.

 
 const int doba_pohybu = 5000; // Cas potrebny pro pohyb vpred.
 const int vykon = 25; // Vykon pro pohyb vpred.
 const int vykon_couvani = 10; // Vykon pro pohyb vzad.
 

Doporučení: Aby robot neprováděl jednotlivé úkony příliš rychle za sebou a také abychom předešli nepřesnostem, je dobré si nadeklarovat ještě jednu konstantu. Bude vyjadřovat krátký časový úsek, který bude plnit funkci čekání před změnou pohybu (natáčení po pohybu vpřed a před začátkem pohybu vzad).

 
 const int cekani = 2000; // Cekani 2 vteriny pred zapocetim dalsiho ukonu.
 
 
Krok 2 - Pohyb vpřed

Na úvod projetí vytyčenou dráhou musí robot urazit rovný úsek. Představme si, že náš vytyčený přímý úsek robot rychlostí otáčení motorů 25% urazí za 5 vteřin. Pro pohon motorů použijeme příkaz motor[]. Výkon motorů pro pohyb vpřed jsme si již nadeklarovali jako konstantu výkon. Použijeme ji tedy nyní a přiřadíme její název do příkazu motor[]. Nyní musíme zařídit, aby se motory otáčely vpřed pouze 5 sekund. Docílíme toho příkazem wait1Msec(), který dokáže oddálit provádění dalších příkazů. Jako jeho parametr uvedeme konstantu doba_pohybu, jejíž hodnota je právě 5 sekund. Na konci rovného úseku musíme motory opět uvést do klidu pomocí příkazu motor[], do kterého jako hodnotu přiřadíme 0.

 
 // Pohyb vpred po dobu 5 sekund.
 motor[motorB] = vykon;
 motor[motorC] = vykon;
 wait1Msec(doba_pohybu);
 motor[motorB] = 0;
 motor[motorC] = 0;
 
 
Krok 3 - Nulování čítače otáček

Motory robotické stavebnice používají snímač otáček sloužící k čítání otáček motoru. To nám umožňuje snáze určovat polohu robota. Pokaždé než začneme se snímačem pracovat, je nutné jej vynulovat, aby otáčky čítal vždy od nuly.

 
 nMotorEncoder[motorB] = 0; // Nulovani snimace otacek motoru B.
 nMotorEncoder[motorC] = 0; // Nulovani snimace otacek motoru C.
 

 
Krok 4 - Natočení o 180 stupňů

Robot urazil rovný úsek bludiště a nyní se musí otočit o 180 stupňů tak, aby stál zadní částí směrem k cíli a mohl tak na závěr do cíle zacouvat. Pro otočení je možné použít několik možností. My použijeme tu, která by nám měla zaručit co nejpřesnější výsledek. Využijeme přitom čítač otáček motoru. Přiřazením hodnoty 180 do příkazu nMotorEncoderTarget[] nastavíme, aby se motory pootočili o 180 stupňů. Nyní musíme přidat příkaz, kterým určíme směr otáčení a výkon s jakým se budou motory otáčet. Použijeme opět příkaz motor[], do kterého přiřadíme již dříve nadefinovanou konstantu výkon, čímž zajistíme otáčení rychlostí 25%. Aby se ale robot natočil pouze o 180 stupňů, musí se jeden motor otáčet směrem vpřed a druhý směrem vzad. Inverzní otáčení motoru B zajistí znaménko minus.

Jako poslední musíme zajistit, aby další příkazy byly prováděny až poté co bude robot skutečně natočen o požadovaný úhel. Pro tento účel použijeme cyklus s podmínkou na začátku while(). Do podmínky vložíme příkaz nMotorRunState[motorB] != runStateIdle. Tím v programu zajistíme, že jakýkoliv příkaz, který bychom vložili do těla cyklu bude proveden až poté, co bude dokončen příkaz pro chod motoru B. Jelikož ale chceme, aby tomu tak bylo u obou motorů, použijeme znaménko ||, které v syntaxi RobotC vyjadřuje slučovací poměr (AND) a připojíme obdobný příkaz i pro motor C. V případě našeho programu nechceme, aby se vykonával žádný příkaz a tak do těla cyklu nebudeme umisťovat nic. Na závěr natáčení opět uvedeme motory do klidu.

 
 nMotorEncoderTarget[motorB] = 180; // Nastaveni cilove pozice motoru B (otoceni o 180 stupnu).
 nMotorEncoderTarget[motorC] = 180; // Nastaveni cilove pozice motoru C (otoceni o 180 stupnu).
 
 motor[motorB] = -vykon; // Nastaveni rychlosti otaceni motoru B na 25%.
 motor[motorC] = vykon; // Nastaveni rychlosti otaceni motoru C na 25%.
 
 while (nMotorRunState[motorB] != runStateIdle || nMotorRunState[motorC] != runStateIdle)
 {
 // Tento cyklus ceka na to, az je dokonceno natoceni encoderu o pozadovany uhel.
 // Neprovadi se zadny dalsi prikaz.
 }
 
 motor[motorB] = 0; // Uvedeni motoru B do klidu. 
 motor[motorC] = 0; // Uvedeni motoru C do klidu.
 
 
Krok 5 - Couvání do cíle

Nacházíme se před poslední částí programu pro ovládání robota. Chceme, aby nyní pomalu zacouval do cíle. Jako u každého pohybu motorů i nyní použijeme příkaz motor[]. Pro pohyb vzad jsme si v úvodu nadeklarovi konstantu vykon_couvani, která vyjadruje výkon 10%, s kterým se má robot pohybovat. Jelikož nyní požadujeme, aby robot couval, musíme u proměnné pro výkon použít záporné znaménko. Potřebujeme ještě zajistit, aby se robot pohyboval pouze do cíle a poté zastavil. K určení doby couvání použijeme příkaz wait1Msec(). Jako jeho parametr použijeme poslední z nadeklarovaných konstant doba_pohybu, díky čemuž bude robot couvat pouze 5 sekund. Následně uvedeme motory do klidu.

 
 motor[motorB] = -vykon_couvani; // Reverzivni otaceni motoru B potrebne pro couvani.
 motor[motorC] = -vykon_couvani; // Reverzivni otaceni motoru C potrebne pro couvani.
 wait1Msec(doba_pohybu); // Nastaveni doby couvani na 5 sekund.
 motor[motorB] = 0; // Uvedeni motoru B do klidu.
 motor[motorC] = 0; // Uvedeni motoru C do klidu.
 
 
Krok 6 - Přehrávání tónu během couvání

V našem příkladu ale nechceme pouze to, aby robot zacouval do cíle. Stěžejní částí této kapitoly je využití zvuků. Budeme tedy nyní chtít, aby byl po celou dobu couvání přehráván tón, který utichne jakmile dorazí robot co cíle a zastaví. Jako první musíme nastavit hlasitost tónu, který se bude přehrávat pomocí příkazu nVolume. Pro dostatečně slyšitelnou úroveň zvuku použijeme hodnotu 5. Nyní musíme nastavit samotné přehvávání tónu. Přehrávání konstantních tónů je realizováno příkazem PlayTone(). V prvním jeho parametru jsme použili frekvenci 784 Hz a ve druhém dobu přehrávání 5 sekund. Oba příkazy umístíme hned za příkaz pro couvání robota. Jakmile se nyní začne robot pohybovat, začne znít zvukový tón. Jelikož doba couvání je stejná jako doba, po kterou se bude přehrávat tón, tak po ukončení pohybu bude ukončena také výstražná signalizace.

 
 motor[motorB] = -vykon_couvani; // Reverzivni otaceni motoru B potrebne pro couvani.
 motor[motorC] = -vykon_couvani; // Reverzivni otaceni motoru C potrebne pro couvani.
 nVolume = 5; // Nastaveni urovne hlasitosti prehravaneho zvukoveho signalu.
 PlayTone(784, 500); // Nastaveni prehravani tonu o frekvenci 784 Hz po dobu 5 sekund.
 wait1Msec(doba_pohybu); // Nastaveni doby couvani na 5 sekund.
 motor[motorB] = 0; // Uvedeni motoru B do klidu.
 motor[motorC] = 0; // Uvedeni motoru C do klidu.
 

Poznámka: Pro couvání by bylo možné využít jakýkoliv jiný zvuk, či audiosoubor. Klasický tón byl zvolen pouze jako vhodná pomůcka pro potřeby tohoto příkladu.

 
Výsledný program

Po správném provedení všech úkonů bude výsledný program vypadat takto:

 
task main()
{
 
 const int doba_pohybu = 5000;
 const int vykon = 25;
 const int vykon_couvani = 10;
 const int cekani = 2000; 
 
 // Pohyb vpred po dobu 5 sekund.
 motor[motorB] = vykon;
 motor[motorC] = vykon;
 wait1Msec(doba_pohybu);
 motor[motorB] = 0;
 motor[motorC] = 0;
 
 wait1Msec(cekani); // Cekani pred zapocetim nataceni.
 
 nMotorEncoder[motorB] = 0; // Nulovani encoderu motoru B.
 nMotorEncoder[motorC] = 0; // Nulovani encoderu motoru C.
 
 nMotorEncoderTarget[motorB] = 180; // Nastaveni cilove pozice motoru B (otoceni o 180 stupnu).
 nMotorEncoderTarget[motorC] = 180; // Nastaveni cilove pozice motoru C (otoceni o 180 stupnu).
 
 motor[motorB] = -vykon; // Nastaveni rychlosti otaceni motoru B na 25%.
 motor[motorC] = vykon; // Nastaveni rychlosti otaceni motoru C na 25%.
 
 while (nMotorRunState[motorB] != runStateIdle || nMotorRunState[motorC] != runStateIdle)
 {
 // Tento cyklus ceka na to, az je dokonceno natoceni encoderu o pozadovany uhel.
 // Neprovadi se zadny dalsi prikaz.
 }
 
 motor[motorB] = 0; // Uvedeni motoru B do klidu. 
 motor[motorC] = 0; // Uvedeni motoru C do klidu.
 
 wait1Msec(cekani); // Cekani pred zapocetim couvani.
 
 motor[motorB] = -vykon_couvani; // Reverzivni otaceni motoru B potrebne pro couvani.
 motor[motorC] = -vykon_couvani; // Reverzivni otaceni motoru C potrebne pro couvani.
 nVolume = 5; // Nastaveni urovne hlasitosti prehravaneho zvukoveho signalu.
 PlayTone(784, 500); // Nastaveni prehravani tonu o frekvenci 784 Hz po dobu 5 sekund.
 wait1Msec(doba_pohybu); // Nastaveni doby couvani na 5 sekund.
 motor[motorB] = 0; // Uvedeni motoru B do klidu.
 motor[motorC] = 0; // Uvedeni motoru C do klidu.
}
 

 

Program ke stažení

Stažení ve formátu .c

1 1 1 1 1 1 1 1 1 1 Hodnocení 4.33 (3 hodnocení)

Nemáte oprávnění přidat komentář.
Komentáře mohou přidávat pouze registrovaní uživatelé, kteří neporušují pravidla diskuze.