Het bouwen van een robot

Uit RobotMC.be
Ga naar: navigatie, zoeken

Handleiding voor het bouwen van een mobiele en autonome robot

Inleiding

Dit boek beschrijft hoe je zelf een robot kunt bouwen met standaard onderdelen. Eerst worden algemene begrippen en kennis voorgesteld. Daarna worden specifieke robot onderdelen besproken. Vervolgens worden een aantal robots voorgesteld die te bouwen zijn door een hobbyist of student.

Het bouwen van robots wordt steeds meer toegankelijk, de onderdelen zijn eenvoudig te vinden en zijn goedkoper geworden. Het internet maakt het mogelijk veel informatie te vinden en met andere robot bouwers te communiceren via mailinglijsten en forums. Met dit boek willen we de kennis die door vele mensen wordt gedeeld via clubs en het internet voor iedereen toegankelijk maken gratis en voor niets.

Verschillende clubs zijn actief waar leden elke maand samenkomen. Wedstrijden worden georganiseerd en zijn voor velen een start om een robot te bouwen.

België: http://www.robotmc.be
Nederland: http://www.robotica.hccnet.nl

Google Discussiegroep

Terminologie

Electronica

Spanning, Stroom en Weerstand

Spanning

Stroom

Weerstand

Gereedschap

Digitale Multimeter

Soldeerbout

Componenten

Weerstand

Variabele weerstand

Diode

LED

Condensator

Spoel

Transistor

Op-amp

IC

printed circuit board (PCB)

Om de elektronica componenten te verbinden wordt een printed circuit board (PCB) gebruikt.

In het Nederlandse taalgebied noemen we dit een printplaat of print.

Het gebruik van een printplaat betekent een definitieve versie van de schakeling.

Printen kunnen we zelf maken volgens de fotografische methode.

Er bestaat echter ook nog de laserprinter-strijk methode. Deze methode is goedkoper en en voor een groter publiek bereikbaar. Hier nog een andere beschrijving van deze methode.

solderless breadboard

Om experimentele schakelingen op te bouwen kan beter een solderless breadboard (prikbord) (steekbord) gebruikt worden. We kunnen de componenten hier makkelijk in steken, wel rekening houden met de interne bedrading van het bord.

Actuatoren

Effectoren

De manier om een robot aan te drijven is om een actuator aan een effector te koppelen. We kennen o.a. de volgende effectoren:

Wielen, benen, luchtkussen.

We kunnen hiermee o.a. de volgende manieren van voortbewegen mee maken.

2 wielen + zwenkwiel: deze aandrijving wordt "differentiële aandrijving" genoemd.

4 wielen (zoals een auto): Dit is de zogenaamde "Ackerman aandrijving"

3 omnidirectionele wielen

balanceren op 2 wielen

rupsbanden (zoals een tank)

hovercraft

Sensoren

We kunnen sensoren klassificeren in verschillende soorten: interne, externe, actieve en passieve. Interne sensoren meten waarde intern in de robot, bijvoorbeeld een batterij spanning of de motor snelheid. Externe sensoren geven informatie over de omgeving van de robot. Bijvoorbeeld afstandsmetingen of geluid. Een passieve sensoren meet de energie die op de sensor invalt, bijvoorbeeld een CCD camera of microfoon. Een actieve sensor stuurt zelf energie naar de omgeving en meet vervolgens de reactie, bijvoorbeeld een ultrasone afstandsmeter.

Contactsensor

Afstandssensor

Navigatiesensor

Omwentelingssensor

Acceleratiesensor

Plaatsbepalingssensor

Temperatuursensor

Mechanica

Microcontrollers

Er zijn zeer veel soorten microcontrollers. Populair bij hobbyisten zijn de goedkope eenvoudig programmeerbare microcontrollers die met een minimum aantal externe componenten via de PC te programmeren zijn.

Atmel AVR

De AVR microcontrollers kunnen geprogrammeerd worden met verschillende compilers. Populair zijn vooral WinAVR en BASCOM. De opensource programmeeromgeving WinAVR werkt met de C compiler GCC. BASCOM werkt met BASIC en er is een gratis demo versie beschikbaar waarmee je kleine programmas kan maken. De fabrikant, Atmel levert ook veel support en voorbeeldprogramma's. Voor het programmeren in machinetaal is er het programma AVR Studio4. Dit is een zeer uitgebreide en gebruiksvriendelijke editor voor het programmeren in in machinetaal. De meest recente versie van AVR Studio en andere informatie is op de website van Atmel (gratis) beschikbaar.

