Reaali Robootika.COM

NXT robotimaailm ja programmeerimine C-keeles

7. tund: NXT kiiruse testimine

Tunni sisu on testida NXT aju protsessori kiirust kahe erineva programmeerimiskeele NXC ja NXT-G ja erinevate NXT Firmwarede korral.

Õppematerjal: Juhend- Do–While ja For tsüklid

Antud ülesande lahendame C-keeles FOR tsükliga.

Ülesanne. NXT kiiruse testimine.

Programm peab välja nägema järgmine.

Programmi käivitudes alustab tööd tsükkel, mis teeb 10 000/100 000 tavalist tsüklit. Lisaks on vaja kirjutada juurde stopper, mis mõõdab nende tsüklite läbimiseks kulunud aega ning kuvab selle ekraanil peale tsükli lõpetamist.

Kirjeldatud programm tuleb luua nii NXT-G kui ka NXC-s. Mõõta ja panna kirja tulemused.

Lisaks tuleb katsetada seda erineva NXT Firmware-ga. 

  • NXC: 1.28
  • Mindsensor: 1.29
  • Lego: 1.29
  • Lego: 1.31

Mõõta ja katsetada kas on erinevate Firmwarede ja programmeerimiskeeltega kiirustes erinevusi. Alljärgnevas tabelis on erinevate mõõtmiste kokkuvõte, tulemused on sekundites.

  Firmware 1.28
NXC
Firmware 1.29
Lego
Firmware 1.31
Lego
Firmware 1.29
Mindsensor
tsükleid NXT-G NXC NXT-G NXC NXT-G NXC NXT-G NXC
10 000 2,197 s 0,806 s 2,179 s 0,774 s 2,176 s 0,773 s 2,059 s 0,736 s
100 000 21,903 s 8,061 s 21,715 s 7,742 s 21,687 s 7,731 s 20,516 s 7,359 s
                 

Erakordselt suur vahe on programmeerimiskeele valikul. NXC on peaaegu 3 korda kiirem kui NXT-G.

Teine, kuid võrdlemisi tagasihoidlik vahe on Firmware’s.

Kuna me kirjutame programme C-keeles, on meil peamiselt laetud NXC firmware 1.28. Olen avastanud sellel firmware’l ühe puuduse, nimelt Mindsensori I2C Digital Port Splitter taga olevad andurid ei tööta selle firmware korral.

Kui laadida aga Mindsensori firmware (et töötaks I2C Digital Port Splitter), ei tööta jällegi mõned NXC spetsiifilised funktsioonid, nagu näiteks HiTechnic Prototype Boardi juhtimine.


Lahendus: NXC programm

/*
autor:Ramses Sepp 16.02.2011   19:28
See programm mõõdab aega mis kulub NXT-l ühe miljoni tsükli läbimiseks
Muudetud: Leivo Sepp 18.02.2011
*/

long LIIDA = 0;
long START;

long Stopper(long tsykkel)
{
	START = CurrentTick();
	//siin defineerin muutuja "i" mis võrdub nulliga 
	//ning paneb iga kord ühe i-le juurde
	//seni kaua kuni on üks miljon täis
	for(long i = 0; i < tsykkel; i++){
		//et NXT-l oleks ka mingi lihtne tehe arvutada
		LIIDA += 4;	
		}
	//funktsioon Stopper tagastab stopperi lõpuaja
	return CurrentTick()-START;
}

task main(){

long k = 10000;
string msg, stpr;

for (long j = 1; j < 3; j ++ ){
	//Kuvame ekraanil, et programm on alles käimas
	TextOut(3, LCD_LINE1, "Running ... ");
	//moodustame stringi ekraanile, mis kuvab tsükli arvu ja kestuse
	msg = StrCat(NumToStr(k), ":              ");
	stpr = NumToStr(Stopper(k));
	msg = StrReplace(msg, 8, stpr);
	TextOut(5, LCD_LINE2-j*8, msg);
	//korrutame tsükliarvu 10-ga
	k *= 10;
	}
ClearLine(LCD_LINE1);
TextOut(3, LCD_LINE1, "Valmis");
//programm jääb nupulevajutust ootama
until(ButtonPressed(BTNCENTER, FALSE));
}

