Reaali Robootika.COM

NXT robotimaailm ja programmeerimine C-keeles

5. tund: Värvilise rooliga auto

Käesoleva tunni eesmärk on õppida kasutama C-keeles switch-funktsiooni.

Õppematerjal: Juhend- IF ELSE ja SWITCH kasutamine

Ülesanne: Värvilise rooliga auto

Teha BOT mis on ühendatud juhtme abil värvianduriga, mis omakorda on BOT-i juhtimispult.

Juhtimispult ehitada selliselt, et värvianduri ees oleks pöörlev komponent (hammasratas, rool), mille peale on kinnitatud värviline ketas. Rooli otse hoides sõidab robot otse kuid keerates muutub värv ning robot hakkab sellele vastavalt pöörama.

Musta värvi paber kinnita teise klotsi külge, mis liigub värvilise ketta ning värvianduri ees edasi tagasi. Must värv on nagu autol gaas, kui must on ees, siis robot seisab, vastasel juhul liigub vastavalt ketta värvile. Sellesama pildi saad siit suuremana avada ja siis välja printida.

Värviline roolVärvide tähendused:

  • Punane: sõidab otse
  • Sinine-roheline: keerab veidi paremale-vasakule
  • Kollane-oranz: keerab keskmisel paremale-vasakule
  • Helesinine-heleroheline: keerab palju paremale-vasakule
  • Valge: keerab kohapeal ringi

Lahendus.

Nagu arvata oligi siis tegemist on lihtsa programmiga, kuid õpetab hästi switch-funktsiooni olemust.

Rooli ehitamise peamine raskus seisnes selles, et värviandur ei tundnud korralikult värve ära. Esialgu arvasime, et liiga ligidalt mõõdab ning jätsime vahe ca 3 cm. Kuid nüüd oli valge ja musta tulemus sama, mis oli eriti veider.

Lõpuks jõudsime lahenduseni, värviandur tuli paigutada väikese nurga all, muidu see mõõtis enda poolt välja kiirguva valguse peegeldust. Seega HiTechnicu värviandur poolviltu asetades oli tulemus perfektne.