Voor programmeervoorbeelden en meer informatie over de verschillende programma's die te gebruiken zijn kan je terecht op de website van AVRFreaks. Daarnaast is er op de website van Linuxfocus een aardig artikel te vinden over hoe je een avr kan programmeren aan de hand van gcc en linux.

Info Atmel Info BASCOM Info WinAVR Info AVRLib

Microchip PIC

Microchip (www.microchip.com) levert PIC single chip computers. Voor robots wordt veel gebruik gemaakt van PICs met een 14-bit core (16Fxxx). Voor nieuwe ontwerpen is het handiger gebruik te maken van PICs met de nieuwere 16-bit core (18Fxxx). Wel even controleren of je tools (compiler, programmer) dit ondersteunen.

Veel informatie over de PICs kun je vinden op www.voti.nl. Voti heeft tevens een webwinkel waar je PICs kunt bestellen.

Om PIC's te kunnen programmeren heb je een programmer nodig. Twee programmers waarmee clubleden goede ervaring hebben zijn:

Velleman K8048

Wisp628 (als bouwpakket of gebouwd verkijgbaar bij Voti)

Inmiddels is deze programmer al weer vervangen door een verbeterde versie, de Wisp648 (eveneens gebouwd of als bouwpaket verkrijgbaar bij Voti).


Je kunt PICs programmeren in assembler met de vrij verkrijgbare SDK van de fabrikant. Daarnaast kun je programma's voor PICs schrijven in Bascom, C of JAL.

Online PIC microcontroller tutorial

Sub systemen

Motorsturing

Voor onze robots gebruiken we meestal gelijkstroommotoren. Een (gelijkstroom) motor bestaat normaal uit een vast opgestelde magneet, waarbinnen een rotor met wikkelingen is gemonteerd. Als je een spanning zet op een motor, gaat er stroom lopen door deze wikkelingen. Die stroom geeft een magnetisch veld, dat wordt 'weggeduwd'door het veld van de vaste magneet en daardoor gaat de rotor draaien. Voor ons voorbeeld nemen we een motor die bij 12V 1000 toeren per minuut (rpm in het Engels) draait en een dc-weerstand heeft van 48 Ohm. Als we deze motor nemen, een voltmeter aansluiten op de klemmen en de as ronddraaien met 1000 toeren, dan slaat de voltmeter uit naar 12V. Door het draaien van de rotor door het magnetisch veld wordt wordt een spanning opgewerkt in de wikkeling van de motor en hebben we dus een generator. Als we stoppen met aandrijven van de motor-as, zal deze door verliezen (langzaam) vertragen en tot stilstand komen. En uiteraard werkt dit hetzelfde als de motor draait doordat er spanning op wordt gezet en vervolgens de spanning wordt verwijderd (Z-Z). Op de voltmeter zagen we dat een spanning over de motor staat als deze (vrij) draait en het is dan ook logisch dat er een stroom gaat lopen als we de motor kortsluiten (L-L). Op deze manier halen we energie uit de motor en zal de motor veel sneller stoppen. Met andere woorden: door het kortsluiten van de motor remmen we.

Tot nu toe zijn we steeds uitgegaan van de nominale spanning van de motor (12V), maar we kunnen de spanning natuurlijk ook wat lager maken. Het blijkt dat het toerental dan rechtevenredig afneemt en bij 6V zal onze motor ongeveer 500 toeren per minuut draaien. En datzelfde geldt uiteraard ook voor het gebruik van generator, want het effect van de generator is ook bij het gebruik als motor aanwezig. We kunnen zelfs de snelheid van een robot bepalen door de H-brug zwevend te zetten (Z-Z) en de spanning over de motor te meten (zoek op 'back-emf'voor meer info). En ook het inschakelgedrag van de motor kan worden verklaard met het effect van de generator: bij het inschakelen van de spanning wordt de motor-stroom in eerste instantie bepaald door de dc-weerstand van motor. In ons voorbeeld is de stroom 12V / 48Ohm = 0.25A en wordt 12V * 0.25A = 3W aan de motor geleverd. Het toerental van de motor neemt snel toe. Als het toerental bijvoorbeeld 333 is, zal de 'generator' 4V geven en de polariteit hiervan is tegengesteld aan de aangesloten spanning. Hierdoor staat 12-4=8V over de rotor en is de stroom afgenomen tot 8V/48Ohm = 0.167A en is het toegevoerde vermogen 12V * 0.167A = 2W. Het toerental loopt verder op en het vermogen neemt verder af totdat het toegevoerde vermogen gelijk is aan de verliezen in de motor en vertraging.