Lahendus 2: NXT-G programm

NXT-G programm on selles mõttes lihtsam tehtud, et iga mõõtmise korral tuleb eraldi loop-le counter määrata: 10 000/100 000. NCX programmis toimus see automaatselt.

image

Juhend: HiTechnic prototüüpimislaud

HiTechnic NXT andurite tootjana on teinud ka ühe väga laheda asja – nimelt prototüüpimislaud.

http://www.hitechnic.com/cgi-bin/commerce.cgi?preadd=action&key=NPK1056 

Sellel on 5 analoogsisendit (1024 astet pingega 0..3,3 V) ning 6 digitaalset sisendit/väljundit, mille abil saab kõikvõimalikke keerukaid asju teha. Alljärgnevalt kaks lihtsat näidisprogrammi: a) jooksvad tuled ja b) KITT tuled.

Jooksvad tuled ja KITT tuled HiTechnic Prototype Board abil

Jooksvad tuled

Käesoleva juhendi käigus vaatame ainult prototüüpimislaua digitaalsete väljunditesse kirjutamise osa.

Prototüüpimislaual on 6 digitaalset väljundit B0…B5. Neid saab kasutada nii sisendi kui ka väljundi režiimis. Register “Digital Control” määrab ära millised pordid on sisendid ja millised väljundid. Näiteks “Digital Control” registris number 63 (kahendsüsteemis 111111) muudab kõik väljunditeks.

Digital Out registrisse antud number määrab ära milline väljundportidest on aktiveeritud 1-ga. 1 tähendab siis 3,3V ja 12mA. Näiteks Digital Out numbriga 63 (ehk 0x3F) tähendab, et kõik valgusdioodid põlevad.

Alljärgnev programm suunab DigitalOut registrisse järjest numbrid 1,2, 4, 8, 16, 32 (0x01, 0x02, 0x04, 0x08, 0x10, 0x20).

Alljärgnevalt näidisprogramm kuidas teha prototüüpimislaua abil jooksvad tuled NXC programmeerimiskeeles.

/*
Leivo Sepp 12.02.2011
See programm kasutab HiTechnicu prototüübi plaati
Paneb plaadi taha ühendatud valgusdioodid järjekorras põlema
Ehk teisisõnu "jooksvad tuled"
*/


#define PROTO_PORT S1

int count;
int light = 0x01;
byte cmndbuf[];
byte respbuf[];                 

/* protoboard I/O map
   42,43 - A0 input
   44,45 - A1 input
   46,47 - A2 input
   48,49 - A3 input
   4A,4B - A4 input
   4C    - B inputs
   4D    - B outputs
   4E    - B controls
*/

//see alamprogramm teostab reaalse kirjutamise protolaua registrisse
//aktiveerides kindla pordi (B0..B5), mille taga peab süttima valgusdiood
void writedata(int outputdata)
  {
  //loo 3 väärtusega massiiv
  ArrayInit(cmndbuf, 0, 3);
  //protolaua aadress
  cmndbuf[0] = 0x02;
  //register kuhu kirjutatakse 4D on output
  cmndbuf[1] = 0x4D;
  //output registrisse kirjutatakse number mis aktiveerib kindla väljundi
  cmndbuf[2] = outputdata;
  count=0;
	//Käivitada eelnevate andmete põhjal protolauda kirjutamine
  I2CBytes(PROTO_PORT, cmndbuf, count, respbuf);  
  }

