Programování pro malé i velké – Lego RIS 2.0, základy jazyka NQC, 2. díl

V minulém díle našeho seriálu zaměřeného na programování jsme se naučili robota rozhýbat a příkazem if podmínit jeho činnost. Tématem druhého dílu budou cykly, využití senzorů a vyluzování zvuků.

Cyklus s daným počtem opakování

Potřebujeme-li opakovat skupinu příkazů, použijeme cyklus. Opakovat lze daný počet n-krát nebo podmíněně.

Zápis vypadá následovně:

repeat(n)
{
  příkaz1;
  příkaz2;
  …
}

Blok příkazů mezi složenými závorkami se bude vykonávat n-krát. Konkrétním příkladem může být pokus o jízdu robota do čtverce. Přesné hodnoty obou konstant musíte zjistit metodou pokus/omyl, protože jízda robota je ovlivněna spoustou přirozených faktorů (povrch, výkon motorů konkrétní stavebnice, stav baterií aj.).

#define pohyb_rovne  150
#define pohyb_zataceni  100
task main()
{
  OnFwd(OUT_A+OUT_C);
  repeat(4) /*robot čtyřikrát zatočí*/
  {
    Wait(pohyb_rovne);
    OnRev(OUT_A);
    Wait(pohyb_zataceni);
    OnFwd(OUT_A);
  }
  Off(OUT_C+OUT_A);
 
}

Kód s cyklem je přehlednější, než zapsaný bez něj.

Cyklus s podmínkou na začátku

Syntax tohoto cyklu je následující:

while(podmínka)
{
  příkaz1;
  příkaz2;
}

Příkazy uvnitř složených závorek se vykonají pouze v případě, že platí podmínka v závorce. Často se používá konstrukce while(true) – v tomto případě se budou příkazy mezi závorkami vykonávat stále znovu a znovu, protože podmínka true je vždy platná. Tento zápis má praktický význam při práci se senzory.

Použijeme-li v cyklu příkaz break, cyklus se přeruší a začnou se vykonávat příkazy následující bezprostředně za ním. Poslední příkaz používaný uvnitř těla cyklů je continue. Tento příkaz ukončí právě prováděný průchod cyklem a vynutí přechod k dalšímu průchodu.

Senzory

Díky senzorům může robot reagovat na vnější podněty. Základními senzory jsou dotykový a světelný senzor.

Dotykový senzor

Při stisku mikrospínače vyšle dotykový senzor signál RCX kostce, která na něj může reagovat. V programu je nejprve potřeba nastavit jeden ze vstupů tak, aby byl připraven na data z dotykového senzoru. To se provede příkazem SetSensor(SENSOR_x,SENSOR_TOUCH), kde x je číslo vstupu, ke kterému je dotykový senzor připojen.

SENSOR_1 je proměnná, v níž se zaznamenává hodnota v závislosti na poloze senzoru. Pokud je senzor stlačen, přiřadí se do proměnné SENSOR_1 hodnota 1, v opačném případě obsahuje proměnná hodnotu 0.

Použití dotykového senzoru vypadá následovně:

task main()
{
  SetSensor(SENSOR_1,SENSOR_TOUCH);
  OnFwd(OUT_A+OUT_C); /*robot jede rovně,…*/
  while(SENSOR_1!=1)  /*…dokud nenarazí*/
  {}
  Off(OUT_C+OUT_A);
}

Světelný senzor

Další ze senzorů je světelný. Tento senzor vyšle infračervený paprsek a podle toho, jak se odrazí, dokáže přibližně rozeznat tři barvy. V programu je nejprve opět potřeba připravit vstup ze senzoru příkazem SetSensor(SENSOR_x,SENSOR_LIGHT), kde x je číslo vstupu, ke kterému je připojen světelný senzor.

#define SVETLO  40
task main()
{
  SetSensor(SENSOR_1,SENSOR_LIGHT);
  OnFwd(OUT_A+OUT_C);
  while(SENSOR_1<SVETLO)
  {}
  Off(OUT_C+OUT_A);
}