Het toerental van een motor is dus rechtevenredig met de spanning die we op de motor aansluiten en met zo'n linear verband maakt het mogelijk om een naukeurige en stabiele regeling te maken. Maar een circuit maken dat een motor met een analoge spanning - en ook nog vooruit en achteruit - aanstuurt is redelijk complex en ook nog eens inefficient doordat het veel energie omgezet in warmte. Daarom maken we meestal gebruik van een H-brug. Dit is een schakeling waarmee we een motor zowel vooruit of achteruit kunnen laten draaien.Veelal wordt gekozen voor een chip die 2 H-bruggen bevat, zoals de L293D of de L298. De eerste kan motoren aansturen die maximaal 600mA stroom gebruiken, de tweede kan 2A per motor leveren. - over een H-brug met transistoren (zoals L293D en L298) valt 2 a 3V, dus bij een 12V accu blijft maximaal 10V over voor de motor. - FET H-brug heeft minder spanningsverlies en schakelt sneller, daardoor veel minder verliezen en warmteontwikkeling. Maar door het snelle schakelen ook meer kans op storing op de voeding. - L298 bevat geen ingebouwde beschermingsdiodes; 1N5822 schottky diode dus extern toevoegen.

Een H-brug bestaat uit twee gelijke helften, die ieder een aansluiting van de motor kunnen verbinden met de voeding (H) of met massa (L). Daarnaast kan de H-brug worden uitgeschakeld (met enable), waardoor de motor-aansluiting zweeft (Z). De enable-ingang van de genoemde chips werkt op beide helften van een brug. Dit geeft de volgende mogelijke toestanden van de brug:

L - L (beide aansluiting laag => geen spanning over de motor)
L - H (een aansluiting laag, andere hoog - motor draait linksom)
H - L (een aansluiting hoog, andere laag - motor draait rechtsom)
H - H (beide aansluitingen hoog => geen spanning over de motor en dus gelijk met L - L)
Z - Z (ingangen zwevend, motor loopt vrij)

(De bovenstaande beschrijving van de H-brug is wat beknopt. Mocht niet duidelijk zijn hoe een H-brug werkt, lees dan eens een paar van de vele online artikelen over H-bruggen en werk eventueel bovenstaande verhaal bij ;) Het artikel gaat nu verder in op aansturing van de H-brug).

Op het eerste gezicht lijken L-L en Z-Z op elkaar, maar er is een belangrijk verschil: bij L-L is de motor kortgesloten en zoals we bij de beschrijving van motor hebben gezien, zal dit de motor (en daarmee de robot) sterk afremmen. Bij Z-Z is de motor niet aangesloten en zal de robot langzaam afremmen.

Bij H - L en L - H is de draairichting tegengesteld, maar ze lijken op elkaar in de zin dat dit 'vol gas' is. De motor is aangesloten op de volle batterijspanning (minus de spanningsval over de H-brug) en zal dus op volle snelheid draaien en dat is meestal niet de bedoeling. We willen de snelheid kunnen regelen en hiervoor gebruiken we PWM - Pulse Width Modulation ofwel puls-breedte modulatie. Hierbij wordt de H-brug door een puls met een vaste frequentie aangestuurd, maar de deel van de tijd dat deze puls hoog is, kan worden ingesteld. Het ligt voor de hand om het PWM signaal aan te sluiten op de enable van de H-brug. We kunnen dan met de H en L ingang de draairichting van de motor instellen en de PWM waarde kunnen we de snelheid varieeren. Maar wat gebeurt er dan precies? Laten we het draaien van de motor eens vergelijken met het duwen van een auto. Inschakelen van de H-brug is als het duwen tegen de auto, die daardoor steeds sneller gaat totdat de normale loopsnelheid is bereikt. Als je de helft van de tijd duwt, zal de motor tussendoor iets vertragen, maar minder dan deze versnelt tijdens het duwen. Kortom, de snelheid van de auto zal na enige tijd aanzienlijk sneller zijn dan 'halve loopsnelheid'. Dit effect zien we ook bij een H-brug en is weergegeven als blauwe curve in onderstaande grafiek.