task main()
  {
  SetSensorLowspeed(PROTO_PORT); 
  Wait(100);

  //massiivi initsialiseerimine, 3 väärtust
  ArrayInit(cmndbuf, 0, 3);
  //esimene väärtus massiivis, prototüüpimislaua aadress
  cmndbuf[0] = 0x02;
  //teine väärtus massiivis, registri Control valimine (sisendid/väljundid)
  cmndbuf[1] = 0x4E;
  //kirjutada registrisse Control number 63 ehk 111111
  //st. et kõik B0..B5 on väljundid
  cmndbuf[2] = 0x3F;
  //mitu baiti peab I2C protolaud tagastama, meie puhul 0
  count=0;
  //Käivitada eelnevate andmete põhjal protolauda kirjutamine
  I2CBytes(PROTO_PORT, cmndbuf, count, respbuf);
  Wait(100);

  while (TRUE)
    {
    //kutsutakse välja alamprogramm, kuhu kirjutatakse number
    //numbrid on 1, 2, 4, 8, 16, 32
    writedata(light);
     light = light * 0x02;
     if (light == 0x40)
        light = 0x01;
    Wait(100);
    }
}

KITT tuled.

Ja teine programm, mis paneb tuled edasi-tagasi liikuma, ehk nagu KITT
/*
Leivo Sepp 12.02.2011
See programm kasutab HiTechnicu prototüübi plaati
Paneb plaadi taha ühendatud valgusdioodid edasi/tagasi põlema
Ehk teisisõnu "KITT tuled"
*/


#define PROTO_PORT S1

int count;
int light = 0x01;
byte cmndbuf[];
byte respbuf[]; 
bool kitt=TRUE;                

/* protoboard I/O map
   42,43 - A0 input
   44,45 - A1 input
   46,47 - A2 input
   48,49 - A3 input
   4A,4B - A4 input
   4C    - B inputs
   4D    - B outputs
   4E    - B controls
*/

//see alamprogramm teostab reaalse kirjutamise protolaua registrisse
//aktiveerides kindla pordi (B0..B5), mille taga peab süttima valgusdiood
void writedata(int outputdata)
  {
  //loo 3 väärtusega massiiv
  ArrayInit(cmndbuf, 0, 3);
  //protolaua aadress
  cmndbuf[0] = 0x02;
  //register kuhu kirjutatakse 4D on output
  cmndbuf[1] = 0x4D;
  //output registrisse kirjutatakse number mis aktiveerib kindla väljundi
  cmndbuf[2] = outputdata;
  count=0;
	//Käivitada eelnevate andmete põhjal protolauda kirjutamine
  I2CBytes(PROTO_PORT, cmndbuf, count, respbuf);  
  }

task main()
  {
  SetSensorLowspeed(PROTO_PORT); 
  Wait(100);

	//massiivi initsialiseerimine, 3 väärtust
  ArrayInit(cmndbuf, 0, 3);
  //esimene väärtus massiivis, prototüüpimislaua aadress
  cmndbuf[0] = 0x02;
  //teine väärtus massiivis, registri Control valimine (sisendid/väljundid)
  cmndbuf[1] = 0x4E;
  //kirjutada registrisse Control number 63 ehk 111111
  //st. et kõik B0..B5 on väljundid
  cmndbuf[2] = 0x3F;
  //mitu baiti peab I2C protolaud tagastama, meie puhul 0
  count=0;
  //Käivitada eelnevate andmete põhjal protolauda kirjutamine
  I2CBytes(PROTO_PORT, cmndbuf, count, respbuf);
  Wait(100);

    while (TRUE)
    {
    //kutsutakse välja alamprogramm, kuhu kirjutatakse number
    //numbrid on 1, 2, 4, 8, 16, 32
    writedata(light);
    if (kitt){
    	 //numbrid jooksevad väiksemast suuremaks
       light = light * 0x02;
       if (light == 0x20){
          kitt = FALSE;
          }
       }
    else {
    	  //numbrid jooksevad suuremast väiksemaks
        light = light / 0x02;
        if (light == 0x01)
           kitt = TRUE;
        }
    Wait(200);
    }
}

Kahe seina vahel roniv robot

