Inleiding - betapartners.nl  · Web viewStel dat we het bovenstaande programma willen wijzigen,...

57
Het Programmeren van Lego Robots met NXC Leerlingenboek 2018 - 2019

Transcript of Inleiding - betapartners.nl  · Web viewStel dat we het bovenstaande programma willen wijzigen,...

Het Programmeren van Lego Robots met NXC

Leerlingenboek 2018 - 2019

School : Cartesius LyceumVak : InformaticaDocent : Ron Klaver

Inhoudsopgave

Inleiding....................................................................................4Robots................................................................................................................4De programmeertaal NXC..................................................................................4Het Bricx commando centrum............................................................................4Het starten van het Bricx commando centrum..................................................4

Hoofdstuk 1...............................................................................6Het schrijven van een eerste programma..........................................................7Veranderen van de snelheid..............................................................................8Samenvatting.....................................................................................................8Opdrachten bij hoofdstuk 1................................................................................9

Hoofdstuk 2.............................................................................10Een interessanter programma..........................................................................10Draaien............................................................................................................10Herhalingscommando’s....................................................................................11Commentaar toevoegen...................................................................................12Variabelen en Constanten:...............................................................................13Motoren laten draaien in graden:.....................................................................13Samenvatting...................................................................................................13Opdrachten bij hoofdstuk 2..............................................................................14

Hoofdstuk 3.............................................................................15Variabelen gebruiken.......................................................................................15Een soort spiraal maken...................................................................................15Random (= toevals-) getallen..........................................................................16Samenvatting...................................................................................................17Opdrachten bij hoofdstuk 3..............................................................................18

Hoofdstuk 4.............................................................................19Controlestructuren...........................................................................................19De if-opdracht..................................................................................................19De do-opdracht................................................................................................20Samenvatting...................................................................................................21Opdrachten bij hoofdstuk 4..............................................................................21

Hoofdstuk 5.............................................................................22Sensoren..........................................................................................................22Wachten op een sensor....................................................................................22Werken met een druksensor............................................................................23Lichtsensoren...................................................................................................23Geluidssensor...................................................................................................24Ultrasone sensor..............................................................................................25Samenvatting...................................................................................................26Opdrachten bij hoofdstuk 5..............................................................................26

CARTESIUS LYCEUM Pagina 2 van 44 mei ’23

Hoofdstuk 6.............................................................................27Taken en deeltaken..........................................................................................27Samenvatting...................................................................................................28Opdrachten bij hoofdstuk 6 (8 pt)....................................................................29

Hoofdstuk 7.............................................................................29Parallelle taken.................................................................................................29Een programma met fouten.............................................................................29Het stoppen en weer starten van taken...........................................................30Het gebruik van semaforen (signalen).............................................................31Samenvatting...................................................................................................33Opdrachten bij hoofdstuk 7 (9 pt)....................................................................34

Bijlage A..................................................................................35Het bouwen van een Lego Mindstorms robot...................................................35Het aansluiten van sensoren op de NXT...........................................................35Het verzenden van programma’s van de computer naar de robot...................36Het compileren van een programma................................................................36

CARTESIUS LYCEUM Pagina 3 van 44 mei ’23

Inleiding

RobotsRobots spreken sterk tot de verbeelding van mensen. Men denkt daarbij vaak aan science fiction films: enigszins mensachtige apparaten die regelmatig op hol slaan. De werkelijkheid is minder spectaculair. Robots worden al vele jaren in de industrie gebruikt. Ze lijken echter in de verste verte niet op mensen. In de auto-industrie doen bijv. robotarmen een aanzienlijk deel van het werk. In sommige ziekenhuizen rijden robots die medicijnen rondbrengen.Sinds enige tijd worden ook robots gemaakt als speelgoed. Eén ervan is de Lego Mindstorms Robotic Invention System. In de VS is dit ‘speelgoed’ al een groot succes geworden. Met Mindstorms kun je robots maken die een bepaald gedrag hebben. Ze kunnen rondrijden, obstakels vermijden, objecten oppakken en ergens anders weer neerzetten en, als er meerdere robots zijn, met elkaar communiceren.

De programmeertaal NXC

Om een robot een bepaalde taak te laten uitvoeren, moet deze geprogrammeerd worden. De programmeertaal die hoort bij de Lego Mindstorms Robotics Invention System ziet er aantrekkelijk uit, maar is helaas nogal beperkt in zijn mogelijkheden. Gelukkig bestaat er een alternatieve programmeeromgeving in de taal NXC die speciaal geschreven is voor het programmeren van Lego robots. Deze letters staan voor “Not Exactly C”. Zoals de naam al suggereert (niet precies C) is NXC afgeleid van de (hogere programmeer-)taal C.

Het Bricx commando centrum

De programmeerbare Legosteen NXT vormt de kern van het Mindstorms RIS. Om het programmeren van de robots nog makkelijker te maken, maken we gebruik van het “Bricx Command Center”. Dit is een bijzonder handig en nuttig hulpmiddel bij het schrijven van NXC programma’s; ook wordt het gebruikt voor het verzenden van programma’s naar de robot en voor het starten en stoppen van de robot. Het Bricx Command Center is te downloaden van: http://bricxcc.sourceforge.net/, als je er thuis mee zou willen werken, maar het programma werkt op school gewoon in het netwerk.

Het starten van het Bricx commando centrum

CARTESIUS LYCEUM Pagina 4 van 44 mei ’23

Bij het starten van het BCC verschijnt eerst een scherm dat controleert of de robot op de computer is aangesloten. Aangezien we voorlopig eerst programma’s gaan maken zonder daarbij de robot te gebruiken, kun je deze schermpjes negeren door op Cancel (of: Annuleren) of OK te klikken.

Het volgende dat je te zien krijgt is het onderstaande BCC-scherm. Het ziet eruit als een gewone tekstverwerker met de gebruikelijke menu’s en knoppen. Er zijn ook speciale menu’s voor het compileren en verzenden van programma’s naar de robot. Compileren is het omzetten van de hogere taal NXC naar machinetaal die de robot (de NXT-steen) “begrijpt”.

CARTESIUS LYCEUM Pagina 5 van 44 mei ’23

CARTESIUS LYCEUM Pagina 6 van 44 mei ’23

Als je later besluit met de NXT-robot te gaan werken en je programma’s naar de NXT wil verzenden, kun je via <Tools> <find NXT> het Bricx Command Center contact laten maken met de robot.

Als dat is gebeurd, zijn er meer knoppen en menukeuzes beschikbaar, zoals in het onderstaande scherm is te zien.

CARTESIUS LYCEUM Pagina 7 van 44 mei ’23

Hoofdstuk 1Het

schrijven van een eerste programma

Bij het schrijven van de programma’s voor de robot gaan we uit van het model zoals dat is afgebeeld in bijlage A. We beginnen met een eenvoudig programma. Let op: elk programma moet altijd beginnen met #include "NXCDefs.h" anders gaat het niet werken. Het onderstaande programma start de robot; laat hem gedurende 4 seconden vooruit rijden en daarna 4 seconden achteruit; vervolgens stopt de robot weer:

#include "NXCDefs.h"

task main(){  OnFwd(OUT_B,75);  OnFwd(OUT_C,75);  Wait(4000);  OnRev(OUT_BC,75);  Wait(4000);  Off(OUT_BC);}