Motorcurve.jpg

Deze curve geeft het verband aan tussen de PWM waarde (horizontale as, van 0 tot 1023) en het toerental (verticale as, in encoder pulsen per seconde). De curves zijn echte meetwaarden van faulhaber motoren met encoders van voti. De tweede curve in deze grafiek laat zien dat er een oplossing is. Deze oplossing is om te schakelen tussen duwen en afremmen. Ofwel schakelen tussen:

L-H en L-L 
en
H-L en H-H 

Er zijn natuurlijk meer combinaties mogelijk, maar deze waarden geven duidelijk aan hoe we dit kunnen toepassen bij een H-brug: We gebruiken een IO lijn om op de ene helft van de H-brug de richting aan te geven en zetten een PWM signaal op de andere helft van de H om de snelheid te regelen. De 'enable' ingang kunnen we vastleggen of - als we ook de mogelijkheid willen houden om 'uit te bollen' - op een IO lijn aansluiten. Het enige waar we rekening mee moeten houden is, dat in de eerste situatie een hoge PWM waarde (PWM lijn is lang hoog) ervoor zorgt dat de motor maximaal zal draaien. In de tweede situatie is dit H-H, waardoor de robot zal stoppen. De gewenste PWM waarde wordt dus bepaald door de gewenste snelheid en de draairichting. Maar... er is ook een nadeel aan deze methode. Van continue duwen en trekken wordt je moe en de robot-variant is dat de stroom sterk toeneemt. Bij de aansturing met 50% PWM op de enable pin, gebruikt de eerder genoemde faulhaber motor 17mA bij 14.3V. Bij aansturing H/L loopt de stroom op tot 106mA. Dit betekent dat de piek-stromen zeker het dubbele zijn (en waarschijnlijk nog veel meer). Dus gebruik, ook voor relatief kleine motoren een zware H-brug (mijn H-brug van 1.1A continue is bij deze testen in rook opgegaan...).

Motorkeuze

In voorgaande paragraaf is een aantal motorparameters besproken. Maar wat is nu een geschikte motor voor jouw robot? Het antwoord is: dat hangt er vanaf. Van de grootte van je wielen, de gewenste snelheid, het gewicht van je robot en de helling die je wilt nemen. Een mooie tool om dit door te rekenen vind je hier:

motor sizing tool

Je zult zien dat de maximale helling een grote invloed heeft op de motor die je nodig hebt!

Nog een aantal punten bij de keuze van motoren:

  • Het koppel (torque) uit de berekening is het maximale continue koppel. Soms wordt alleen de 'stall torque' opgegeven, omdat dit een hoger getal is en dus goed overkomt in de advertentie. De vuistregel is dat het continue koppel 20%-25% is van de stall torque.
  • Het is verleidelijk om een hoge topsnelheid te kiezen. Je kunt nooit genoeg snelheid hebben, toch? Realiseer je dat daarmee de minimale snelheid van je robot ook toeneemt. Daardoor neemt de nauwkeurigheid af waarmee je robot een route kan rijden of op een bepaald punt kan stoppen. Neem (voor nu) als vuistregel dat de minimale snelheid van de robot 20% is van de maximale snelheid. Voor robots die je binnenshuis gebruikt is de standaard 2 meter/seconde (7.2 km/uur) uit bovenstaand formulier erg hoog. Overweeg een topsnelheid tussen 0,5 en 1 meter/seconde.
  • Er is een groot verschil in de kwaliteit van motoren. Met motoren van betere kwaliteit heb je je robot over het algemeen beter onder controle, ook op lagere snelheden (soms wel tot 10% of 5% van de maximale snelheid). Maar hoe herken je goede motoren? De eenvoudige indicatie is de nieuwprijs in verhouding tot het vermogen. Merken als Maxon, Portescap en Faulhaber leveren top-motoren. Motoren van deze merken met een vermogen van enkele Watts kosten inclusief vertragingen vaak 150 euro of meer. Gelukkig zijn ze tweedehands vaak een stuk goedkoper.
  • Natuurlijk is prijs niet de enige indicatie voor de kwaliteit van de motoren, maar het is vaak lastig te zien in de specs. Eigenschappen die een motor beter bestuurbaar maken bij lage snelheid zijn (in willekeurige volgorde) goede lagers, maximaal toerental van de motor (voor de vertraging), hogere voedingsspanning en meer collector segmenten (commutator segments).