Ma tegin ühe roboti mis ronib kahe seina vahel üles-alla. Seda ehitades mul polnud mitte mingit probleemi. Kuid kui ma jõudsin programmeerimise juurde siis tekkis mul küll mõningaid probleeme. Kuid enne räägin milline oli mu roboti programmeerimise järjekord. Kõigepealt kui robot oli valmis siis polnud mingit muret esimese kolmandikuga alustada. Esimeses kolmandikus ma panin ta lihtsalt üles sõitma seni kuni ta näeb lähedamal kui 10 cm lage. Sellega erilisi probleeme ei tekkinud kuna see oli üpriski lihtne programm. Teise kolmandiku programmist ma panin roboti sõitma küll pikema programmiga kuid mõne algaja jaoks ka kergem ning seekord sõitis robot lõpmatuseni üles-alla. Minu viimane kolmandik programmist sõitis robot ka muidugi lõpmatusein üles alla kuid nüüd on see lühem ja kergem kui eelmine kord.

Mu isa tegi sellest ka video:

Kahe seina vahel ronija robot

Programm näeb välja selline:

/*
Autor:Ramses Sepp 09.02.2011
See programm võimaldab robotil sõita kahe seina vahelt üles
*/

//See alamprogramm juhib roboti mootoreid üles-alla sõidul
void Liikumine(bool Yles, int KiirusSeinal){
	//Järgnev if lause peatab ühe või teise mootori kui robot on balansist väljas
	//Siin if-i lauses korrgeerib balanssi robot siis kui ta näeb oranþi
	if (Sensor(S2) > 50){
		//Need kaks järgmist rida suunavad kumb mootor peatub 
		//siis kui läheb üles-alla ja näeb oranþi
		if (Yles) Off(OUT_B);
		else Off(OUT_C);
		until(Sensor(S2) < 50);
		}
	//Siin else if-i lauses korrigeerib balanssi robot siis kui ta näeb musta
	else if(Sensor(S2) < 40){
		//Need kaks järgmist rida suunavad kumb mootor peatub 
		//siis kui läheb üles-alla ja näeb musta
		if (Yles) Off(OUT_C);
		else Off(OUT_B);
		until(Sensor(S2) > 40);
		}
	else{
		//Muidu sõidab robot lihtsalt kahe seina vahelt alla
		OnRevReg(OUT_BC, KiirusSeinal, OUT_REGMODE_SPEED);
		OnRev(OUT_A, 20);
		}
}
task main(){
SetSensorLowspeed(S4);
SetSensorLight(S2);
SetSensorLowspeed(S3);
bool TOP;
//Järgnev mootori programmi osa laiendab mõlemad mootorid seinte vastu
OnFwd(OUT_A, -75);
Wait(1000);
while (TRUE){
	//Siin vaatab kas lagi on lähedamal kui 10 cm
	if(SensorUS(S4) < 10){
		Off(OUT_BC);
		TOP = TRUE;
		}
	//Siin vaatab kas põrand on lähedamal kui 10 cm
	if(SensorUS(S3) < 10){
		Off(OUT_BC);
		TOP = FALSE;
		}
	//See pool paneb roboti alla sõitma
	if(TOP){
		Liikumine(FALSE, -15);
	}
	//See pool paneb roboti üles sõitma
	else{
		Liikumine(TRUE, 30);
	}
}
}

6. tund: Andurite info kuvamine NXT ekraanil

Selle tunni käigus õpitakse kuvama andurite infot ekraanil. See on vajalik et aru saada mis infot andurid parasjagu väljastavad.

Õppematerjal:

Ülesanne.

Kuva ühendatud anduri info ekraanil. Vaja läheb NXT-d ning erinevaid andureid.


Variant a)

UltraSonic kauguseandur

Lahendus: Iseenesest väga lihtne programm, vaid ühe while() tsükliga.

/*
See programm kuvab ekraanile sõna Ultrasensor 
ja selle alla kui kaugel on ees olev asi.
*/

task main () {

SetSensorLowspeed (S2);

while (TRUE) {
   ClearScreen();
   TextOut(1, LCD_LINE1, "Ultrasonic");
   NumOut(1, LCD_LINE2, SensorUS (S2));
   Wait(200);
   }
}