Het ziet er wellicht ingewikkeld uit, dus laten we het eens bekijken. Programma’s in NXC bestaan uit taken (tasks). Ons programma heeft slechts 1 taak, genaamd ‘main’. Ieder programma moet een taak ‘main’ hebben, want die wordt uitgevoerd door de robot. Dit komt in hoofdstuk 4 nog eens terug. Een taak (task) bestaat uit een aantal commando’s, oftewel ‘opdrachten’ (‘statements’). Om deze statements heen staan accolades { }, om aan te geven dat ze allemaal bij dezelfde task horen. Elk statement eindigt met een punt-komma (;). Dan is duidelijk waar het ene statement eindigt en het volgende begint. Een task ziet er dus in het algemeen als volgt uit:

CARTESIUS LYCEUM Pagina 8 van 44 mei ’23

task main(){ statement1; statement2; statement3; …}

Ons programma heeft 6 statements. We bekijken ze één voor één:

OnFwd(OUT_B,75);Dit statement vertelt de robot output B te starten, dat wil zeggen, de motor die via output B is aangesloten op de NXT. Hij rijdt niet op de maximale snelheid (deze is in te stellen van 1 tot en met 100, maar dat komt later ook nog).

OnFwd(OUT_C,75);Hetzelfde statement, maar nu voor het starten van motor C. Na deze 2 statements draaien beide motoren en rijdt de robot naar voren.

CARTESIUS LYCEUM Pagina 9 van 44 mei ’23

Wait(4000);Nu komt het wachten. Dit statement laat het programma 4 seconden wachten. Het argument (ook wel parameter of variabele genoemd) is het getal tussen haakjes en geeft het aantal ”tikken” weer. Elke tik duurt 1 duizendste seconde. Je kunt dus zeer nauwkeurig aangeven hoe lang het programma moet wachten voordat het volgende statement uitgevoerd wordt. Het programma doet dus 4 seconden lang niets, terwijl de robot met beide motoren vooruit rijdt.Een argument (of parameter/variabele) is dus een middel om informatie aan een statement door te geven.

OnRev(OUT_BC,75);De robot is nu ver genoeg doorgereden en we vertellen hem om in tegengestelde richting, dus achteruit, verder te gaan.

Wait(4000);Wederom doet het programma “niets” gedurende 4 seconden.

Off(OUT_BC);Tenslotte schakelen we beide motoren uit. Let er op dat beide motoren in 1 statement kunnen worden gestopt, dat was bij het starten hierboven ook al mogelijk geweest.

Als je het programma in de NXT-editor (Bricxcc) intypt, zul je ontdekken dat bepaalde gedeelten van de tekst gekleurd worden. Dit gebeurt automatisch. Alles in blauw is een commando voor de robot, of een indicatie van een motor of iets anders waar de robot mee bekend is. Het woord task is vetgedrukt omdat het een belangrijk (gereserveerd) woord is in NXC. Andere belangrijke woorden verschijnen eveneens vetgedrukt (zien we later nog). De kleuren zijn ook nog handig om fouten te ontdekken in je typewerk.

Veranderen van de snelheidDe snelheid kan aangepast worden door een komma gevolgd door een getal te typen achter het commando waarmee de motor wordt aangezet. De kracht is een nummer tussen 1 (langzaamst) en 100 (snelst). Hier is een nieuwe versie van ons programma waarin de robot langzamer beweegt:

#include "NXCDefs.h"

task main(){  OnFwd(OUT_B,15);  OnFwd(OUT_C,15);  Wait(4000);  OnRev(OUT_BC,15);  Wait(4000);  Off(OUT_BC);}

SamenvattingWat betreft programmeren hebben we een aantal belangrijke aspecten van de taal NXC geleerd. Ten eerste, dat elk programma een task heeft die main heet en die altijd uitgevoerd wordt door de robot. Ook hebben we de vier

CARTESIUS LYCEUM Pagina 10 van 44 mei ’23

belangrijkste statements gezien: OnFwd(), OnRev(), en Off(). Tenslotte hebben we iets over het Wait()-statement geleerd.

CARTESIUS LYCEUM Pagina 11 van 44 mei ’23

Opdrachten bij hoofdstuk 1

Opdracht 1:

Open een nieuw bestand en type de volgende code:

#include "NXCDefs.h"

task main(){  OnFwd(OUT_D,75);  OnFwd(OUT_C,75);  Wait(4000);  OnRev(OUT_BC,75);  Wait(4000);  Of(OUT_BC);}

In deze code zitten twee fouten. Misschien heb je ze bij het typen al ontdekt. De NXC-compiler zal deze fouten ook ontdekken en zelf de foutieve regel selecteren. Onder aan het scherm zie je niet alleen in welke regel de fout zit, maar ook de aard van de fout. Trek je er maar niets van aan als je de foutmelding niet begrijpt. Voorlopig gaat het erom dat je leert dat de NXC-compiler fouten in een programma kan opsporen.Om de compiler de fouten te laten ontdekken, gaan we het bovenstaande programma compileren. Klik op ‘Compile’ in de menubalk of druk op functietoets F5.

1a:Welke foutmelding geeft de compiler precies als je het programma wil uitvoeren?

1b:Beschrijf in je eigen woorden waarom de compiler deze fout niet accepteert.De compiler gaat pas verder als de fout hersteld is. Doe dit eerst en drukdaarna weer op F5.

1c:Wat is de volgende foutmelding? Herstel ook deze fout voordat je aan opdracht 2 begint.

Opdracht 2:

2a: Beschrijf wat er gebeurt als in het (gecorrigeerde) programma van opdracht 1 de opdracht Wait(4000); in regel 7 weggelaten wordt. Test daarna je “theorie” door dit programma door de robot te laten uitvoeren. In bijlage A staat hoe je een programma van de computer naar de NXT-steen kunt verzenden. Vraag hulp aan je docent als het niet lukt.

2b:

CARTESIUS LYCEUM Pagina 12 van 44 mei ’23

Kun je nu voorspellen wat er gebeurt als je beide Wait()-statements uit het bovenstaande programma weglaat?

Hoofdstuk 2Een interessanter programmaWe gaan nu stapsgewijs een interessanter programma maken, waarbij een aantal belangrijke onderdelen van de programmeertaal NXC naar voren komt.

DraaienJe kunt de robot laten draaien door een van de twee motoren te laten stoppen of in tegengestelde richting te laten draaien. Het onderstaande programma moet de robot een stukje laten rijden en dan een bocht van 90° laten maken.

#include "NXCDefs.h"

task main(){  OnFwd(OUT_AC,75);  Wait(1000);  OnFwd(OUT_C,50);  Wait(450);  Off(OUT_AC);}

Misschien moet je een iets ander getal dan de 450 bij het tweede Wait()-commando invullen om een bocht van precies 90° te maken. Dat hangt af van het type oppervlak waarover de robot rijdt en de snelheid van de motor. Slimmer dan dit in het programma steeds te moeten veranderen is om een naam voor dit aantal te gebruiken. Dat heet dan een CONSTANTE. Het is gebruikelijk in veel programmeertalen om constanten met hoofdletters te schrijven. In NXC kun je constanten (dat zijn dus constante waarden) definiëren zoals in het volgende voorbeeldprogramma:

#include "NXCDefs.h"

#define MOVE_TIME 1000#define TURN_TIME 450

task main(){ OnFwd(OUT_AC,75); Wait(MOVE_TIME); OnRev(OUT_C,50); Wait(TURN_TIME); Off(OUT_AC);}