State Machine

(Eindige) toestandsmachines (FSM, Finite State Machines) zijn een waardevol hulpmiddel om complexe taken te implementeren op controllers die niet multi-tasking zijn. Neem als voorbeeld een situatie waarin een robot een obstakel wil vermijden door 10 seconden recht achteruit te rijden, vervolgens 5 seconden vooruit met het stuur naar rechts en dan weer rechtdoor. Een klassieke oplossing zou zijn:

void vermijd() { 
  stuur_rechtdoor();
  rijd_achteruit();
  wacht(10);               // A
  
  stuur_rechts();
  rijd_vooruit();
  wacht(5);                // B
  
  stuur_rechtdoor();
  rijd_vooruit();          // C
}

Dit werkt, maar heeft wel als consequentie dat de controller alleen hiermee bezig is en bijvoorbeeld sensoren worden tijdens deze actie niet uitgelezen. Een alternatieve aanpak is het gebruik van een toestandsmachine. De kern hiervan is dat je iedere toestand die enige tijd duurt een code geeft. In het voorbeeld hierboven zijn die met letters aangegeven achter de wachttijden. Vervolgens bepaal je per toestand naar welke andere toestand je kunt overgaan (in het voorbeeld is dat alleen A -> B -> C) en wanneer je zo'n overgang maakt (in het voorbeeld een bepaalde tijd). De functie pas je nu zo aan dat iedere state haar eigen stukje code krijgt. Dit ziet er als volgt uit:

