Minule jsme zmiňovali možnost programovat roboty postavené ze stavebnice Lego RIS 2.0 v jazyce NQC a prostředí BricxCC. V článku použité programy jsou testované na modelu ZRP, Základním Robotu na Pásech. Postup jeho konstrukce najdete na stránkách http://www.roboti.unas.cz v sekci konstrukce robotů.
Pokud se ZRPa sestavit nepodaří, můžete klidně použít robota Roverbot, jehož konstrukce je popsaná v návodu u stavebnice. Náš ZRP vypadá takto:
Každý program v NQC musí obsahovat hlavní úlohu task main(), kterou překladač označí za výchozí bod hotového programu. Klíčové slovo task označuje, o jaký druh úlohy se jedná, identifikátor main je názvem úlohy. Syntaxe vypadá následovně:
task main()
{
/*tady bude kód*/
}
Mezi složené závorky {} budeme psát jednotlivé příkazy, které se po spuštění úlohy main() vykonají. Kód uzavřený mezi dvěma lomítky s hvězdičkou je poznámka, tu překladač ignoruje.
Začneme s tím nejjednodušším – s pohybem robota. Robota pohání dvojice motorů a ty chceme spustit. Příkazy pro ovládání motorů jsou: OnFwd(„motory“), OnRev(„motory“) a Off(„motory“), přičemž pomocí prvního příkazu robot rozjedeme dopředu, pomocí druhého dozadu a pomocí příkazu Off() ho zastavíme. Nezapomeňte přitom, že směr vpřed a vzad určuje polarita zapojených kontaktů. Jednotlivé příkazy musí být odděleny středníkem. Nyní si to vyzkoušíme na příkladu
task main()
{
OnFwd(OUT_A+OUT_C); /*OUT_A je motor na výstupu A, OUT_C je o motor na výstupu C*/
Wait(100); /*viz dále*/
OnRev(OUT_A+OUT_C);
Wait(100);
Off(OUT_A+OUT_C);
}
Robot pojede jednu sekundu dopředu, poté sekundu zpátky a zastaví. V programu je použit příkaz Wait(100). Ten je velice důležitý, protože jinak by zapnutí a vypnutí motorů proběhlo téměř souběžně. Doba, po jakou nedojde k žádné úmyslné změně stavu robota, je uvedena v závorce v setinách sekundy.
Zatáčení u pásového vozidla docílíme tak, že jeden motor necháme běžet směrem dopředu a druhý dozadu. Opět nezapomeneme vložit příkaz Wait(). Motory robota nejsou krokové a chceme-li docílit otočení např. o 90°, musíme patřičnou prodlevu odhadnout a zkoušením doladit, mimo jiné i podle typu povrchu, po jakém se budou pásy pohybovat.
task main()
{
OnFwd(OUT_A);
OnRev(OUT_C);
Wait(105);
Off(OUT_A+OUT_C);
}
Pomocí příkazu SetPower(„motory“, „síla“), kde síla je číslo od 0 do 7 (sedm pro nejvyšší otáčky), lze ovlivnit výkon motorů. konkrétní případ může vypadat třeba takto:
SetPower(OUT_B,5); /* nastaví rychlost otáčení motoru na výstupu B na 5)*/
Toto je pouze základní přehled příkazů pro motory, o dalších až příště.
V programu můžeme použít proměnné, konstanty nebo náhodná čísla. Proměnné definujeme na kterémkoliv místě zdrojového textu programu příkazem int „název proměnné“ před jejich prvním použitím; například takto:
task main()
{
int ipohyb_vpred;
ipohyb_vpred = 100; /*takto vypadá přiřazení*/
OnFwd(OUT_A+OUT_C);
Wait(ipohyb_vpred); /*proměnné lze použít jako parametry příkazů*/
Off(OUT_A+OUT_C);
}
Konstanta je identifikátor, který nahrazuje jednu konkrétní hodnotu. Konstanty se definují na začátku programu takto:
#define pohyb_rovne 150
Konstanta dostala název pohyb_rovne a zastupuje hodnotu 150. Stejně jako názvy pro čísla můžeme definovat např. názvy motorů:
#define levy_motor OUT_A /*v programu místo OUT_A stačí psát levy_motor*/
Zbývá se zmínit o náhodných číslech. Zatím jsme do proměnných přiřazovali pouze neměnné hodnoty, jazyk NQC však dovoluje pracovat i s náhodnými čísly; syntaxe je následující:
int nahoda;
nahoda = Random(100);
Proměnná nahoda bude obsahovat náhodně vybrané číslo z intervalu 0 až 100 (včetně 0 a 100); obecně příkazem x=Random(n) se do proměnné x uloží číslo od 0 do n. S náhodnými čísly může být chování robota mnohem zajímavější.
Prostou posloupnost příkazů doplníme podmíněným příkazem. Příkaz if se dá česky vyjádřit větou: „Jestliže platí podmínka, něco vykonej.“ Syntaxe vypadá následovně:
if (podmínka)
{}
else /* tato část je nepovinná */
{}
Pokud platí podmínka v závorce, vykonají se příkazy ve složených závorkách, a pokud podmínka splněna není, bude program vykonávat příkazy ve složených závorkách následujících po příkazu else. Část s else u příkazu if být nemusí, potom by se v případě nesplnění podmínky vykonával kód až za ukončovací složenou závorkou. V podmínce se vyhodnocuje pravdivost nějakého výrazu, např.:
int i;
i = Random(5);
if(i>2) /*pokud bude hodnota v i větší než 2, bude se provádět část za if*/
{
OnFwd(OUT_A+OUT_C);
}
else /*jinak se bude provádět tato část*/
{
OnRev(OUT_A+OUT_C);
}
Operátory použitelné při zápisu podmínek jsou shrnuty v tabulce:
Symbol |
Význam |
== |
je rovno |
!= |
není rovno |
< |
je menší |
> |
je větší |
<= |
je menší nebo rovno |
>= |
je větší nebo rovno |
V závěrečném programu necháme robota rozjet rovně a po 1,5 sekundě náhodně zatočí o 90 stupňů doleva nebo doprava. Po další sekundě znovu náhodně zatočí a poté zastaví.
task main()
{
OnFwd(OUT_A+OUT_C);
Wait(150);
if (Random(1) == 0 )
{
OnRev(OUT_A);
Wait(105);
OnFwd(OUT_A);
}
else
{
OnRev(OUT_C);
Wait(105);
OnFwd(OUT_C);
}
Wait(100);
/*------------------po prvním zatočení----------------------------*/
if (Random(1) == 0 )
{
OnRev(OUT_A);
Wait(105);
OnFwd(OUT_A);
}
else
{
OnRev(OUT_C);
Wait(105);
OnFwd(OUT_C);
}
/*------------------po druhém zatočení----------------------------*/
Off( OUT_A+OUT_C );
}
Příště se podíváme na cykly, využití senzorů a přehrávání hudby.
autoři: Filip Děchtěrenko, Mirek Dočekal a Jakub Sedlák