Variant b)

Light sensor andur

/*
See programm kuvab ekraanile sõna LightSensor 
ja selle alla kui hele on ees olev asi.
*/
task main () {

SetSensorLight (S2);

while (TRUE) {
   ClearScreen();
   TextOut(1, LCD_LINE1, "LightSensor");
   NumOut(1, LCD_LINE2, Sensor(S2));
   Wait(200);
   }
}

Variant c)

Color sensor

Lahendus. Selle anduri juures annab numbri kuvamine liiga vähe olulist informatsiooni, seega palusin lahendada ülesande sellisel moel, et vastavalt värvile kuvataks ekraanil värvi nimetus. Ja need värvid mille nimetus pole kirjutatud, nende korral kuvatakse number. NB! Edaspidi õpime massiive ning saab sama programmi uuesti teha massiivi abil. Ehk tunduvalt lühema ja lihtsama.

/*
See programm kuvab ekraanile sõna ColorSensor 
ja selle alla värvi nimetuse
*/
task main () {

SetSensorLowspeed (S2);

while (TRUE) {
   ClearScreen();
   TextOut(1, LCD_LINE1, "ColorSensor");
   switch(SensorHTColorNum(S2))
   {
     case 0:
            TextOut (1, LCD_LINE2, "Must");
            break;
     case 6:
            TextOut (1, LCD_LINE2, "Kollane");
            break;     
     case 8:
            TextOut (1, LCD_LINE2, "Punane");
            break;     
		 case 14:
            TextOut (1, LCD_LINE2, "Beez");
            break;
     case 17:
            TextOut (1, LCD_LINE2, "Valge");
            break;

     default:
            NumOut(1, LCD_LINE2, SensorHTColorNum(S2));
      }
      Wait (200);
   }
}

Bricx Command Center häälestamine

BricxCC on NXT programmeerimise vahend, mille abil meie oma põhilise osa koodist kirjutamine.

Tegemist on tasuta tarkvaraga, mille saab alla laadida siit: http://bricxcc.sourceforge.net/

Järgnevalt leidsin hulga asju mida annab selles keskkonnas vaikimisi häälestuse suhtes oluliselt kasutajasõbralikumaks muuta.

Alljärgnevate ekraanipiltide järgi häälestades saad enda BricxCC keskkonna mugavamaks.

Edit – Preferences – Editor vaheleht

Bricx Preferences Editor seaded

Paremal pool ülalt alla:

Automatically indent lines (ON) – kui kirjutad koodirida mis algas mitte rea algusest vaid eendiga, siis enteriga järgmisele reale minnes satud täpselt samale tasemele eelneva reaga. Väga kasutajasõbralik ning normaalne käitumine.

Alt sets column selection (OFF) – Selle sisselülitamisel saab Alt klahvi all vajutades teha hiirega selectioni üle mitme rea nii et veeru osa jääb paigale. Üsna segane ja mõttetu asi.

Move cursor on right click (ON) – kui teed koodis mõnes kohas hiirega paremklõpsu siis viiakse automaatselt ka hiirekursor sellesse kohta. Põhimõtteliselt on see normaalne asjade toimimise viis arvutis.

Scroll Past EOL (OFF) – sisselülitamisel liigub kursor lõputult paremale kui vajutad noole paremale. Täiesti mõttetu funktsionaalsus – lülitasin välja. Välja lülitaud asendis viib nool paremale kursori rea lõppu jõudes järgmise rea algusesse. See on normaalne ja ootuspärane käitumine.

HalfPage Scroll (OFF) – Kui see on sisse lülitatud siis PgUp või PgDn nuppe vajutades liigub ekraan üles-alla ainult poole kaupa. Ebamugav funktsionaalsus, lülitasin välja, mulle meeldib et kogu leht liigub korraga üles-alla.

Drag and drop editing (ON) – see on ju elementaarne, et saan koodijupi hiirega kinni võtta ja teise kohta lohistada, muidugi lülita sisse.