/*
Autor: Ramses Sepp 02.02.2011
Sellel robotil on värviline rool ja must käigukang. 
Rooliga ta sõidab erinevalt ja käigukang peatab roboti. */ task main(){ SetSensorLowspeed(S2); while (TRUE){ switch (SensorHTColorNum(S2)) { //must - mootorid seisavad case 0: Off(OUT_BC); ClearScreen(); TextOut(5, LCD_LINE3, "must"); break; //sinine - robot keerab kergelt paremale case 2: OnFwdSync(OUT_BC, -50, 5); ClearScreen(); TextOut(5, LCD_LINE3, "sinine"); break; //helesinine - robot keerab palju paremale case 3: OnFwdSync(OUT_BC, -50, 35); ClearScreen(); TextOut(5, LCD_LINE3, "helesinine"); break; //roheline - robot keerab kergelt vasakule case 4: OnFwdSync(OUT_BC, -50, -5); ClearScreen(); TextOut(5, LCD_LINE3, "roheline"); break; //kollane - keerab keskmiselt paremale case 6: OnFwdSync(OUT_BC, -50, 15); ClearScreen(); TextOut(5, LCD_LINE3, "kollane"); break; //oranþ keerab keskmiselt vasakule case 8: OnFwdSync(OUT_BC, -50, -15); ClearScreen(); TextOut(5, LCD_LINE3, "oranþ"); break; //punane - sõidab otse case 9: OnFwdSync(OUT_BC, -50, 0); ClearScreen(); TextOut(5, LCD_LINE3, "punane"); break; //heleroheline - keerab palju vasakule case 13: OnFwdSync(OUT_BC, -50, -35); ClearScreen(); TextOut(5, LCD_LINE3, "heleroheline"); break; //valge - keerab kohapeal ringi case 17: OnFwdSync(OUT_BC, -50, 100); ClearScreen(); TextOut(5, LCD_LINE3, "valge"); break; } } }

Juhend: NXT ekraani kasutamine

Ekraani saab kasutada selleks, et saada aktiivselt tagasisidet roboti töö kohta. Alljärgnevalt mõned peamised käsud NXC-s, mille abil juhtida ekraani. Siin on toodud välja ka NXT-l asuvad nupud ja heli tegemine.

ClearScreen();

 

Puhastab ekraani.

ClearLine(“Line”);

ClearLine(LCD_LINE2);

Puhastab ekraanil rea nr 2.

TextOut(“x”, “line”, “txt”, “options”);

TextOut(50, LCD_LINE3, "Hello World");

 

Kirjutab  ekraanil reale nr 3 sõnad „Hello World“.

NumOut(“x”, “line”, “val”, “options”);

TextOut(50, LCD_LINE3, 38);

 

Kirjutab  ekraanil reale nr 3 numbri 38.

ButtonPressed(“btn”,“reset”);

ButtonPressed(BTNRIGHT, FALSE);

Kontrollitakse nupuvajutust.

BTNRIGHT

BTNLEFT

BTNCENTER

BTNEXIT

Reset on TRUE/FALSE ning see nullib nupuvajutuste arvu.

PlayTone(“frequency”, “duration”);

PlayTone(440, SEC_2);

Mängib 2 sekundit tooni sagedusel 440 Hz.

Juhend: Matemaatika C-keeles

Programmide kirjutamisel on tarvis liita-lahutada-korrutada-jagada. Oma tavapärasest matemaatikas oleme harjunud kirjutama, et a + b = c.

C-keeles saab aga asju lühemalt väljendada, kõik ikka selleks et programm oleks lihtsam.

Tüüpiliselt on programmis muutuja (see on mingi arv näiteks), millele on vaja juurde liita mingi teine number.

Matemaatiliselt tavaline liitmistehe on võimalik C-keeles järgmiselt teha x += y. Hea lühike.

Tehe C-keeles Kirjeldus

liitmine

x += 2

Liidab muutujale juurde teise arvu. 

  • Olgu x alguses 1
  • Seejärel liidame x-le juurde 2 (x + 2 = 3)
  • Tulemuse kirjutame iseendasse, st. x-le omistatakse väärtus 3 ja seega x = 3

See tehe on pikemalt välja kirjutades x = x + 2

Näide 2. x += y

  • olgu x alguses 3 ja y väärtus 2
  • ülaltoodud tehe on x + y ehk siis 3 + 2 = 5
  • antud arv 5 omistatakse x-le, ja seega x = 5

lahutamine

x –= 2

Lahutab muutujast teise arvu. 

  • Olgu x alguses 5
  • Seejärel lahutame x-st arvu 2 (x – 2 = 3)
  • Tulemuse kirjutame iseendasse, st. x-le omistatakse väärtus 3 ja seega x = 3

See tehe on pikemalt välja kirjutades x = x - 2

korrutamine

x *= 2

Korrutab muutujat teise arvuga. 

  • Olgu x alguses 3
  • Seejärel korrutame x-i arvuga 2 (x * 2 = 6)
  • Tulemuse kirjutame iseendasse, st. x-le omistatakse väärtus 6 ja seega x = 6

See tehe on pikemalt välja kirjutades x = x * 2

jagamine

x /= 2

Jagab muutujat teise arvuga. 

  • Olgu x alguses 6
  • Seejärel jagame x-i arvuga 2 (x / 2 = 3)
  • Tulemuse kirjutame iseendasse, st. x-le omistatakse väärtus 3 ja seega x = 3

See tehe on pikemalt välja kirjutades x = x / 2

liitmine
ühe ühiku võrra

i++

Kahekordne pluss tähistab seda, et muutujale i liidetakse juurde üks ühik.

  • Olgu i alguses 1
  • peale selle käsu käivitamist on tehtud tehe i + 1
  • seega tulemus, i = 2

lahutamine
ühe ühiku võrra

i--

Kahekordne miinus tähistab seda, et muutujast i lahutatakse üks ühik.

  • Olgu i alguses 10
  • peale selle käsu käivitamist on tehtud tehe i - 1
  • seega tulemus, i = 9

Juhend: IF ELSE ja SWITCH kasutamine

Programmeerimise enimkasutatav funktsioon on ilmselgelt IF ja IF ELSE laused. Tegemist siis tingimuste kontrolliga ning vastavalt sellele tegevuse ette võtmine.

Teise funktsioonina olen alljärgnevalt välja toonud ka SWITCH funktsiooni, kuna selle näol on tegemist nö. pika if-elseif-elseif-else lausendi jadaga.


if ("condition”) {“body” } else {“body” }

if (x == 1) {
   y = 1;
   z = 2;
 }
 else {
   y = 3;
   z = 5;
 }

Kui tingimus on tõene, täidetakse esimene käsk kui tingimus on väär täidetakse alternatiivne käsk.

IF lause sees võib ELSE IF lauseid palju olla, vaata alljärgnevat.

if (x == 1) {
   y = 1;
   z = 2;
 }
 else if (x == 2) {
   y = 3;
   z = 5;
 }
else {
  y = 6;
  z = 7;
 }

 

Sellisel juhul kontrollitakse kõigepealt IF tingimust kui see on väär minnakse edasi ja kontrollitakse ELSE IF tingimust, kui ka see on väär minnakse edasi järgmise kontrolli juurde.

Ehk siis ülaltoodud IF lauset tuleks lugeda järgmiselt: Kui x on võrdne 1-ga, pane y väärtuseks 1 ja z väärtuseks 2, kui aga x on võrdne 2-ga, pane y väärtuseks 3 ja z väärtuseks 5, või muidu pane y väärtuseks 6 ja z väärtuseks 7.


switch ("expression”) {“body” }

switch(x)
 {
        case 1:
         // tee midagi kui x on 1
         break;
        case 2:
        case 3:
         // tee midagi kui x on 2 või 3
         break;
        default:
         // tee midagi kui x pole 1, 2 või 3
         break;
 }

 

Switch kontrollib x väärtust ja vastavalt selle väärtusele teostab operatsiooni. See on sama tulemus kui ELSE IF funktsiooni jada kasutades. Kuid switch konstruktsiooni on oluliselt lihtsam kasutada võrreldes ELSE IF lausete jadaga.

Näiteks värviandurist värvi-info saamise korral, musta värvi korral tehakse ühtemoodi, punase korral teisiti jne.

Või infrapuna seekerist saabuvate numbrite 1..9 korral saan kirjeldada, mida ühel või teisel juhul tehakse.

Juhend: while, until tsüklite kasutamine

Programmeerimise peamised konstruktsioonid seisnevad tsüklites ning tingimuslausetes. Tsükkel on  tegevus mida korratakse seni, kuni etteantud tingimus vastab tsükli konstruktsioonile. Alljärgnevalt vaatame tsükleid while ning until ja seda mille poolest need erinevad.

Väga levinud on robootikas kasutada lõpmatult täidetavat tsüklit, seda läheb praktiliselt tarvis iga lõputult toimiva programmi korral.


while("tingimus")

while(x < 10)
 {
        x += 1;
        y *= 2;
 }

Kontrollitakse tingimust x<10 kui see on tõene, täidetakse while tsükli sisu ning siis kontrollitakse taas tingimust. Toimub seni kuni tingimus on väär - siis väljutakse tsüklist. Seega antud näite korral läbitakse tsüklit 9 korda, sest 10-dal korral on x = 10, seega tingimus pole tõene ja väljutakse tsüklist ehk minnakse programmiga edasi. 

while(TRUE) see on lõpmatult kestev tsükkel. Kuna TRUE tähendab seda, et avaldise väärtus on alati tõene siis selline tsükkel täidab oma sisu lõpmatu arv kordi.

Alljärgnev on näide nupu “bumped” funktsiooni teostamine:

while(!Sensor(S1));        // ootab nupule vajutamist
while(Sensor(S1));         // ootab nupu lahti laskmist


Ülalkirjeldatud bumped-funktsionaalsus töötab järgmiselt. Kui nupp on lahti siis see tähendab, et esimene tsükkel on tõene. Kui nupp vajutatakse alla, muutub esimese tsükli tingimus vääraks ning tõeseks muutub teise tsükli tingimus. Kui nuppu hoitakse all ei lähe programm edasi, kuna täidetakse teist tsüklit. Nupu lahti laskmise korral muutub tingimus vääraks ning programm läheb edasi.

 


until(EVENT_OCCURS);

until(SensorUS(S1) > 50);

until käitub vastupidiselt while tsüklile, st. see funktsioon ootab kuni tema tingimus saab tõeseks. Seda saab kasutada edukalt programmi seiskamiseks ning andurist kindla signaali ootamiseks.

Alljärgnev on näide nupu “bumped” funktsiooni teostamine, võrdle while tsükliga:

until(Sensor(S1));         // ootab nupule vajutamist
until(!Sensor(S1));        // ootab nupu lahti laskmist

Kui nupp on avatud siis esimese until funktsiooni tingimus on FALSE ja seega programm ootab selle taga. Nupu allavajutamisel muutub tingimus TRUE-ks ning programm läheb edasi, jäädes ootama teise until funktsiooni taha. Kui nüüd nupp lahti lasta ehk nupu väljund on FALSE, muutub teise until funktsiooni tingimus TRUE-ks ning programm liigub edasi

Juhend: Mootorite peamised käsud NXC-s

Alljärgnevalt peamised NXC käsud, mille abil robot liikuma või seisma panna.

OnFwd("ports", "pwr"); OnRev(..)

OnFwd(OUT_A, 75);

Mootor A liigub edasi kiirusega 75


OnFwdSync("ports", "pwr", “turn”); OnRevSync(..)

OnFwdSync(OUT_AB, 75, -100);

Mootorid A ja B liiguvad edasi ning neid hoitakse sünkroonis. Turn ehk keeramine -100 määrab ära kummale poole keeratakse. 0 – sõidab otse, 50 – üks ratas seisab, 100 – rattad liiguvad vastassuundades.


OnFwdReg("ports", "pwr", OUT_REGMODE_SPEED); OnRevReg(..)

OnFwdReg(OUT_AB, 100, OUT_REGMODE_SPEED);

Mootorid A ja B sõidavad otse ning rakendavad lisajõudu kui ette satub takistus.


Off(OUT_AB);

Off(OUT_AB);

Lülitab mootorid A ja B välja


RotateMotor("ports", "pwr", “degrees”);

RotateMotor(OUT_A, 75, 360);

Pöörab mootorit A 360 kraadi kiirusega 75.


RotateMotorEx("ports", "pwr", “degrees”, “turn”, “sync”, “stop”);

RotateMotorEx(OUT_AB, 75, 360, 50, TRUE, TRUE);

Keerab mootoreid A ja B 360 kraadi kiirusega 75. Turn määrab ära kummale poole keeratakse (0 – sõidab otse, 50 – üks ratas seisab, 100 – rattad liiguvad vastassuundades), sync määrab et mootorid on sünkroonis ja stop määrab kas lõpus on vaja pidurdada või mitte.


Coast("ports”);

Coast(OUT_AB);

Laseb määratud mootorid vabajooksuga seismiseni.

Juhend: Andurite defineerimine ja lugemine

Roboti juures andurite kasutamine on seotud kahe tegevusega: a) defineerimine b) lugemine.
Selleks, et programmis andureid kasutada (lugeda), tuleb robotile kõigepealt selgeks õpetada millised andurid ja kus pordis asuvad.

Alljärgnevas tabelis on andurite initsialiseerimisega seotud funktsioonid. Erinevaid andureid tuleb erineval moel initsialiseerida.

SetSensorLight("port");

SetSensorLight(S1);
Valgussensori initsialiseerimine pordis 1.

SetSensorTouch("port")

SetSensorTouch(S1);
Puuteanduri initsialiseerimine pordis 1.

SetSensorSound("port");

SetSensorSound(S1);
Helianduri initsialiseerimine pordis 1.

SetSensorHTEOPD("port");

SetSensorHTEOPD(S1);
Hitechnic EOPD sensori initsialiseerimine.

SetSensorHTGyro("port");

SetSensorHTGyro(S1);
Hitechnic Gyro sensori initsialiseerimine.

SetSensorLowspeed("port");

SetSensorLowspeed(S1);
Ultrasonic ja Hitechnic IRSeeker, Color, Compass sensori initsialiseerimine pordis 1.

Anduritelt andmete lugemiseks kasutatavad funktsioonid on alljärgnevas tabelis. Jällegi tuleb tähele panna, et osade andurite jaoks saab kasutada sama funktsiooni lugemiseks, kuid osade jaoks on spetsiifilised funktsioonid.

Sensor("port");

Sensor(S1);
Andmete lugemine Touch, Light, Sound sensorist.

SensorUS("port");

SensorUS(S1);
Andmete lugemine Ultrasonic sensorist.

SensorHTGyro("port", “Offset”);

SensorHTGyro(S1, 2);
Andmete lugemine Gyro sensorist. Ette on antud offset ehk nulli hälve.

SensorHTEOPD("port");

SensorHTEOPD(S1);
Andmete lugemine EOPD sensorist.

SensorHTCompass("port");

SensorHTCompass(S1);
Andmete lugemine Compass sensorist.

SensorHTIRSeekerDir("port");

SensorHTIRSeekerDir(S1);
IR Seeker sensorist suuna lugemine.

SensorHTColorNum("port");

SensorHTColorNum(S1);
Värviandurist vastava värvi numbri lugemine.

Juhend: Loogika kasutamine

Loogikalülitused omavad NXT-maailmas alati ja ainult kahte väärtust: true või false (1 või 0).
1 ja 0 abil saab teha hulgaliselt tehteid ning lahendada erinevaid ülesandeid. Programmis tähistatakse seda tüüpi muutujat sõnaga bool (tuletatud sõnast Boolean ehk kahendmuutuja).
C-keeles muutuja defineerimine ja algväärtustamine:
bool ShootBall = FALSE;
Enimkasutatavad kahendmuutujatega tehtavad tehted on AND (JA), OR (VÕI), XOR (välistav VÕI), NOT (EI).
Kahendmuutujate tabelid
Loogikatehete vasted NXC-s:
AND tehte korral kasuta kahte ja märki &&
Alltoodud avaldistes muutub if lause tõeseks ainult siis kui mõlemad muutujad on tõesed. Kõik toodud kolm kombinatsiooni on õiged, kuid soovituslik on kasutada esimest kui kõige lühemat varianti.
if(ShootBall && ShootButton)
if(ShootBall == TRUE && ShootButton == TRUE)
if(ShootBall == 1 && ShootButton == 1)

OR tehte korral kasuta kahte püstist kriipsu ||
Alltoodud avaldistes muutub if lause tõeseks juba siis kui vaid üks muutuja on tõene ja jääb ka tõeseks kui mõlemad on 1-d. Kõik toodud kolm kombinatsiooni on õiged, kuid soovituslik on kasutada esimest kui kõige lühemat varianti.
if(ShootBall || ShootButton)
if(ShootBall == TRUE || ShootButton == TRUE)
if(ShootBall == 1 || ShootButton == 1)

NOT tehte korral kasuta hüüumärki !
Alltoodud avaldise sees muudab hüüumärk muutuja väärtuse vastupidiseks. If lause muutub tõeseks sel juhul kui muutuja on FALSE ehk 0. Kuigi kõik alljärgnevad avaldised annavad sama tulemuse, on soovituslik kasutada esimest kui lühimat.
if(!ShootBall)
if(ShootBall == FALSE)
if(ShootBall == 0)