void vermijd() {

  if (state == 'A') {
     if (first) {
        stuur_rechtdoor();
        rijd_achteruit();
        tijd = 10;
        first = 0;
     }
     if (tijd == 0) {
        state = 'B'
        first = 1;
     }
     return;
  }

  if (state == 'B') {
     if (first) {
        stuur_rechts();
        rijd_vooruit();
        tijd = 5;
        first = 0;
     }
     if (tijd == 0) {
        state = 'C'
        first = 1;
     }
     return;
 
  if (state == 'C') {
     if (first) {
        stuur_rechtdoor();
        rijd_vooruit();
        tijd = 999;
        first = 0;
     }
     return;
  }

}

Het is langere code, maar de structuur is wel vergelijkbaar. Wat is er nu veranderd? Om de opdracht uit te voeren moeten we onthouden waar we mee bezig zijn en in het eerste programma werd dit gedaan door middel van de regel van de code die we aan het uitvoeren waren. En daardoor konden we niets anders doen! In de nieuwe code gebruiken we de variabele 'state' om te onthouden waar we mee bezig zijn, zodat we iedere keer als de functie wordt aangeroepen, we de juiste regels code kunnen opzoeken. Daarnaast is een hulpvariabele 'first' toegevoegd om aan te geven dat we voor de eerste keer in een state zijn. We kunnen dan dingen instellen, zoals de rijrichting en de tijd die we in de state willen doorbrengen (n.b. dit is op zich niet nodig - je kunt het ook instellen als je de state wijzigt - maar hierdoor hou je wel alles van een state bij elkaar en dat maakt je code beter leesbaar).
Verder is de manier van tijdmeten veranderd. In de eerste functie werd een library-functie aangeroepen die het opgegeven aantal seconden wacht en in de tweede functie wordt de wachttijd in een variabele gezet die (bijvoorbeeld door een interrupt functie) iedere seconde met één wordt verlaagd totdat deze nul is.
Tot slot is de aanroep van de functie veranderd: we roepen de functie regelmatig aan (eens per seconde of vaker), maar de aanroep duurt maar heel kort. En daar was het allemaal om te doen! We kunnen na de aanroep van deze functie een functie aanroepen die een ultrasoon sensor uitleest, eentje die bumpersensors leest en verwerkt, eentje die het toetsenbord uitleest enz enz.

PID regelaar

Een regelaar is bedoeld om een gewenste waarde te "regelen". Hiervoor is het eerst noodzakelijk om de werkelijke waarde te meten. Aan de hand van de meting kan er dan bijgestuurd worden. Bij een robot moet er onder andere de wielsnelheid geregeld worden. De snelheid wordt meestal gemeten door encoders op de wielen, of op de motor. Deze encoders geven een aantal pulsen per omwenteling van het wiel. Als we deze pulsen tellen binnen een bepaalde tijd, weten we de wielsnelheid. Daarnaast weten dan ook de afgelegde weg. We kunnen nu deze meting gebruiken om de snelheid te regelen .

P-deel : We regelen bij evenredig met de fout (fout = gewenste snelheid - werkelijke snelheid).

I-deel : We regelen bij evenredig met de som van alle fouten.

D-deel : We regelen bij evenredig met de snelheid dat de fout verandert.

De kunst is nu om de juiste factoren te bepalen van P, I en D factor.

P = Proportional / I = Integral / D = Derivative of in het nederlands P = Proportioneel / I = integrerend / D = Differentiërend

Odometrie

Er zijn verschillende manier om de positie van je robot te kunnen bepalen. Eén daarvan is odometrie, ook wel "dead reckoning" genoemd. Columbus en de meeste andere zeevaarders uit zijn tijd, maakte gebruik van "dead reckoning". In dead reckoning, vindt de navigator zijn positie aan de hand van de route en afgelegde afstand vanaf het begin punt. Wanneer hij vertrekt vanuit een bepaald gekend punt, zoals een haven, meet de navigator zijn route en zijn afstand op een kaart uit vanaf dat punt, en prikt met een pin om de nieuwe positie te markeren. De eindpositie van elke dag, zal het startpunt zijn voor de route- en afstandsmeting van de volgende dag.

Odometrie kan je op verschillende manieren implementeren. Je kan werken met twee wiel-encoders en telkens uitrekenen welke afstand je aflegt en onder welke hoek. Of je kan een kompas gebruiken en één wiel-encoder.

De methode van Columbus wordt geimiteerd door de afgelegd weg te berekenen over een bepaalde tijd. Zogenaamde "timestamps" zijn bedoeld om vaste punten in de tijd te creeren waarop een nieuwe berekening gemaakt wordt. Per tijdsinterval wordt de afgelegde weg berekend. Dat is dus te vergelijken met de dagelijkse pin op de kaart. Voor een betere nauwkeurigheid is het aan te bevelen om de afgelegde weg te berekenen over een zo groot mogelijke afstand en tijd. Als de robot bijvoorbeeld gedurende vijf intervals dezelfde koers volgt is het nauwkeuriger om in een keer de totaal afgelegde weg te berekenen in plaats van over vijf stukjes. Hierdoor ontstaan er minder afrondingsfouten. Ook het maken van bochten draagt sterk bij aan het optreden van fouten in de berekende positie. De grootste nauwkeurigheid wordt bereikt door de robot te laten stoppen en dan op de plaats te draaien tot de neus weer de juiste kant uitwijst.

Formules voor odometrie

Gebruikte variabelen: n = current timestamp; n-1 = previous timestamp; D = distance traversed in the last interval;

Px = X-position on a virtual grid; Py = Y-position on a virtual grid

Tx, Ty = Coordinates of target

Formules: Grid position: Px(n) = (D(n) x sin @(n) + Px(n-1); Py(n) = (D(n) x cos @(n) + Py(n-1);

Heading to target: Tx - Px(n)/Ty - Py(n)= tan (compass angle to destination) This will give two solutions that differ 180deg. We can use the sign of Tx - Px(n) & Ty - Py(n) to distinguish

If Tx - Px(n)>0 AND Ty - Py(n)>0 angle = 0-90 If Tx - Px(n)>0 AND Ty - Py(n)<0 angle = 90-180 If Tx - Px(n)<0 AND Ty - Py(n)<0 angle = 180-270 If Tx - Px(n)<0 AND Ty - Py(n)>0 angle = 270-360

This can also be used to limit the search range to one quadrant.

Distance to target (Tx - Px(n)) / (sin (angle to destination) or (Ty - Py(n)) / (cos (angle to destination)

Gedrag

Voorbeeld robots

Uitdagingen (opdrachten)

Lichtzoeken

Lijnvolgen

Muurvolgen

Blikjes zoeken (CAN CAN)

En natuurlijke onze Robotwedstrijden!