Quick tab (OFF) – jälle üks mõttetu asi, lülita välja. Sisselülitamise korral liigub kursor TAB klahvi vajutades eelmise rea esimese tühikuni jne. Täiesti ebakasutajasõbralik funktsioon.

Keep trailing blanks (ON) – vajalik sisse lülitada, et TAB klahv korralikult töötaks.

Enhanced home key (ON) – sisselülitamise korral viiakse kursor Home nupule vajutuse korral esimese täheni antud real. Lülitasin välja, kuna ma olen harjunud et kursor viiakse konkreetselt rea algusesse kui vajutan „home“ nuppu.

With grouped undo (OFF) – ei saanudki aru mis undo’d see grupeerib. Lülitasin välja et ei hakkaks mingit segadust kogemata tekitama.

Use Tab to indent (ON) –See on väga oluline asi sisse lülitada. Selle abil saad tervet koodi blokki korraga paremale nihutada või siis Shift-Tab abil vasakule nihutada. Väga vajalik asi sisse lülitada.

Show special characters (OFF) – kuvad koodikirjutamise aknas ka reavahetuse, tühiku jms sümbolid. Pole kunagi vaja läinud.

Convert tabs to spaces (OFF) – pole vaja sisse lülitada. Las tabid jäävad tabideks ja mitte ei muutu tühikuks.

Highlight current line (ON/OFF) – mul on see sisse lülitatud, kuna poistele suurelt ekraanilt näidates on sedasi parem koodirea peal fookust hoida – sellisel juhul tuleb ka Color vahelehelt määrata mis on Highlight rea värvus, mina valisin kollase. Kui kirjutan lihtsalt koodi, siis selleks ajaks võtan välja.

Keep caret x position (ON) – sisselülitamisel hoiab kursor oma positsiooni kui üles alla liikuda. Hea mugav asi, kogu aeg vaja.

Autosize max left character (OFF) – mingi veidi mõttetu asi taas.

Edit – Preferences – General vaheleht

image

Multiformat clipboard copy (ON) – Kopeerib koodi vaikimisi RTF-vormingusse.

Maximize editor Windows (ON) – Käivitamisel ja uute loomisel on aknad kohe full screen.

Use MDI mode (OFF) – võta linnuke ära, siis on programmid TAB-dena

Edit – Preferences – Options vaheleht

image

Lülita sisse ridade nummerdamine. Line numbers.

Edit – Preferences – StartUp vaheleht

image

Määra, et vaikimisi Brick-type oleks NXT.

Juhend: Do–While ja For tsüklid

Alljärgnevalt veel kaks eriliste omadustega tsüklit, mille abil saab panna programmi täitma mingit protseduuri teatud arv kordi.

 

do { “body” } while ("tingimus")

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

 

Erinevus tavalisest while-tsüklist seisneb selles, et tsükkel täidetakse alati vähemalt ühe korra ja alles seejärel kontrollitakse tingimuse vastavust. Kui on tõene, täidetakse tsükkel teist korda.

Seega, kõigepealt läheb tsükkel käima, täida enda sees olevad käsud ja siis jõuab viimase reani while (..), mille sees on tingimus. Kui see tingimus on tõene minnakse do-tsükli algusesse tagasi ja täidetakse uuesti kõik käsud. Kui aga while (..) tingimus on muutunud vahepeal FALSE-ks, väljutakse tsüklist ja minnakse ülejäänud programmiga edasi.


for("init", “condition”, “increment”) { “body” }

for (int i = 0; i < 8; i++)
 {
    NumOut(0, LCD_LINE1-i*8, i);
 }


Init-ga algväärtustatakse muutuja i, tsükkel täidetakse kuni tingimus on tõene ja iga tsükli alguses täidetakse increment, mis liidab muutujale i juurde ühe numbri.

Seega, For-tsükli eripära seisneb selles, et sellele on sisse ehitatud loendur, mida saab kohe for-tsükli parameetrites häälestada. Pole tarvis ise tsükli sisse kirjutada liitmistehet ja suurem/väiksem kontrolli.

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; } } }