2. diel - NXJ - základy API a prvý užitočný program
V minulom dieli sme si sprevádzkovali vývojové prostredie pre NXJ. Dnes si konečne urobíme niečo užitočného. Ak ste si prechádzali NXJ firmware na NXT, asi ste si všimli absencia nejaké utilitky na odčítaní hodnôt z vstavaných rotačných senzorov v motoroch a ostatných senzorov. Presne tento nedostatok dnes čiastočne zaplníme. Zároveň nám to poskytne priestor na predstavenie niektorých zo základných tried, ktorými NXJ API disponuje.
Užitočné triedy API
Najskôr si poďme predstaviť triedy, s ktorými budeme pracovať. Pred tým
ale ešte trochu terminológie. Budem používať termín "blokujúce metódy"
(neviem, či to môžem jednoducho preložiť z "blocking method", takže ma
kľudne opravte). Znamená to, že sa vlákno zastaví a čaká na jej
vykonanie. Takým príkladom môže byť trebárs
Button.waitForAnyPress().
Motor
Bezpochyby jedna z najpoužívanejších tried a to či už priamo, alebo nepriamo, pretože len zriedkakedy bude výstupom programu len obraz na displeji alebo zvuk. Najskôr by sme si mali povedať niečo o hardvérovej povahe motorov. Ako som už spomenul, majú vstavané rotačné senzory, ktoré dokážu s presnosťou ± 1 ° snímať fyzickej natočenia výstupu (oranžová časť). Zároveň majú nastaviteľnú rýchlosť, a síce v stupňoch za sekundu. Maximálna rýchlosť == 100 * napätie dodávané batériami, preto závisí od toho, či používate alkalické batérie (6 * 1,5V = 9V => maximálna rýchlosť = 900 ° / s), alebo nabíjacie (6 * 1,2V = 7.2V, plne nabité aj napriek 8V => používajte rýchlosť cca 700 ° / s, 7.2V sú už väčšinou batérie skoro vybité). Samotná trieda Motor nič nevie, ale o to zaujímavejšie sú statické inštancie triedy NXTRegulatedMotor: A, B, a C. Iste viete, že NXT ponúka výstupy pre 3 motory, ktoré sa práve týmito písmenami označujú.
NXTRegulatedMotor
Táto trieda reprezentuje motor pripojený na daný port a k neužitečnějším metódam patrí:
rotate(int angle)
- otočí motor o daný počet stupňov relatívne k súčasnej pozícii; blokujúce metódarotate(int angle, boolean immediateReturn)
- rovnaká ako predchádzajúca, ale ak uvediete druhý parameter true, nebude metóda blokujúcerotateTo(int angle)
- otočí motor do absolútnej pozície k nulovému bodu na nehybnom telu motora. Blokujúce, disponuje rovnakým preťažením ako metódarotate()
forward()
- motor sa začne točiť dopredu, kým ho inou metódou nezastavítebackward()
- rovnako ako predchádzajúce, ale točí sa pospiatkystop()
- jedna z metód, ktorá zastavíforward()
alebobackward()
. Po zavolaní si motory "zabrzdí" a nemožno s nimi otáčať. Blokujúce, ale zastavenie je prakticky okamžité (pokiaľ nezastavuje zotrvačník : D )flt()
- ďalšia metóda na zastavenie, ale tentoraz sa bude motor voľne pretáčať. Opäť teoreticky blokujúce, ale nemá zmysel sa tým zaoberaťsetSpeed(int/float speed)
- nastavuje rýchlosť v ° / sgetTachoCount()
- vracia celkovú relatívnu rotáciu interného rotačného senzora typu int v stupňochresetTachoCount()
- vynuluje interný rotačný senzor. (Presne toto bude jadro nášho programu) Pozor: na konci sa zavolá stop ()
LCD
Ako už názov napovedá, táto statická trieda reprezentuje LCD na NXT. Displej disponuje rozlíšením 100 * 64px a vie len 2 farby- čiernu a bielu (ona nie je biela, ale budeme jej tak hovoriť), nič medzi tým, ak ste nad tým premýšľali. Ešte trochu terminológie - LCD znamená liquid crystal display, preto nepoužívajte spojenie "LCD displej", je to barbarské. metódy:
clear()
- zmaže všetok obsah displejadrawString(String str, int x, int y)
- vykreslí str na určených súradniciach. Nejedná sa o súradnice v pixeloch, ale v znakoch. Na jednu z 8 riadok sa zmestí 16 znakov. Všetky znaky sú rovnako veľké (6 * 8px). Príklad: LCD.drawString ( "hi", 7,3) vykreslí "hi" približne uprostred. Súradnice pochopiteľne začínajú nulou.drawInt(int i, int x, int y)
- rovnaké ako predchádzajúce metóda, len vie kresliť len čísla.setPixel(int x, int y, int color)
- vykreslí jediný pixel na [x, y], pričom tieto súradnice sú v pixeloch. Farba môže mať len hodnoty 1, alebo 0 (1 = čierna, 0 = biela)scroll()
- posunie posledný riadok vypísaný pomocou System.out úplne hore
Sound
Ďalšie statická trieda určená ako výstup informácií. Hoci sa jedná o relatívne nepodstatnú časť, zistíte, že ju budete používať relatívne často. metódy:
setVolume(int vol)
- nastaví hlasitosť reproduktora na hodnotu 0-100. Ak chcete pracovať so zvukom, nezabudnite ju použiť, pretože východiskové hlasitosť je takmer nepočuteľná.- metódy pre pípanie a podobne, nič, čo by stálo za rozobratie
Button
Posledný triedou, ktorú si dnes uvedieme, bude trieda pre prácu s tlačidlami. Na NXT nájdeme 4 tlačidlá - ENTER, ESCAPE, LEFT, RIGHT, každé z nich je reprezentované číselným id a zároveň inštancií triedy Button. Jedinou užitočnou statickú metódou je:
waitForAnyPress()
- s touto metódou sme sa už stretli, zastaví beh programu, pokiaľ nie je stlačené niektoré z tlačidiel, ktoré vráti ako id typu int. Id je konštanta na Button, vyzerá asi takto: Button.ID_ENTER.
Inštančný metódy sú oveľa zaujímavejšie, resp. užitočnejšie:
isUp()
- vracia boolean, či je tlačidlo stlačenéisDown()
- asi nemá cenu popisovať
Prvý užitočná utilitka
Založte si nový projekt (naozaj si ho založte, neprepisujte "hello world", neskôr budeme pracovať s jednotlivými projektmi, a preto sa hodí mať viac ako jeden) "Motor measure" a pridajte hlavnú triedu Main. Všimnite si, že používam anglický názov, a pretože je to veľmi dobrý zvyk, mali by ste s anglickým pojmenováváním začať (ak to už však nerobíte). Tento štýl budem používať počas celého seriálu.
Každý návrh programu musí nutne začať otázkou: Čo vlastne chcem
urobiť? Naša súčasná odpoveď by bol program, ktorý bude odpočítavať
rotáciu motorov a bude nám ich v reálnom čase zobrazovať na displeji + bude
umožňovať vynulovanie hodnôt. Ďalšia otázka bude: Ako? Vzhľadom k tomu,
že sa jedná o naozaj jednoduchý program, použijeme adekvátne jednoduché
riešenie - necháme bežať nekonečnú slučku, ktorá bude neustále
prepisovať hodnoty na LCD na aktuálny. Na začiatku cyklu sa navyše uistíme,
že nie je stlačené žiadne tlačidlo - ak zistíme, že áno, vykonáme - v
prípade enter vynulovanie, v prípade ESCAPE ukončenia programu. Vystačíme
si s metódou main(String[] args)
public static void main(String[] args) throws Exception { NXTRegulatedMotor[] motors = {Motor.A, Motor.B, Motor.C}; // abychom nemuseli opisovat vše pro každý motor zvlášť, budeme je // procházet cyklem char[] names = {'A', 'B', 'C'};// písemné označení motorů na stejných // indexech jako v poli motors while (Button.ESCAPE.isUp()) { LCD.clear();//smazat vše na displeji boolean reset = Button.ENTER.isDown();// chceme vynulovat motory? for (int i = 0; i < motors.length; i++) { NXTRegulatedMotor motor = motors[i];// motor se kterým pracujeme if (reset) { motor.resetTachoCount();// vynulovat motor.flt();// motory se po vynulování zastaví, takto se // budou volně protáčet } LCD.drawString(names[i] + " " + motor.getTachoCount(), 0, i); // v NXJ nefunguje String.format() } Thread.sleep(50);//uspat vlákno na 50ms //kdyby to tu nebylo, displej by podivně problikával } }
Asi nič v kóde nie je nejaká záhada. Všimnite si, že si uložíme stav
tlačidla ENTER na začiatku cyklu namiesto toho, aby sme priamo v kóde
použili Button.ENTER.isDown()
. Robíme to preto, že teoreticky sa
môže stav tlačidla medzi jednotlivými cyklami zmeniť, a taký problém
určite riešiť nechceme. Ďalšia zaujímavosť je, že nemôžeme použiť
String.format()
. Prečo? Pretože to nikto neimplementovala. NXJ
nevyužíva priamo knižnice Javy, ale vlastné. Program si nahrajte a
vyskúšajte. To je pre zatiaľ všetko, nabudúce sa budeme kódu venovať zase
o niečo menej.