Tento program zapne oba motory a robot pojede dopředu, dokud světelný senzor nezaznamená tmavší objekt.  Kontrola, zda nebylo nalezeno tmavé místo, probíhá porovnáním hodnoty proměnné SENSOR_1 s konstantou prahové hodnoty černé barvy senzoru (obvykle to bývá 40). Senzor dokáže rozeznat podle intenzity osvětlení tři barvy: bílou, zelenou a černou. Každou z nich můžeme rozpoznat podle určitého rozmezí dat ze senzoru.

Rozmezí Barva
>50 bílá
43-47 zelená
<40 černá

Pokud budeme například kontrolovat, zda robot nepřejel přes zelenou čáru, napíšeme:

while(SENSOR_2>42 && SENSOR_2<48)
{}

Stejné hodnoty získané z optického senzoru nemusí odpovídat vždy stejné barvě – výsledky závisí na vzdálenosti optického senzoru od sledovaného objektu. Pokud se infračervený paprsek špatně odrazí, nemusí výsledek skutečnosti odpovídat vůbec. Proto je vhodné pro každou barvu používat určité rozmezí, které lze metodou pokus/omyl upřesnit. Takto je možné dokonce vymezit i další barvy.

Hudba

Kostka RCX může přehrávat tóny. Kromě vlastního zvukového efektu mohou při programování sloužit k lepší kontrole činnosti robota.

Tóny přehráváme příkazem PlayTone(x,t), kde x je frekvence tónu a t je doba tónu (stejně jako u příkazu Wait() je v setinách sekundy). Tedy příkaz PlayTone(440,100) zahraje tón a1 po dobu jedné sekundy. Za každým zvukovým příkazem by měl následovat příkaz Wait(), protože procesor RCX nečeká, až zvuk dozní, ale začne vykonávat další příkaz.

Přehled jednotlivých frekvencí je uveden v tabulce:

Oktáva
Tón 1 2 3 4 5 6 7 8
G# 52 104 208 415 831 1661 3322  
G 49 98 196 392 784 1568 3136  
F# 46 92 185 370 740 1480 2960  
F 44 87 175 349 698 1397 2794  
E 41 82 165 330 659 1319 2637  
D# 39 78 156 311 622 1245 2489  
D 37 73 147 294 587 1175 2349  
C# 35 69 139 277 554 1109 2217  
C 33 65 131 262 523 1047 2093 4186
B 31 62 123 247 494 988 1976 3951
A# 29 58 117 233 466 932 1865 3726
A 28 55 110 220 440 880 1760 3520

Následující program přehraje jednoduchou melodii.

task main()
{
  PlayTone(147,40);  Wait(45);
  PlayTone(165,40);  Wait(45);
  PlayTone(175,40);  Wait(45);
  PlayTone(165,40);  Wait(45);
}

Na závěr uvedeme program se všemi dosud probranými prvky jazyka NQC. Robot pojede dopředu, a pokud narazí, změní směr. Jakmile narazí popáté, zastaví se.

task main()
{
  SetSensor(SENSOR_1,SENSOR_TOUCH);
  SetSensor(SENSOR_3,SENSOR_TOUCH);
  int i;
  i=0;
  OnFwd(OUT_A+OUT_C);
  while(true)   /*nekonečný cyklus*/
  {
    while(SENSOR_1!=1) /*robot jede rovně, dokud nenarazí*/
    {}
    i=i+1;   /*počet nárazů se zvětší o 1*/
    if (i=5)   /*pokud robot narazil pětkrát, cyklus končí*/
      break;
    OnRev(OUT_A+OUT_C); Wait(50); /*pojede půl sekundy dozadu*/
    OnFwd(OUT_A); Wait(40);   /*zatočí*/
    OnFwd(OUT_C);    /*a opět jede rovně*/
  }
  Off(OUT_A+OUT_C);
}

V příštím díle našeho seriálu ze světa programování dokončíme základy jazyka NQC.

autoři: Filip Děchtěrenko, Mirek Dočekal a Jakub Sedlák

Váš názor Další článek: Ke stažení: Podívejte se na družice pomocí počítače!

Témata článku: , , , , , , , , , , , , , , , ,