De eerste 2 regels, na #include "NXCDefs.h",definiëren twee ‘constanten’. Deze kunnen nu het hele programma door gebruikt worden. Let op: tussen # en define mag geen spatie staan en de regel wordt niet afgesloten met een ;

CARTESIUS LYCEUM Pagina 13 van 44 mei ’23

Herhalingscommando’sLaten we nu proberen een programma te schrijven waarbij de robot een vierkant maakt. Een vierkant maken betekent: naar voren rijden, 90°draaien, weer vooruit rijden, 90° draaien, enz. We kunnen het stuk code van hiervoor vier maal gebruiken, maar het kan eenvoudiger met een herhalingscommando: repeat

#include "NXCDefs.h"

#define MOVE_TIME 1000#define TURN_TIME 450

task main(){ repeat(4) { OnFwd(OUT_AC,75); Wait(MOVE_TIME); OnRev(OUT_C,50); Wait(TURN_TIME); } Off(OUT_AC);}

Het getal achter repeat tussen haakjes geeft aan hoe vaak iets moet worden herhaald. De commando’s die herhaald moeten worden staan, net als de commando’s in een task, altijd tussen haakjes. Let er ook op dat we in het bovenstaande programma steeds inspringen. Dit is niet verplicht, maar het staat veel netter en het maakt het programma beter leesbaar.

Als laatste voorbeeld laten we de robot 10 keer een vierkant rijden. Hier is het programma:

#include "NXCDefs.h"

#define MOVE_TIME 1000#define TURN_TIME 450

task main(){ repeat(10) { repeat(4) { OnFwd(OUT_AC,75); Wait(MOVE_TIME); OnRev(OUT_C,50); Wait(TURN_TIME); } } Off(OUT_AC);}

CARTESIUS LYCEUM Pagina 14 van 44 mei ’23

Nu staat het ene herhalingscommando in het andere. Dit heet een ‘genest’ herhalingscommando. Je kunt herhalingscommando’s zoveel als je wilt ‘nesten’. Let goed op de accolades en het inspringen in het programma. De task start bij de eerste accolade en eindigt bij de laatste. Het eerste herhalingscommando start bij de tweede accolade en eindigt bij de vijfde. Het tweede, geneste, herhalingscommando begint bij de derde accolade en eindigt bij de vierde. De accolades staan dus altijd in paren in het programma en het stuk ertussen springt in.

Commentaar toevoegenOm het programma begrijpelijker te maken, is het verstandig om af en toe commentaar toe te voegen. Als je // op een regel zet, wordt de rest van die regel door het programma genegeerd en kan hij gebruikt worden voor commentaar. Een langer commentaar kan tussen /* en */ gezet worden. Commentaar wordt cursief en zwart weergegeven in het Brixcc. Het volledige programma zou er als volgt uit kunnen zien:

#include "NXCDefs.h"

/*10 VIERKANTENdoor Leo EerlingDit programma laat de robot 10 vierkanten rijden*/

#define MOVE_TIME 1000 //Tijd voor vooruit gaan#define TURN_TIME 450 //Tijd voor 90° draaien

task main(){ repeat(10) //Maak 10 vierkanten { repeat(4) // doe dit 4 keer { OnFwd(OUT_AC,50); Wait(MOVE_TIME); OnRev(OUT_C,80); Wait(TURN_TIME); } } Off(OUT_AC);}

CARTESIUS LYCEUM Pagina 15 van 44 mei ’23

Variabelen en Constanten:In computerprogramma’s wordt heel vaak gebruik gemaakt van variabelen. Een variabele is feitelijk een plaats in het (werk)geheugen van een computer om een bepaalde waarde in op te bergen. In ons geval dus in het geheugen van de NXT.

Een voorbeeld van een variabele is het getal achter het commando Wait (). Door de waarde te wijzigen wordt de tijd die het programma wacht langer of korter; daardoor wordt de afstand die de robot aflegt langer of korter of de hoek die een robot maakt bij het draaien groter of kleiner.Als een variabele met dezelfde waarde vaak voorkomt in een programma is het handiger om een constante te gebruiken. De waarde van een constante kan niet veranderd worden; vandaar de naam. In hoofdstuk 3 leer je meer over het gebruik van variabelen.

Motoren laten draaien in graden:Je kunt de motoren ook in een aantal graden laten draaien. Dat gaat als volgt:RotateMotor(‘poort’, ‘snelheid’, graden’), dus in een programma zou dat er als volgt uit kunnen zien:

#include "NXCDefs.h"

task main(){

RotateMotor(OUT_AC, 50, 360);// of als je de robot achteruit wil laten rijden:RotateMotor(OUT_AC, 50, -360);

}

Je kunt met RotateMotor echter niet tegelijkertijd de ene motor naar voren en de andere motor naar achteren laten draaien.

SamenvattingIn dit hoofdstuk leerden we het repeat-commando en het gebruik van commentaar. Ook zag je de functie van geneste accolades en van het inspringen. Bovendien weet je nu hoe je de motoren in graden precies kunt laten draaien, maar hoe ver dat is, is natuurlijk afhankelijk van de omtrek van de wielen, c.q. de banden.

Met de kennis die je nu hebt, kun je de robot in allerlei richtingen laten bewegen.

CARTESIUS LYCEUM Pagina 16 van 44 mei ’23

Opdrachten bij hoofdstuk 2

Opdracht 1:Wat is er mis met het onderstaande programma?Beantwoordt deze vraag eerst zonder gebruik te maken van de compiler.Aanwijzing: er zitten vier fouten in.

#include "NXCDefs.h"

# MOVE_TIME 1000;

task main(){ repeat(10) { repeat(4) { OnFwd(OUT_AC,60); Wait(MOVE_TIME); OnRev(OUT_C,40); } Off(OUT_AC);}

Opdracht 2:Schrijf een programma dat de NXT robot een halve meter vooruit laat rijden; dan 180° om zijn as laat draaien en daarna weer terug gaat naar het vertrekpunt.

Opdracht 3:Schrijf in gewoon Nederlands een programma dat de robot drie vierkantjes van ca. 50 centimeter laat afleggen. Aanwijzing: er komt een geneste herhaling in voor. Maak een schatting voor de tijd die nodig is om de gevraagde afstand af te leggen. De details komen in opdracht 4 aan de orde.

Opdracht 4:Schrijf nu het programma aan de hand van het Nederlandse programma van opdracht 3. In dit programma moet je gebruik maken van constanten. Als het programma klaar is moet je het testen met de robot. Je zult ongetwijfeld wat moeten experimenteren met de waarden van de constanten om de robot de voorgeschreven afstand te laten afleggen.

Opdracht 5:Schrijf een programma dat de robot in een cirkel van plusminus een meter doorsnee laat rijden. Een meter is ongeveer van je vingertoppen van je linkerhand tot aan je schouder van je rechterarm.

CARTESIUS LYCEUM Pagina 17 van 44 mei ’23

Hoofdstuk 3

Variabelen gebruikenVariabelen zijn in elke programmeertaal zeer belangrijk. Variabelen zijn geheugenplaatsen waarin we een waarde kunnen opslaan. We kunnen die waarde op verschillende plaatsen in een programma gebruiken en we kunnen de waarde veranderen. We gaan het bekijken aan de hand van een voorbeeld.

Een soort spiraal maken.Stel dat we het bovenstaande programma willen wijzigen, zodanig dat de robot een soort van spiraal gaat maken. Dit kan, door de ‘wachttijd’ bij iedere beweging recht vooruit iets langer te maken. D.w.z. dat we de waarde van ‘move_time’ elke keer willen verhogen. Maar hoe kunnen we dit doen? Move_time is een constante en constanten kunnen we niet wijzigen. We hebben daarom een variabele nodig. Variabelen kunnen in NXC eenvoudig worden gedefinieerd. Je kunt er 32 van hebben en ze kunnen elk een andere naam krijgen. Hieronder staat het programma van een soort spiraal:

#include "NXCDefs.h"

#define TURN_TIME 200 //definieer een constante

int move_time; //definieer een variabele

task main(){ move_time = 200; //geef de beginwaarde repeat(20) { OnFwd(OUT_BC,60); Wait(move_time); //gebruik van de variabele OnRev(OUT_C,60); Wait(TURN_TIME); //gebruik van de constante move_time += 200; //verhoog de variabele } Off(OUT_BC);}

De belangrijke zaken staan in het commentaar. Eerst definiëren we een variabele via het keyword int, gevolgd door een naam die we kiezen. De naam moet met een letter beginnen, maar kan daarna ook cijfers bevatten en het onderstreepteken (_). Andere symbolen zijn niet toegestaan. ditzelfde geldt voor constanten, task-namen, enz.De afkorting int staat voor integer; dit zijn gehele getallen zonder komma. Alleen deze getallen mogen hier staan.

CARTESIUS LYCEUM Pagina 18 van 44 mei ’23

In de tweede commentaarregel geven we de variabele de waarde 20. Nu volgt de herhalingslus waarin we de variabele gebruiken om de wachttijd aan te geven, en aan het einde van de lus verhogen we de waarde met 5. Zo wacht de robot eerst 20 tikken, de tweede keer 25, de derde keer 30, enz.

Bij een variabele kun je naast optellen, zoals hierboven, ook vermenigvuldigen (met *=), aftrekken (met -=) en delen (met /=). (N.B. bij delen wordt de uitkomst afgerond op de dichtstbijliggende integer) Je kunt ook de ene variabele bij de andere optellen, en meer gecompliceerde expressies gebruiken. Hieronder een paar voorbeelden:

int aaa, bbb, ccc;

task main(){ aaa = 10; bbb = 20 * 5; ccc = bbb; ccc /= aaa; ccc -= 5; aaa = 10 * (ccc + 3); // aaa is nu gelijk aan waarde 80}

Let erop dat we op de eerste regel meerdere variabelen in één regel definiëren.

Random (= toevals-) getallenTot nu toe hebben we de robot precies verteld wat hij doen moest. Het kan interessant zijn als de robot dingen gaat doen die wij niet van tevoren kennen. We willen wat toeval (randomness) in de acties. In NXC kun je random getallen gebruiken. Het volgende programma gebruikt deze om de robot rond te laten rijden op een random-manier. Hij rijdt steeds een bepaalde random-tijd vooruit en maakt dan een random-draai.

CARTESIUS LYCEUM Pagina 19 van 44 mei ’23

#include "NXCDefs.h"

int move_time, turn_time;

task main(){ while(true) { move_time = Random(3000); turn_time = Random(1000); OnFwd(OUT_AC,50); Wait(move_time); OnRev(OUT_A,50); Wait(turn_time); }}

CARTESIUS LYCEUM Pagina 20 van 44 mei ’23

Het programma kent twee variabelen met random nummers. Random(3000); betekent een willekeurig getal tussen de 0 en de 3000 (dus 1 t/m 2999). Telkens zijn de getallen verschillend. Let erop dat we het gebruik van een variabele hadden kunnen vermijden door te schrijven Wait (Random(3000));

Je ziet hier ook een nieuwe soort lus. Dit komt door de while(true) herhalingsopdracht. De while-opdracht herhaalt de opdrachten eronder net zo lang als de uitdrukking tussen haakjes waar is. Het woord tussen haakjes (true) is altijd waar, en dus wordt het commando tussen haakjes eindeloos herhaald. En dat is juist wat we willen. Zeker bij het gebruik van sensoren. In hoofdstuk 4 komt de while-opdracht nog terug.

SamenvattingIn dit hoofdstuk hebben we het gebruik van variabelen geleerd. Variabelen zijn nuttig, maar ook, door de beperkingen van de robots, begrensd in hun gebruik. Je kunt er slechts 32 definiëren en ze kunnen alleen werken met integers. Maar voor veel robottaken is dit voldoende.

Ook leerde je nog om met random getallen te werken, zodat je de robot onvoorspelbaar gedrag kunt laten vertonen. Tenslotte zagen we het gebruik van de while-opdracht om een oneindige loop te maken.

CARTESIUS LYCEUM Pagina 21 van 44 mei ’23

Opdrachten bij hoofdstuk 3

Opdracht 1:Schrijf een programma dat de robot een bepaalde afstand rechtdoor laat rijden, bijv. 5 cm; laat hem vervolgens 2 seconden wachten en daarna weer verder rijden, maar nu het dubbele van de vorige afstand, dus 10 cm. Laat de robot dit vier keer doen, dus vier keer rijden afgewisseld met vier keer wachten.

Opdracht 2:Bestudeer het onderstaande programma. Teken vervolgens in je verslag in Word de weg die je denkt dat de robot volgens dit programma aflegt.

Het programma luidt als volgt:#include "NXCDefs.h"

#define RIJ_TIJD 1000#define DRAAI_TIJD 750

int snelheid;

task main(){ snelheid = 50; OnFwd(OUT_AC, snelheid); Wait(RIJ_TIJD); OnRev(OUT_A, snelheid); Wait(DRAAI_TIJD); repeat(2) { OnFwd(OUT_AC, snelheid); Wait(RIJ_TIJD); OnRev(OUT_C, snelheid); Wait(DRAAI_TIJD); } OnFwd(OUT_AC, snelheid); Wait(RIJ_TIJD); OnRev(OUT_A, snelheid); Wait(RIJ_TIJD); Off(OUT_AC);}

Opdracht 3:

Schrijf een programma dat de robot steeds sneller in een cirkel van ongeveer 50 cm. doorsnee laat rondrijden. De versnelling moet met behulp van een variabele geprogrammeerd worden.

Opdracht 4:

Schrijf een programma dat de robot vooruit laat rijden, waarbij er om en om een bocht naar rechts en een bocht naar links gemaakt wordt op willekeurige momenten.

CARTESIUS LYCEUM Pagina 22 van 44 mei ’23

Hoofdstuk 4

ControlestructurenIn het vorige hoofdstuk zagen we de repeat- en de while-opdracht. Deze opdrachten controleren de manier waarop andere opdrachten in het programma worden uitgevoerd. Zij heten “controlestructuren”. In dit hoofdstuk zien we er nog een aantal van.

De if-opdrachtSoms wil je dat een bepaald deel van je programma alleen wordt uitgevoerd in bepaalde situaties. In dat geval wordt de if-opdracht gebruikt. Een voorbeeld. We gebruiken weer het programma van hiervoor, maar met een nieuwe draai. We willen de robot in een rechte lijn laten rijden en dan een draai naar links óf naar rechts laten maken. Om dit te bereiken hebben we de opdracht weer Random nodig. We nemen Random(2). Dan is de uitkomst tussen de 0 en de 2, d.w.z. het is of 0 of 1. Als het getal 0 is draait de robot naar rechts; als het 1 is naar links. Hier is het programma:

#include "NXCDefs.h"

#define MOVE_TIME 1000#define TURN_TIME 450

task main(){ while(true) { OnFwd(OUT_AC,50); Wait(MOVE_TIME); if (Random(2) == 0) { OnRev(OUT_C,50); } else { OnRev(OUT_A,50); } Wait(TURN_TIME); }}

De if-opdracht lijkt wat op de while-opdracht. Als de voorwaarde tussen de haakjes waar is, dan wordt het deel tussen de accolades uitgevoerd. Zo niet, dan wordt het deel tussen de accolades achter het woord else uitgevoerd. Laten we wat beter kijken naar de gebruikte voorwaarde. Er staat Random(2) == 0. Dit betekent dat Random(2) gelijk moet zijn aan de waarde 0 om de

CARTESIUS LYCEUM Pagina 23 van 44 mei ’23

voorwaarde waar te laten zijn. Je vraagt je misschien af waarom er == gebruikt wordt en niet alleen =. De reden is om het te onderscheiden van een opdracht die een waarde aan een variabele geeft.

CARTESIUS LYCEUM Pagina 24 van 44 mei ’23

De belangrijkste van deze symbolen staan hieronder:

= = gelijk aan< kleiner dan<= kleiner dan of gelijk aan> groter dan>= groter dan of gelijk aan!= ongelijk aan

Je kunt ook samengestelde combinaties maken als &&, wat betekent ‘EN’, of ||, wat betekent ‘OF’.Hier zijn een paar voorbeelden van deze voorwaarden:

true altijd waar

false nooit waar

ttt != 3 waar als ttt niet gelijk is aan 3

(ttt >= 5) && (ttt <= 10) waar als ttt ligt tussen 5 en 10

(aaa = = 10) || (bbb = = 10) waar als óf aaa óf bbb (of beide) gelijk zijn aan de waarde 10

Let erop dat de if-opdracht uit twee delen bestaat. Het deel direct na de voorwaarde, dat uitgevoerd wordt als de voorwaarde waar is, en het deel, dat uitgevoerd wordt na else, als de voorwaarde níet waar is. Het sleutelwoord else en het deel erachter is facultatief. Je kunt het dus weglaten als er niets moet gebeuren als de voorwaarde onjuist is.

De do-opdrachtEen andere controlestructuur is de do-opdracht. De opdrachten tussen de accolades na do worden minimaal 1 keer uitgevoerd, zolang de voorwaarde waar is. De voorwaarde heeft dezelfde vorm als bij de if-opdracht hierboven besproken. Hier een voorbeeld van een programma. De robot rijdt 20 seconden random rond en stopt dan.

#include "NXCDefs.h"int move_time, turn_time, total_time;

task main()

CARTESIUS LYCEUM Pagina 25 van 44 mei ’23

{ total_time = 0; do { move_time = Random(1000); turn_time = Random(1000); OnFwd(OUT_AC,50); Wait(move_time); OnRev(OUT_C,50); Wait(turn_time); total_time += move_time;

total_time += turn_time; } while (total_time < 20000); Off(OUT_AC);}

CARTESIUS LYCEUM Pagina 26 van 44 mei ’23

Let er in dit voorbeeld op dat we 2 opdrachten op één regel hebben gezet. Dat mag. Je mag zo veel mogelijk opdrachten op een regel zetten als je wilt (zolang er maar punt-komma’s tussen staan). Maar voor de leesbaarheid van je programma is dat niet zo’n goed idee.

Let er verder op dat de do-opdracht zich bijna net zo gedraagt als de while-opdracht. Maar in de while-opdracht is de voorwaarde getest vóór uitvoering van de opdracht, terwijl in de do-opdracht de voorwaarde aan het eind wordt getest. Bij de while-opdracht wordt de opdracht wellicht nooit uitgevoerd, maar bij de do-opdracht minstens 1 keer.

SamenvattingWe hebben 2 nieuwe controlestructuren leren kennen: de if-opdracht en de do-opdracht. Samen met de repeat- en de while-opdracht controleren zij de manier waarop het programma wordt uitgevoerd.We zagen ook dat we meerdere opdrachten op één regel kunnen zetten.

Opdrachten bij hoofdstuk 4

Opdracht 1:Leg uit wat het gevolg is voor het programma wanneer je in de if-opdracht van het programma aan het begin van dit hoofdstuk == vervangt door !=

Opdracht 2:Idem wanneer je == vervangt door >=

Opdracht 3:Bij de hiervoor beschreven do-opdracht rijdt de robot maximaal 20 sec. schoksgewijs rond.Leg uit dat het berekenen van het maximum aantal keren dat de robot in deze 20 sec. vooruit rijdt niet mogelijk is.

Opdracht 4:Wijzig het programma dat je bij opdracht 1 van hoofdstuk 3 hebt gemaakt in een programma met een do-opdracht. Als de robot vijf keer vooruit heeft gereden moet deze in één keer achteruit terugrijden naar zijn beginpositie.

Opdracht 5:Wijzig het programma van opdracht 4 nu zo dat er een if-opdracht gebruikt wordt i.p.v. een do-opdracht.

CARTESIUS LYCEUM Pagina 27 van 44 mei ’23

Hoofdstuk 5SensorenEén van de aardige aspecten van de Lego NXT-robot is dat je er sensoren op kunt aansluiten en dat je de robot op de sensoren kunt laten reageren. Voor we dat kunnen zien, moeten we de robot iets veranderen door er een sensor op aan te sluiten. Bouw daartoe het model dat in de bij de doos geleverde handleiding staat. Zie ook bijlage 1.

Verbindt de aanraaksensor met input 1 op de NXT.

Wachten op een sensorLaten we beginnen met een eenvoudig programma waarin de robot vooruit rijdt tot hij ergens tegenaan botst. Hier zie je het:

#include "NXCDefs.h"

task main(){ SetSensorTouch(IN_1); OnFwd(OUT_AC, 70); until (SENSOR_1 == 1); Off(OUT_AC);}

Er staan 2 belangrijke regels in. De eerste regel van het programma vertelt de robot welk type sensor gebruikt wordt. IN_1 is het input-nummer waaraan de sensor gekoppeld is. De andere 3 sensor-inputs zijn IN_2, IN_3 en IN_4.

CARTESIUS LYCEUM Pagina 28 van 44 mei ’23

SetSensorTouch geeft aan dat het de aanraaksensor is. Voor de lichtsensor gebruiken we SetSensorLight. Nadat het type sensor gespecificeerd is, schakelt het programma beide motoren in en begint de robot vooruit te rijden. De volgende opdracht is een bijzonder bruikbare constructie. Er wordt gewacht tot de voorwaarde tussen haken waar is. Deze voorwaarde zegt dat de waarde van de sensor IN_1 gelijk moet zijn aan de waarde 1, wat betekent dat de sensor ingedrukt wordt. Zo lang de sensor niet wordt ingedrukt, is de waarde 0. Dus deze opdracht wacht tot de sensor wordt ingedrukt. Dan schakelen we de motor uit en is de taak beëindigd.

Werken met een druksensorWe gaan nu proberen de robot obstakels te laten ontwijken. Telkens als de robot een voorwerp aanraakt, laten we hem 2 seconden achteruitrijden, een draai maken van anderhalve seconde en dan weer verderrijden. Hier is het programma:

#include "NXCDefs.h"

task main(){ SetSensorTouch(IN_1); OnFwd(OUT_AC, 75); while (true) { if (SENSOR_1 == 1) { OnRev(OUT_AC, 75); Wait(2000); OnFwd(OUT_A, 75); Wait(1500); OnFwd(OUT_AC, 75); } }}

Net als in het vorige voorbeeld, geven we eerst het type sensor aan. Daarna begint de robot voorwaarts te bewegen. In de oneindige ‘while(true)’ loop testen we steeds of de sensor ingedrukt is en, als dat zo is, gaan we terug voor 2000 milliseconde, draaien en daarna weer vooruit.

De druksensor hoeft niet altijd helemaal ingedrukt te worden. Gebruik bijvoorbeeld:if (SENSOR_1 > 50) om aan te geven dat de druksensor maar 50% ingedrukt hoeft te worden.

LichtsensorenIn het MindStorms pakket zit naast een aanraaksensor ook een lichtsensor. De lichtsensor meet de hoeveelheid licht in een bepaalde richting. De lichtsensor straalt ook licht uit. Daardoor is het mogelijk de lichtsensor in een bepaalde richting te sturen en een onderscheid te maken in de intensiteit van het voorwerp in die richting. Dit is makkelijk als de robot een lijn op de grond moet volgen. Dat gaan we in het volgende voorbeeld doen. We moeten eerst de

CARTESIUS LYCEUM Pagina 29 van 44 mei ’23

lichtsensor zo op de robot aansluiten, dat hij in met midden vooraan zit en naar beneden wijst. Verbind hem met input 2.

We hebben ook een soort ‘racebaan’ nodig die helaas niet in het pakket zit (bijv. een groot stuk papier met een zwart spoor erop). De bedoeling is nu dat de robot er voor zorgt dat de lichtsensor steeds boven het spoor blijft. Telkens als de intensiteit van het licht toeneemt, is de lichtsensor van het spoor en moeten we de richting aanpassen. Hier een voorbeeld van een eenvoudig programma dat alleen werkt als we met de wijzers van de klok mee rondrijden.

#include "NXCDefs.h"

#define THRESHOLD 50

task main(){ SetSensorLight(IN_2); OnFwd(OUT_AC, 35); while (true) { if (Sensor(IN_2) > THRESHOLD) { OnRev(OUT_C, 35); Wait(100); until(Sensor(IN_2) <= THRESHOLD); OnFwd(OUT_AC, 35); } }}

Het programma geeft eerst aan dat sensor 2 een lichtsensor is. Daarna laat het de robot vooruit rijden en begint een oneindige ‘loop’. Telkens als de lichtwaarde groter is dan 50 (we gebruiken een constante zodat hij makkelijk kan worden aangepast, omdat het sterk van het omringende licht afhangt) stopt er 1 motor en wachten we tot we weer op het goede spoor zitten.

Om een beweging langs een willekeurig gekozen pad mogelijk te maken is een veel ingewikkelder programma nodig.

GeluidssensorIn de legodoos van MindStorms zitten ook een geluidssensor en een ultrasone sensor. De geluidssensor kan geluiden waarnemen en de ultrasone sensor kan afstanden meten tot een bepaald voorwerp. In het volgende programma staat een voorbeeld van hoe je de geluidssensor zou kunnen gebruiken. Dit programma laat de robot eerst stilstaan, totdat hij een geluid waarneemt. Dan rijdt de robot 1 seconde vooruit totdat een volgend geluid wordt gehoord. (De sensor is verbonden met input 3.)

CARTESIUS LYCEUM Pagina 30 van 44 mei ’23

#include "NXCDefs.h"

#define THRESHOLD 40#define MIC SENSOR_2

task main(){ SetSensorSound(IN_2); while(true) { until(MIC < THRESHOLD); OnFwd(OUT_AC, 75); Wait(1000); until(MIC > THRESHOLD); Off(OUT_AC); Wait(1000); }}

Eerst wordt een THRESHOLD constante gedefinieerd en wordt een bijnaam gegeven aan SENSOR_2. In de main task wordt gezegd dat poort 2 gegevens moet lezen van de geluidssensor en dan begint een oneindige loop. Door until te gebruiken, wacht het programma tot er een geluid van een niveau wordt waargenomen dat groter is dan de gekozen geluidsdrempel (threshold).Als de robot een luid geluid hoort, begint hij vooruit te rijden totdat hij wordt gestopt door een ander geluid.De wait opdrachten zijn noodzakelijk, omdat de robot anders zou beginnen te rijden en direct zou stoppen. De NXT is zo snel dat er geen tijd nodig is om regels tussen twee until opdrachten uit te voeren. Hetzelfde geluid waardoor de robot gaat rijden, zorgt er dus ook voor dat de robot stopt. Dit zou opgelost kunnen worden door while te gebruiken in plaats van until. while(MIC <= THRESHOLD)Verder is er niet veel meer wat je moet weten over de analoge sensors, behalve dat ze een bereik hebben van 0 tot 100.

Ultrasone sensorDe ultrasone sensor werkt ongeveer als een sonar. De sensor zendt ultrasone golven uit en meet de tijd die nodig is voor de golven om teruggekaatst te worden door het voorwerp. Dit is een digitale sensor, wat betekent dat het een “embedded integrated device” is om gegevens te analyseren en te verzenden. Met deze nieuwe sensor is het mogelijk om een robot obstakels te laten zien en ze te ontwijken vóórdat hij er tegenaan rijdt.

CARTESIUS LYCEUM Pagina 31 van 44 mei ’23

#include "NXCDefs.h"

#define NEAR 25 //het aantal cm van het bereik

task main(){ SetSensorLowspeed(IN_4);

while(true){

OnFwd(OUT_AC, 50);while(SensorUS(IN_4) > NEAR);Off(OUT_AC);OnRev(OUT_C, 40);Wait(800);

}}

In dit programma laat poort 4 de gegevens lezen die deze binnenkrijgt van de US sensor, maakt een oneindige loop waarin de robot vooruit rijdt, totdat hij dichterbij iets komt dan 25 cm, stopt dan, rijdt een stukje achteruit, maakt een bocht en begint weer vooruit te rijden.

SamenvattingIn dit hoofdstuk hebben we het gebruik van druk-, licht-, geluids- en ultrasone sensoren gezien. We zagen ook de until opdracht, die nuttig is bij sensorgebruik.

Schrijf nu zelf een aantal programma’s. Je hebt nu alle ingrediënten om de robot een ingewikkeld gedrag te laten vertonen. Zet bijvoorbeeld twee sensoren op je robot, één aan de rechter-, één een aan de linkervoorkant, en laat de robot wegrijden van obstakels die hij raakt. Probeer ook de robot binnen een gebied te houden aangegeven door een dikke zwarte ‘grens’ op de grond.

Opdrachten bij hoofdstuk 5

Opdracht 1:Je kunt een druksensor ook zo bevestigen dat hij steeds ingedrukt wordt totdat hij ergens tegen aankomt. Hoe moet je het eerste programmaatje van dit hoofdstuk dan wijzigen om de robot op dezelfde manier te laten reageren?

Opdracht 2:Leg precies uit wat de variabele THRESHOLD doet.

Opdracht 3:

CARTESIUS LYCEUM Pagina 32 van 44 mei ’23

Maak een druksensor aan de voorkant en maak ook een druksensor aan de voorkant. Schrijf nu een programma, dat er voor zorgt dat de robot tussen twee obstakels (muren bijv.) heen en weer blijft rijden.

CARTESIUS LYCEUM Pagina 33 van 44 mei ’23

Hoofdstuk 6Taken en deeltakenTot nu toe bevatten onze programma’s slechts één taak, de task main. Maar NXC-programma’s kunnen meer taken tegelijkertijd aan. Je programma’s worden compacter en eenvoudiger te begrijpen door het gebruik van taken en deeltaken. In dit hoofdstuk zullen we de verschillende mogelijkheden bekijken.

Een NXC-programma bestaat uit ten hoogste 255 taken. Elke taak heeft een naam. Eén taak wordt altijd ‘main’ genoemd en deze taak wordt uitgevoerd. De andere taken worden slechts uitgevoerd wanneer een (andere) deeltaak die op een bepaald moment wordt uitgevoerd vraagt om een startcommando. Vanaf dat moment worden beide taken gelijktijdig uitgevoerd. (De eerste taak blijft doorlopen). Een lopende taak kan er ook voor zorgen dat een deeltaak wordt gestopt door middel van een stop commando. De betreffende deeltaak kan naderhand weer herstarten, maar zal dan weer van af het begin uitgevoerd worden en niet op de plaats waar de deeltaak werd stopgezet.

We zullen het gebruik van taken en deeltaken demonstreren. Zet je druksensor maar weer op je robot. We gaan een programma maken waarin de robot in vierkanten gaat rijden. Als hij een obstakel raakt moet hij daarop reageren. Dit is moeilijk in één taak te realiseren, omdat de robot twee dingen tegelijkertijd moet doen: rondrijden; oftewel de motoren op het juiste moment aan en uit zetten én op de sensoren letten. Vandaar dat het beter is om hiervoor twee taken te maken: één taak voor het rijden en de andere taak voor het in de gaten houden van de sensoren. Hier volgt het programma:

CARTESIUS LYCEUM Pagina 34 van 44 mei ’23

#include "NXCDefs.h"mutex moveMutex;

task rijden(){ while (true) { Acquire(moveMutex); OnFwd(OUT_AC, 75); Wait(1000); OnRev(OUT_C, 75); Wait(500); Release(moveMutex); }}task druksensor(){ while (true) { if (SENSOR_1 == 1) { Acquire(moveMutex); OnRev(OUT_AC, 75); Wait(500); OnFwd(OUT_A, 50); Wait(500); Release(moveMutex); } }}task main(){ SetSensorTouch(IN_1); Precedes(rijden, druksensor);}

De hoofdtaak main geeft het sensortype aan en start dan de beide andere deeltaken. Dan is de hoofdtaak afgelopen. De deeltaak: ‘rijden’ zorgt ervoor dat de robot blijft rijden. De deeltaak ‘druksensor’ controleert of de aanraaksensor wordt ingedrukt. Als dat zo is, worden de volgende handelingen verricht: eerst wordt de deeltaak ‘rijden’ stil gezet. Dit is erg belangrijk. De deeltaak ‘druksensor’ neemt nu het commando over de bewegingen van de robot over. Vervolgens zorgt deze deeltaak ervoor dat de robot een stukje terug gaat en draait. Daarna laat hij de deeltaak ‘rijden’ weer beginnen om de robot zijn stukjes vooruit te laten rijden.Het is erg belangrijk dat je beseft dat de taken die je start ook tegelijkertijd uitgevoerd worden. Dit kan onverwachte gevolgen hebben. Om deze problemen te vermijden, is er een vreemd soort variabele gebruikt, mutex, wat staat voor “mutual exclusion”. Deze variabele werkt alleen met de functies Acquire en Release.

SamenvattingIn dit hoofdstuk hebben we het gebruik van taken en deeltaken bekeken. Zij worden op verschillende wijze gebruikt.Deeltaken worden naast elkaar uitgevoerd en regelen geheel verschillende zaken die tegelijkertijd plaats moeten vinden.

Nu je deze zes hoofdstukken hebt doorgewerkt, moet je voldoende kennis hebben om je robot gecompliceerde, parallelle taken te laten uitvoeren.

CARTESIUS LYCEUM Pagina 35 van 44 mei ’23

Opdrachten bij hoofdstuk 6

Opdracht 1Stel je werkt met twéé druksensoren aan de voorkant van je robot. Wat zou hiervan het voordeel kunnen zijn t.o.v. één druksensor? Beargumenteer je antwoord.

Bouw nu een robot met twee druksensoren aan de voorkant en programmeer het programma zo, dat het aan deze eisen voldoet.

CARTESIUS LYCEUM Pagina 36 van 44 mei ’23

Hoofdstuk 7Parallelle takenZoals eerder is aangeduid, worden taken in de NXT-taal gelijktijdig uitgevoerd of anders gezegd parallel. Dit is buitengewoon nuttig. Het stelt je in staat om sensoren te bekijken die één taak uitvoeren, terwijl een andere taak er voor zorgt dat de robot rondrijdt en nog weer een andere taak muziek afspeelt. Maar parallelle taken kunnen ook problemen veroorzaken. De ene taak kan een andere taak storen.

Een programma met foutenBekijk het volgende programma. Hier zorgt een taak ervoor dat de robot in vierkanten (zoals we dat al zo vaak deden) rondrijdt en een tweede taak controleert de aanraaksensor. Wanneer de sensor aangeraakt wordt, rijdt de robot een stukje achteruit en maakt een draai van 90 graden.

#include "NXCDefs.h"

task check_sensors(){ while (true) { if (SENSOR_1 == 1) { OnRev(OUT_AC, 75); Wait(500); OnFwd(OUT_A, 75); Wait(850); OnFwd(OUT_C, 75); } }}

task submain(){ while (true) { OnFwd(OUT_AC, 75); Wait(1000); OnRev(OUT_C, 75); Wait(500); }}

task main(){ SetSensor(IN_1,SENSOR_TOUCH); Precedes(check_sensors, submain);}

Dit ziet er waarschijnlijk uit als een perfect werkend programma. Maar als je het programma uitvoert, zul je hoogstwaarschijnlijk enkele onverwachte bewegingen tegenkomen. Probeer het volgende maar: laat de robot ergens tegenaan rijden, terwijl deze draait. Hij zal terugrijden, maar meteen weer vooruit gaan rijden en opnieuw tegen het obstakel botsen. De reden hiervoor is dat de verschillende taken elkaar waarschijnlijk storen. Bekijk het volgende

CARTESIUS LYCEUM Pagina 37 van 44 mei ’23

schouwspel. De robot draait naar rechts, op het moment dat de tweede taak in een slapende toestand verkeert. Nu raakt de robot de sensor en begint achteruit te rijden, maar precies op dat moment komt de hoofdtaak uit zijn slapende toestand en zorgt ervoor dat de robot weer vooruit rijdt. De tweede taak blijft slapende zodat deze de botsing niet waarneemt. Dit is zeer zeker niet het programma dat we graag hadden gezien. Het probleem zit ‘m in het feit, dat terwijl de tweede taak in een slapende toestand verkeert we ons niet realiseerden dat de eerste taak nog steeds actief was en op deze manier de acties van de tweede taak stoort.

Het stoppen en weer starten van taken

Een manier om dit probleem op te lossen is er zeker van te zijn dat slechts één taak per keer de robot aanstuurt. Dat was de aanpak die we in Hoofdstuk 6 hanteerden. Hier staat het programma nog een keer.

#include "NXCDefs.h"

mutex moveMutex;task move_square(){ while (true) { Acquire(moveMutex); OnFwd(OUT_AC, 75); Wait(1000); OnRev(OUT_C, 75); Wait(850); Release(moveMutex); }}task check_sensors(){ while (true) { if (SENSOR_1 == 1) { Acquire(moveMutex); OnRev(OUT_AC, 75); Wait(850); OnFwd(OUT_A, 75); Wait(1000); Release(moveMutex); } }}task main(){ SetSensor(IN_1,SENSOR_TOUCH); Precedes(check_sensors, move_square);}

De essentie is dat de check_sensors taken de robot alleen besturen wanneer de move_square taken zijn afgehandeld. Op die manier kan deze taak het

CARTESIUS LYCEUM Pagina 38 van 44 mei ’23

wegrijden van de robot van het obstakel niet storen. Als de back-upprocedure is beëindigd, kan de move_square taak weer opstarten.

Hoewel dit een goede oplossing voor de boven geschetste situatie is, blijft er een probleem. Als we de taak move_square opnieuw starten, start deze weer vanaf het begin. Dit is leuk bij kleine taken, maar vaak is dat niet het gewenste resultaat. We zien liever dat de taak op een bepaald punt eindigt en daar ook weer begint. Helaas is dit geen gemakkelijke opgave.

Het gebruik van semaforen (signalen)

Een algemene techniek om deze problemen het hoofd te bieden is een varabele te gebruiken die aangeeft welke taak de motoren controleert. De andere taken wordt niet toegestaan de motoren aan te sturen, totdat de eerste taak via een variabele aangeeft, dat hij klaar is. Zo’n variabele wordt vaak een semafoor genoemd. We gebruiken hiervoor de afkorting sem. We nemen aan dat de waarde 0 aangeeft dat er geen taak is die de motoren aanstuurt. Telkens als een taak iets met de motoren wil gaan doen, moeten voortaan onderstaande commando’s worden uitgevoerd.

until (sem == 0); sem = 1; //Neem voorrang;// Schrijf hier opdrachten

sem = 0; // Geef voorrang weer terug;

Dus, eerst wachten totdat niemand de motoren nodig heeft. Dan nemen we de besturing over door sem de waarde 1 te geven. Nu kunnen we de motoren aansturen. Klaar, dan geven we sem weer de waarde 0. Hierboven vermelde programma legt de implementatie van het gebruik sem uit.Wanneer de aanraaksensoren iets voelen, wordt de semafoor aangezet (waarde 1) en de back-upprocedure uitgevoerd. Tijdens deze procedure moet de taak move_square wachten. Wanneer de back-upprocedure klaar is, wordt de semafoor uitgezet en kan de move_square taak verder uitgevoerd worden.

CARTESIUS LYCEUM Pagina 39 van 44 mei ’23

#include "NXCDefs.h"

int sem;

task move_square(){ while (true) { until (sem == 0); sem = 1; OnFwd(OUT_AC, 75); sem = 0; Wait(1000); until (sem == 0); sem = 1; OnRev(OUT_C, 75); sem = 0; Wait(850); }}

task submain(){ SetSensor(IN_1, SENSOR_TOUCH); while (true) { if (SENSOR_1 == 1) { until (sem == 0); sem = 1; OnRev(OUT_AC, 75); Wait(500); OnFwd(OUT_A, 75); Wait(850); sem = 0; } }}

task main(){ sem = 0; Precedes(move_square, submain);}

Semaforen zijn erg nuttig, wanneer je een gecompliceerd programma met parallelle taken schrijft. Bijna altijd heb je er wel een paar nodig.

CARTESIUS LYCEUM Pagina 40 van 44 mei ’23

SamenvattingIn dit hoofdstuk bestudeerden we enkele problemen die kunnen optreden bij het gebruik van verschillenden taken. Pas goed op voor zijdelingse effecten. Veel onverwachte zaken in het programma zijn hier aan te wijten. We hebben twee verschillende manieren om zulke problemen op te lossen bekeken.

De eerste oplossing met mutex moveMutex; laat een taak stoppen en weer herstarten om er zeker van te zijn dat slechts de belangrijkste taak op een bepaald moment actief is.

De tweede benadering maakt gebruikt van semaforen om de afhandeling van taken te sturen. Deze zorgt er zeker voor dat op elk moment alleen het belangrijkste deel van een taak wordt uitgevoerd.

CARTESIUS LYCEUM Pagina 41 van 44 mei ’23

Opdrachten bij hoofdstuk 7

Opdracht 1In de onderstaande programmacode wordt een semafoor gebruikt.Geef aan wat de functie van deze semafoor is en verklaar waarom dit programma niet zal werken. Kijk evt. welke foutmelding de compiler geeft.

#include "NXCDefs.h"

int sem;

task main(){ sem = 1; start move_square; SetSensor(IN_1, SENSOR_TOUCH); while (true) { if (SENSOR_1 == 1) { until (sem == 0); sem = 1; OnRev(OUT_AC, 70); Wait(500); OnFwd(OUT_A, 70); Wait(850); sem = 0; } }}

task move_square(){ while (true) { until (sem == 0); sem = 1; OnFwd(OUT_AC, 70); sem = 0; Wait(1000); until (sem == 0); sem = 1; OnRev(OUT_C); sem = 0; Wait(850); }}

Opdracht 2Oefen nu verder nog programma’s die 2 of 3 sensoren goed samen laten werken. Dat is namelijk ook de opdracht in je PO, die iedereen binnenkort krijgt.

CARTESIUS LYCEUM Pagina 42 van 44 mei ’23

Bijlage AHet bouwen van een Lego Mindstorms robot

Bij een set Lego Mindstorms Robotics Invention System zit een bouwbeschrijving, de “Construct-opedia”, voor het maken van verschillende robots. Probeer het model te bouwen uit deze handleiding. Het model ziet er als volgt uit:

Het aansluiten van sensoren op de NXTBovenop de NXT zitten 4 gekleurde knoppen en een klein LCD scherm. Met de oranje knop zet je de robot aan of uit. Met de twee lichtgrijze kun je zoeken naar iets uit het menu. Met de oranje kun je de geselecteerde functie kiezen of laten uitvoeren. En met de donkergrijze knop kun je terug gaan naar het vorige menu. Op de NXT zitten ook zeven contacten. Drie voor de motoren A, B en C en vier voor de sensoren 1, 2, 3 en 4.

CARTESIUS LYCEUM Pagina 43 van 44 mei ’23

Het verzenden van programma’s van de computer naar de robot

Om programma’s van de computer naar het geheugen van de NXT te verzenden moet deze met de USB-kabel zijn aangesloten. Controleer dit, eventueel met hulp van je docent.

De NXT moet met de USB-kabel zijn aangesloten aan de computer. De NXT moet aan staan. Als het Bricx Command Center wordt gestart, zal het automatisch de NXT zoeken. Als je het scherm hierboven ziet, klik dan op OK.

Het compileren van een programma

Nadat een programma correct is getypt in de NXT-editor klik je op de knop “Compile Program”. Als de compiler geen fouten vindt, kun je het programma verzenden naar de NXT.

Klik op de knop rechts van “Compile Program”. Deze knop heet “Download Program”. Het verzenden begint dan, mits de NXT op de juiste wijze is aangesloten met de USB-kabel om het programma te ontvangen.

CARTESIUS LYCEUM Pagina 44 van 44 mei ’23