ee1810: Smart Robot Challenge - 2013/2014
Autonome Mijnen-Ontwijkende Robot Gebaseerd op Spartan-3 Platform
Delft University of Technology
Ontwerprapport
door Projectteam A4 Danny Eldering, 4297407 Bart Hettema, 4293398 Daan Offerhaus, 4276035 Hans Okkerman, 4290453 Joran Out, 4331958
15 juni 2014 Versie 2.1
Versieoverzicht In de onderstaande tabel staat een overzicht van de versies van dit document. Bij elke versie zijn de belangrijkste wijzigingen genoteerd. Versie 1.0 1.1 1.1
Datum 02/04/2014 04/04/2014 04/04/2014
1.1 1.1 1.1
04/04/2014 04/04/2014 04/04/2014
1.2 2.0 2.1
08/04/2014 09/06/2014 15/06/2014
Wijzigingen Eerste opzet Servomotoren Lijnvolger Conclusie XBee Routeplanner Inleiding Probleemstelling Systeemoverzicht Appendices Eindrapport Bijgewerkte C-code
Auteur Bart Daan Hans Danny Bart Joran
Bart Allen Bart
Samenvatting Tijdens het EPO-2 project "Smart Robot Challenge"hebben wij een robot gemaakt en geprogrammeerd die diverse challenges uit kan voeren. Ook zijn diverse metingen uitgevoerd.
Programmeren Het programmeren van de robot gebeurt door het instellen van een FPGA. Hierbij wordt gebruikt gemaakt van de hardwarebeschrijvingstaal VHDL. De robot communiceert door middel van een draadloze verbinding met een computer. Deze verbinding wordt tot stand gebracht tussen twee XBEE’s. Het deel op de computer hebben wij geprogrammeerd in C. Dit deel bevat een routeplanner en aansturing van de robot.
Opdrachten De robot kan succesvol een zwarte lijn volgen en van afstand bestuurd worden. De robot moet drie opdrachten kunnen uitvoeren. Bij de eerste opdracht wordt de robot op controlepost 1 geplaatst en moet hij vervolgens 3 gegeven controleposten passeren. De robot is in staat deze opdracht in zijn geheel succesvol uit te voeren. Bij de tweede opdracht wordt op 13 baanstukken in het midden een metalen ’mijn’ geplaatst. De robot mag niet over deze mijnen heen rijden, en zal ze dus moeten kunnen detecteren en er vervolgens een route omheen plannen. De robot begint weer op controlepost 1 en moet 3 voorafgegeven controleposten bezoeken. De robot is in staat om mijnen op te merken en dit door te geven aan de computer. Het Cprogramma kan vervolgens met succes een nieuwe route berekenen. Door een tot vooralsnog onbekende fout is het programma vervolgens echter niet in staat om verder te gaan. De robot kan deze opdracht dus niet geheel succesvol afronden. Bij opdracht 3 wordt op 13 baanstukken een mijn neergelegd. De robot moet in kaart brengen op welke lijnstukken deze mijnen liggen. Vervolgens wordt een 14e mijn neergelegd, de zogenaamde ’schat’. De robot moet met behulp van de eerder gemaakte kaart aangeven waar deze mijn is bijgelegd. Wij zijn er niet aan toegekomen om zo te programmeren dat deze challenge uitgevoerd kan worden. Wel is er een algoritme bedacht om deze opdracht efficiënt te kunnen uitvoeren.
i
ii
SAMENVATTING
Inhoudsopgave Samenvatting
i
1
Inleiding 1.1 Motivatie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.2 Opbouw rapport . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
1 1 1
2
Probleemstelling 2.1 Projectopgave: . . . . . . . . . . 2.1.1 Opdrachten . . . . . . . . 2.2 Beschikbare infrastructuur . . . . 2.2.1 Spartan-3 robotplatform . 2.2.2 Eigenschappen mijnenveld 2.3 Functionele eisen . . . . . . . . . 2.4 Randvoorwaarden . . . . . . . . . 2.5 Plan van aanpak . . . . . . . . . . 2.6 Projectresultaat . . . . . . . . . . 2.7 Doelstelling . . . . . . . . . . . . 2.7.1 Eisen . . . . . . . . . . . 2.8 Risico-analyse . . . . . . . . . . . 2.9 Projectorganisatie . . . . . . . . . 2.9.1 Projectleden . . . . . . . . 2.9.2 Coordinatie . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
3 3 3 3 4 4 4 4 6 6 6 6 7 8 8 8
Systeemoverzicht 3.1 Gewenste systeemspecificaties . . 3.2 Functionele systeemdecompositie 3.2.1 Hardware . . . . . . . . . 3.2.2 Software . . . . . . . . . 3.3 Algemene ontwerpoverwegingen .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
9 9 9 9 10 10
Aansturing Servomotoren 4.1 Eisen . . . . . . . . . . 4.2 Ontwerp . . . . . . . . . 4.3 Implementatie . . . . . . 4.3.1 Tijdbasis . . . . 4.3.2 Motoraansturing 4.4 Test . . . . . . . . . . . 4.5 Discussie . . . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
11 11 11 11 11 11 12 12
3
4
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
iii
iv 5
6
7
INHOUDSOPGAVE Simpele lijnvolger 5.1 Eisen . . . . 5.2 Ontwerp . . . 5.3 Implementatie 5.4 Test . . . . . 5.5 Discussie . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
13 13 13 13 14 14
Draadloze Communicatie: XBee Module 6.1 Eisen . . . . . . . . . . . . . . . . . 6.2 Ontwerp . . . . . . . . . . . . . . . . 6.3 Implementatie . . . . . . . . . . . . . 6.4 Test . . . . . . . . . . . . . . . . . . 6.5 Discussie . . . . . . . . . . . . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
15 15 15 15 15 16
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
Mijndetector 7.1 Eisen . . . . . . . . 7.2 Ontwerp . . . . . . . 7.3 Implementatie . . . . 7.3.1 Sensorcircuit 7.3.2 Uitleescode . 7.4 Test . . . . . . . . . 7.5 Discussie . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
17 17 17 17 17 20 21 22
Routeplanner 8.1 Eisen . . . . 8.2 Ontwerp . . . 8.3 Implementatie 8.4 Test . . . . . 8.5 Discussie . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
25 25 25 25 26 26
Routevolger 9.1 Eisen . . . . 9.2 Ontwerp . . . 9.3 Implementatie 9.4 Test . . . . . 9.5 Discussie . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
27 27 27 27 28 28
10 Integratie van de Subsystemen 10.1 Toplevel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.2 FPGA controller . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10.3 Console aansturing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
29 29 29 30
11 Testen van de Robot 11.1 Testplan . . . . . . . . . . . . . 11.2 Testresultaten . . . . . . . . . . 11.2.1 Lijnvolger . . . . . . . . 11.2.2 Draadloze communicatie 11.2.3 ’Challenge 1’ . . . . . . 11.2.4 Mijnendetector . . . . . 11.2.5 ’Challenge 2’ . . . . . .
31 31 31 31 31 32 32 32
8
9
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
INHOUDSOPGAVE
v
11.3 Vergelijking gewenste en bereikte systeemspecificaties . . . . . . . . . . . . . . . . . . .
32
12 Discussie
33
13 Conclusies en Aanbevelingen
35
14 Reflectie op de Groepsproces 14.1 Afspraken . . . . . . . . 14.1.1 Communicatie . 14.1.2 Opslag . . . . . 14.1.3 Rolverdeling . . 14.2 Groepsproces . . . . . . 14.3 Opmerkingen . . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
37 37 37 37 37 38 38
Bibliografie
39
A RTL Schematic
41
B C broncode bestanden B.1 C program main.c . . B.2 C program roadplan.c B.3 C program junction.h B.4 C program junction.c B.5 C program road.h . . B.6 C program road.c . . B.7 C program robot.h . . B.8 C program robot.c . . B.9 C program salloc.h . B.10 C program salloc.c .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
43 43 48 50 50 50 51 51 51 52 52
C User constraint file
53
D Wedstrijdregels
55
E VHDL broncode bestanden E.1 UART . . . . . . . . . . . E.2 Baud rate generator . . . . E.3 UART transmitter . . . . . E.4 UART receiver . . . . . . E.5 Buffer register with flag FF E.6 Mijnsensor . . . . . . . . E.7 Inputbuffer . . . . . . . . E.8 Tijdbasis . . . . . . . . . . E.9 Motorcontroller . . . . . . E.10 Controller . . . . . . . . . E.11 Robot . . . . . . . . . . . E.12 Toplevel . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
. . . . . . . . . . . .
59 59 60 61 62 64 64 66 66 67 67 69 71
vi
INHOUDSOPGAVE
Hoofdstuk 1
Inleiding 1.1
Motivatie
Dit project is onderdeel van de Bachelor opleiding "Electrical Engineering", uitgevoerd door EPO Groep A4. Tijdens dit project doen wij onderzoek naar de techniek van Robotica. Hiertoe zullen wij een robot programmeren om een afstand zo snel mogelijk af te leggen. Ook zullen wij uiteindelijk zelf een metaalsensor maken. Het ontwerpen en programmeren van de robot en sensor is hierbij van groot belang. Het einddoel van dit project is om alle opdrachten zoals in chapter 2 beschreven te voltooien. Daarnaast is er buiten de Technische Universiteit Delft ook nog steeds (groeiende) belangstelling voor deze technieken. In het verkeer wordt er steeds meer gevraagd naar betere navigatiesystemen. Ook de mijndetector is nog erg gewild. Niet alleen in actieve oorlogsgebieden, maar ook oude mijnen en bommen uit reeds gestreden oorlogen vormen een gevaar. Veel van deze bommen en mijnen kunnen alsnog ontploffen en moeten dus gevonden worden. Het ontwikkelen en verbeteren van mijndetectors is hierin essentieel.
1.2
Opbouw rapport
Het verslag zal bestaan uit een overzicht van de probleemstellingen, een ontwerpbeschrijving, een conclusie en een literatuurlijst. Na de projectopgave en de hieraan verbonden opdrachten worden in de ontwerpbeschijving de volgende onderdelen van de robot besproken: het systeemoverzicht, de aansturing van de servomotoren, de (Simpele) lijnvolger, de draadloze communicatie en de routeplanner. Elk onderdeel zal verdeeld zijn in vijf delen. Het eerste deel zal de vereisten van het onderdeel bevatten. In het tweede deel wordt het ontwerp beschreven. Daarop volgt de implementatie en de test. In de discussie, het vijfde en laatste deel, zal deze test besproken worden.
1
2
HOOFDSTUK 1. INLEIDING
Hoofdstuk 2
Probleemstelling Tijdens dit project zullen wij als projectgroep veel probleemstellingen moeten oplossen. Hoewel problemen vooral uit praktijk gehaald zullen worden, weten we enkele doel- en probleemstellingen die wij deze projecttijd zullen moeten oplossen.
2.1
Projectopgave:
De robot doet aan het einde van het project mee aan een challenge bestaande uit 3 onderdelen met oplopende moeilijkheidsgraad. De oprdachten voor de drie onderdelen zijn: het navigeren van een 5 × 5 grid om van een gegeven knooppunt zo snel mogelijk naar een ander punt te komen, het navigeren van een 5 × 5 grid met detecteerbare ’mijnen’ die ontweken moeten worden en het in kaart brengen van een 5 × 5 grid met 13 ’mijnen’ waarna een 14e mijn geplaatst wordt en gevonden moet worden.
2.1.1
Opdrachten
Opdracht 1: Bij de eerste opdracht wordt de robot op controlepost 1 geplaatst en moet vervolgens 3 gegeven controleposten passeren. Opdracht 2: Bij de tweede opdracht worden op 13 baanstukken op het midden een ’mijn’ geplaatsd. De robot mag niet over deze mijnen heen rijden, en zal ze dus moeten opmerken en een route eromheen plannen. De robot begint weer op controlepost 1 en moet 3 voorafgegeven controleposten bezoeken. Opdracht 3: Bij opdracht 3 worden op 13 baanstukken mijnen neergelegd. De robot moet in kaart brengen op welke lijnstukken deze 13 liggen. Vervolgens wordt een 14e mijn neergelegd, de zogenaamde ’schat’. De robot moet met behulp van de eerder gemaakte kaart aangeven waar deze mijn is bijgelegd. NB.: Zie Appendix D voor de wedstrijdregels.
2.2
Beschikbare infrastructuur
De beschikbare infrastructuur zal bestaan uit zowel de hardware van de robot als het mijnenveld waarop de robot moet gaan functioneren. 3
4
HOOFDSTUK 2. PROBLEEMSTELLING
2.2.1
Spartan-3 robotplatform
Als hardware hebben wij de beschikking over een Spartan-3 robotplatform. Dit is een Basys2 FPGA development board, en vormt de basis van onze robot. Aangesloten aan dit platfrom zit een utility bord, waaraan de andere componenten van de robot verbonden zijn. Ook de computer kunnen we via een mini-usb poort op het platform aansluiten op de robot.
2.2.2
Eigenschappen mijnenveld
Het wedstrijdveld dat voor de robotcompetitie gebruikt wordt bestaat uit een zwart-wit geprint papiervel (3 rollen, elk 914 mm breed). Het is geplakt op een houten bord met afmetingen 244 cm x 244 cm. Het zwarte patroon is te zien in Figure 2.1.
2.3
Functionele eisen
De robot moet aan het eind van het project aan de volgende (functionele) eisen voldoen: • De robot moet (zo snel mogelijk) een lijn kunnen volgen. • De robot moet zo snel mogelijk bochten van 90◦ kunnen maken. • De robot moet (al dan niet draadloos) kunnen communiceren met de computer. • De robot moet via deze communicatie aangestuurd kunnen worden. • De robot moet mijnen kunnen detecteren. • De robot moet mijnen in een geheugen kunnen opslaan. • De robot moet vervolgens een nieuwe mijn kunnen ontdekken.
2.4
Randvoorwaarden
Tijdens dit project wordt rekening gehouden met randvoorwaarden waaraan het eindproduct moet voldoen. Allereerst worden algemene voorwaarden door de opdrachtgever voorwaarden gesteld voor de robot1 : • De robot moet niet groter zijn dan 30 cm x 25 cm x 20 cm; gewicht is maximaal 1 kg. • De aansturing moet worden gedaan via de Spartan3E 250k FPGA chip en de draadloze communicatie via ZigBee (twee XBee modules), via de laptop of pc. • De configuratie van de FPGA-chip kan alleen geschieden via een in-VHDL-geschreven broncode. • Het stuurprogramma op de laptop/PC moet in de programmeertaal C geschreven zijn (dus niet in C++ of C#). • Het besturingsprogramma moet zo geschreven zijn, dat het door de gebruiker niet mogelijk is om de posities van de obstakels of de vrije wegsegmenten op het wedstrijdveld in te voeren. • Als energiebron mogen alleen accu’s gebruikt worden. 1 Zie
Appendix D
2.4. RANDVOORWAARDEN
5 Smart Robot Challenge
7
8
9
Smart Robot Challenge
1
START
2
3
Smart Robot Challenge
4
12
5
11
6
10 Smart Robot Challenge
Figuur 2.1: Het wedstrijdveld Smart Robot Challenge 2013 (de afmetingen zijn 244 cm x 244 cm).
• De robot moet zo geconstrueerd zijn, dat deze geen schade of markeringen aan het wedstrijdveld aanbrengt. • Verder moet de robothardware in de oorspronkelijke configuratie zonder schade terug ingeleveren worden na afloop van EPO2. Omdat de grootste vrijheden liggen bij het ontwerpen van de sensor, is het verstandig te onderzoeken of we hierin gelimiteerd zijn. Vanuit de wedstrijdregels1 en de FAQ is gebleken dat er geen beperkingen zijn wat betreft het aantal of type sensoren. Er zijn echter de volgende voorwaarden: • De sensor(en) die gebruikt worden voor mijndetectie moet zelf opgebouwd zijn door het projectteam
6
HOOFDSTUK 2. PROBLEEMSTELLING uit discrete elementaire componenten (draad, stukje printplaat, spoel, etc.), d.w.z. er is niet toegestaan om een complete sensorsysteem te kopen of door iemand anders dan de teamleden te laten bouwen. • De sensoren mogen ook aan de achterkant van de robot gevestigd worden.
Naast al deze restricties hebben we ook vrijheden, zo mogen we een totaal nieuw robotontwerp gebruiken.
2.5
Plan van aanpak
Tijdens het tweede projectkwartaal hebben wij als projectgroep een eigen planning gemaakt. Deze planning word besproken in het "Plan van aanpak", dat onderdeel van het procesverslag is.
2.6
Projectresultaat
Het resultaat van ons project zal een robot zijn die op een grid van zwarte lijnen zijn weg kan vinden. Ook zal de robot mijnen moeten ontwijken en een schat moeten opzoeken[2]. De robot bestaat uit: • NiCH battery pack • Basys2 FPGA development board • Utility board met stroomregelaar en connectors voor sensors en servo’s • 2 servomotoren en line tracking sensor board aangesloten op de utility board Over het ontwerpen en programmeren van de robot zal er een ontwerprapport gemaakt worden
2.7 2.7.1
Doelstelling Eisen
De robot moet al het in section 2.1 gestelde kunnen uitvoeren. Moeilijkheden Bij het doorlopen van het project zullen wij een aantal onderdelen zelf moeten bouwen, ontwerpen of aanpassen. Hierbij zullen wij Algemeen: Het eerste onderdeel van de robot waar aandacht aan moet worden besteed is de accu. Hoewel dit onderdeel snel over het hoofd kan worden gezien is het cruciaal belang dat deze goed werkt aan het einde van het project. Dit betekend niet alleen dat we hem moeten opladen, maar ook dat wij erachter moeten zien te komen welke specificaties de accu heeft. De accu is standaard meegeleverd met de robot. Op basis van de specificaties kunnen wij de andere onderdelen van de robot met optimaal resultaat ontwerpen.
2.8. RISICO-ANALYSE
7
De Motor: De batterij alleen breng de robot niet in beweging, dus zal onze volgende uitdaging het aansturen van de motor zijn. Ook de motoren zijn hebben we al tot onze beschikking gekregen. We moeten dus uitvinden hoe deze aan te sturen zijn en hiervoor een schakeling bouwen. Belangrijk bij het ontwerpen van deze schakeling zijn de volgende vraagstukken: Hoe gaan we de route volgen? - Door de afstand te meten? - Door kruisingen detecteren en dan af te slaan? Ook het maken van bochten is een aandachtpunt, aangezien wij verwachten dat de bochten het meeste tijdverlies opbrengen. Sensoren: Voor het volgen van de rasterlijnen hebben wij beschikking gekregen over een aantal sensoren. Ook zal er een sensor beschikbaar zijn voor het detecteren van mijnen. Vraagstukken die opgelost moeten worden tijdens dit project zijn: - Op welke afstand tot de grond moeten de sensoren hangen om optimaal te werken? - Hoe moeten we de kruispunten detecteren? - Hoe kunnen we terugkeren als we een mijn ondekt hebben? - Hoe kunnen we de mijnen onthouden voor latere opdrachten? - Hoe kunnen we een module inbouwen die berekent of over een mijn rijden effectiever is? Communicatie: - Betrouwbaar (rekening houden met interferentie met anderen) Bevoorrading: - Uitzoeken welke materialen te gebruiken - Wat ligt er op Drebbelweg - Waar moeten we zelf voor zorgen?
2.8
Risico-analyse
Dit project gaat gepaard met enkele risico’s. Een van die risico’s bestaat uit het feit dat de verschillende oderdelen van dit project van elkaar afhankelijk zijn. Een belangrijk onderdeel is bijvoorbeeld het onderdeel waar de robot wordt geprogrameerd om de zwarte lijnen te volgen. Een ander risico is het feit dat wij onder tijdsdruk werken. Omdat dit project parallel loopt aan onze opleiding is er een duidelijke deadline. Deze deadline zorgt ervoor dat er weinig speling is en we het daarom ook niet kunnen veroorloven grote vertragingen op te lopen. En juist deze vertragingen kunnen wij oplopen door het volgende risico. Aangezien wij studenten zijn, is het voornaamste doel van dit project om ervan te leren. Dit gaat echter deels ten koste van de sneleid van het project, doordat wij theorieën tegen kunnen komen die ons nog niet geleerd zijn. Het feit dat wij studenten zijn levert nog meer risico’s op. Er bestaat de mogelijkheid dat er een student dit project verlaat. Om te voorkomen dat hierdoor informatie en/of kennis verloren gaat, hebben wij besloten alle taken met minstens twee personen uit te voeren.
8
HOOFDSTUK 2. PROBLEEMSTELLING
Echter een van de grootste risico’s is dat wij geheel afhankelijk zijn de robot. Als er onverhoopt iets gebeurd met onze robot, dan kunnen wij deze vanzelfsprekend de opdracht niet meer laten vervullen. Om dit risico te verminderen hebben wij een extra (reserve) robot gekregen. Het risico blijft echter altijd aanwezig.
2.9 2.9.1
Projectorganisatie Projectleden
Achternm Bartek Eldering Hettema Offermans Okkerman Out
2.9.2
Voornm Marian Danny Bart Daan Hans Joran
Studentnr
Adres, woonplaats
4297407 4293398 4276035 4290453 4331958
Leklaan 79, Ridderkerk Lisztstraat 72, Delft Westlandseweg 39, Delft Gaagweg 7a, Schipluiden Watermuur 42, Velserbroek
e-mailadres
[email protected] [email protected] [email protected] [email protected] [email protected] [email protected]
Telnr +31-(0)15-27 89049 0612610729 0639876825 0657959809 0622891708 0640978183
Coordinatie
Vergaderen Er wordt elke projectmiddag (maandag en woensdag) een openende en afsluitende vergadering gehouden. Deze vergaderingen dienen vooral gespitst zijn op het vinden van nieuwe ideeën en oplossingen en het in de gaten houden van de voortgang van het project. Verslaglegging Vergaderingen worden genotuleerd en deze notulen worden wekelijks op dropbox en blackboard geplaatsd.
Hoofdstuk 3
Systeemoverzicht 3.1
Gewenste systeemspecificaties
Voor het vervullen van de opdrachten (genoemd in hoofstuk 2) moeten er twee systemen gebouwd worden: een mijnen-detector en een routesysteem. Deze systemen moeten zo robuust en betrouwbaar mogelijk gemaakt worden. Ook moet tijdens het ontwerpen van deze systemen worden geprobeerd met beschikbare middelen te werken.
3.2 3.2.1
Functionele systeemdecompositie Hardware
Robot Basys2 FPGA development board robot utility board experimentation board to implenent interface circuitry for the mine-detection sensor line tracking sensor board ZigBee module XBee S1 GWS continuous rotation servos with 3-pin Futaba style connector 2,56"diameter ABS wheels compatible with the servos 7.2 V, 2200 mAh NiMh accu pack with Tamiya connector 41 mm diameter swivel caster wheel chassis from a 4 mm thick perspex plate pc ZigBee module XBee S1 9
10
3.2.2
HOOFDSTUK 3. SYSTEEMOVERZICHT
Software
Robot FPGA (VHDL) Toplevel Controller Inputbuffer Motorcontrol Mijnsensor Robot Timebase PC (C) Main Junction Road Roadplan Robot Salloc De opbouw van de VHDL-onderdelen is in detail te zien in Appendix A. Bij het maken en gebruiken van deze programmeringen hebben wij gebruik gemaakt van de volgende software: Xilinx Design Suite, Modelsim, X-CTU, Digilent Adept
3.3
Algemene ontwerpoverwegingen
De belangrijkste ontwerpoverweging is gemaakt in de software. Deze overweging ging over de verhouding van C-code en VHDL. Besloten is om de robot via de hardware de lijnen te laten volgen. Ook moet de robot via deze weg commando’s als rechtsaf, linksaf etc. kunnen opvolgen. Daarnaast hebben wij besloten om de mijnen-sensor aan de voorkant, maar onder de wagen te bouwen.
Hoofdstuk 4
Aansturing Servomotoren 4.1
Eisen
De servomotoren zijn verantwoordelijk voor het bewegen van de robot, en vormen daarom van begin af aan een essentieel onderdeel van het ontwerp van de robot. De motoren zorgen voor aandrijving maar ook sturing, en moeten daarom onafhankelijk en precies aagestuurd kunnen worden.
4.2
Ontwerp
Beide motoren moeten onafhankelijk aangestuurd worden door de FPGA. Dit wordt bereikt door middel van een puls elke 20 ms [2, p. 84-85], waarbij de pulslengte, tussen de 0.9 en 2.1 ms, bepaalt of de motor linksom, rechtsom of niet draait. Er moet dus een FSM gemaakt worden die een 50 Hz pulssignaal kan produceren met afhankelijk van de gewenste richting een pulsbreedte van 0.9 tot 2.1 ms. De complete aansturing bestaat in essentie uit 4 blokken: een inputbuffer, een regelblok, een tijdbasisblok, en voor elke motor een aansturingsblok dat de puls genereert. Het ontwerp van de laatste twee wordt hier besproken, terwijl de eerste twee bij het hoofdstuk Simpele lijnvolger besproken worden.
4.3 4.3.1
Implementatie Tijdbasis
De tijdbasis is een ontwerpblok dat het 50 MHz trilkristal op het FPGA-bord gebruikt om een tijdreferentie te maken voor de andere ontwerpblokken. Omdat de aansturing bestaat uit een puls met een trillingstijd van 20 ms is de tijdbasis ontworpen om tot 20 ms te ’tellen’ en vervolgens opnieuw te beginnen. Gezien het kloksignaal een frequentie heeft van 50 MHz, moet de tijdbasis simpelweg tot 1000000 tellen. Het ontwerp is een zeer simpele Moore FSM. de tijdbasis heeft twee ingangen, kloksignaal en reset, en een uitgang, count_out, die aangeeft hoeveel klokgangen geteld zijn. Elke klokgang wordt de volgende waarde van count_out de huidige waarde +1. Als de reset waarde ’1’ heeft of de count_out waarde 999999, wordt de volgende waarde 0. De volledige VHDL-code van de tijdbasis staat in appendix Tijdbasis
4.3.2
Motoraansturing
De motoraansturing is een blok dat voor beide servo’s apart met behulp van het regelblok en de tijdsbasis de daadwerkelijke aanstuurpuls genereert. Het blok is een Moore FSM met drie states: motor uit, linksom 11
12
HOOFDSTUK 4. AANSTURING SERVOMOTOREN
draaien, rechtsom draaien. Aan het begin van de 20 ms (tijdbasis output is ’0’) heeft het blok outputwaarde ’1’ tenzij de huidige state motor uit is. Vervolgens, afhankelijk van of de state linkom of rechtsom draaien is, wordt de outputwaarde ’0’ als tijdbasis output 50000 of 100000 is. Dit resulteert in een 1.0 ms dan wel 2.0 ms lange puls. De huidige state wordt elke klokslag bepaalt door de inputs reset en direction. Als reset ’1’ is wordt de state ’motor uit’, zo niet wordt de state linksom draaien als direction ’0’ is of rechtsom draaien als direction ’1’ is. Met De volledige VHDL-code van de tijdbasis staat in appendix Motorcontroller
4.4
Test
Het testen van de servomotoren bestond uit een van de twee motoren aan te sturen door het FPGA bord. Een schakelaar werd gebruikt om de stuurrichting aan te geven, en een drukknop om de input reset aan te geven. Het doel van de test was beide servomotoren onafhankelijk van elkaar links- of rechtom te laten draaien. Zo gauw de FPGA werd aangezet bewoog de motor die op dat moment werd aangestuurd linksom als de switch laag stond, en rechtsom als de switch hoog stond. Hieruit viel af te leiden dat de aansturing werkte zoals bedoeld.
4.5
Discussie
Omdat de VHDL-codes al grondig getest en gesimuleerd waren, was het geen verassing dat de servomotoren zonder problemen de test doorstonden. Het aangesloten wiel draaide linksom of rechtsom afhankelijk van de direction switch, en indien de resetknop ingedrukt werd, hield het wiel op met draaien. De motorcontrol en tijdsbasis blokken zijn onaangepast overgenomen bij verdere opdrachten.
Hoofdstuk 5
Simpele lijnvolger 5.1
Eisen
Om de lijnvolger in de robot te kunnen gebruiken zal deze aan een aantal eisen moeten voldoen. Zo moeten signalen van de sensoren uitgelezen kunnen worden, waarop de lijnvolger een signaal naar de motorcontroller moet sturen om de robot vooruit, flauw- of scherp naar links of rechts te laten rijden.
5.2
Ontwerp
Het sensor-bord van de robot bestaat uit drie afzonderlijke licht-sensoren. Wanneer een sensor voldoende licht ziet -en zich dus niet boven de zwarte lijn bevindt- geeft deze ’1’ als output. De lijnvolger maakt uit de waardes van de drie signalen op waar de lijn is, en hoe de motoren aangestuurd moeten worden om op deze lijn te blijven.
5.3
Implementatie
De drie losse bit-signalen van de sensors worden in de inputbuffer gecombineerd en in twee 3-bit flipflops opgeslagen. Hierdoor wordt eventuele storing in het signaal weggefilterd. De lijnvolger leest de output van de tweede flipflop en vergelijkt dit met gegeven waardes. Als de meetwaarden in de tabel voorkomen stuurt de lijnvolger een signaal naar de motorcontroller over hoe beide motoren moeten draaien. Een ’1’ laat de Tabel 5.1
Links Zwart Zwart Zwart Zwart Wit Wit Wit Wit
Sensor Midden Zwart Zwart Wit Wit Zwart Zwart Wit Wit
Rechts Zwart Wit Zwart Wit Zwart Wit Zwart Wit 13
Motor Links Rechts Reset Reset Reset Vooruit Vooruit Vooruit Achteruit Vooruit Vooruit Reset Vooruit Vooruit Vooruit Achteruit Vooruit Vooruit
14
HOOFDSTUK 5. SIMPELE LIJNVOLGER
motor rechtsom draaien en een ’0’ linksom. Als het ’reset’ signaal voor een motor op ’1’ staat draait de motor niet. Aangezien de servomotoren andersom op de robot gemonteerd zijn moeten ze in tegengestelde richting draaien om de robot rechtdoor te laten rijden. Om te sturen wordt één motor aangedreven en één stilgezet, afhankelijk van de stuurrichting. Om een scherpe bocht te maken draaien beide wielen in tegensgestelde richting. Zie Table 5.1 De VHDL-code van de lijnvolger is te vinden in Appendix E.
5.4
Test
De lijnvolger werd getest door de robot op wit papier met een zwarte lijn te plaatsen. Hierbij werd gekeken hoe de robot op bochten in de lijn reageerde, en of deze alsnog gevolgt kon worden. Hierna werd een parkour gemaakt van zwarte isolatie-tape op een tafel om verschillende soorten bochten te testen; zoals cirkels, scherpe-, flauwe- en S-bochten. Al deze tests werden succesvol afgelegd.
5.5
Discussie
Tijdens de ontwikkeling van de lijnvolger zijn er geen grote problemen opgetreden. Alleen bleek bij het testen dat de motoraansturing voor scherpe- en flauwe bochten bij de verkeerde sensor waarden waren geplaatst, maar dat was met een kleine aanpassing in de code verholpen: De ’-S’ achter de state-naam werd veranderd in ’-F’, en andersom. De lijnvolger werkt nu naar behoren, en kan gebruikt worden bij de uitijndelijk aansturing van de robot.
Hoofdstuk 6
Draadloze Communicatie: XBee Module 6.1
Eisen
De robot moet uiteindelijk in staat zijn om draadloos met een pc te communiceren zodat de route kan worden doorgegeven, hiervoor worden twee XBee modules gebruikt. Eén bevestigt op de robot en één op de pc. De modules moeten aan elkaar gekoppeld worden zodat de communicatie plaats kan vinden en er moet een programma geschreven worden die de input van de routeplanner doorgeeft aan de robot.
6.2
Ontwerp
Voor de draadloze communicatie aan de kant van de robot moet er een UART (Universal Asynchronous Receiver/Transmitter) worden geïmplementeerd in de robot, deze zorgt voor het uitwisselen van informatie met de XBee op de robot. De XBee op de robot wisselt de informatie uit met de XBee die op de pc is aangesloten, deze XBee wisselt de informatie dan weer uit met het C-programma die de informatie van de routeplanner doorgeeft.
6.3
Implementatie
Via het programma X-CTU zijn de XBee modules aan elkaar gekoppeld. De modules moesten beide op hetzelfde kanaal worden ingesteld en het ontvangst adres van de één moest gelijk zijn aan het zend adres van de ander. De UART vhdl-code (zie Appendix E section E.1) werd ingeladen op de robot en via X-CTU kon er dan simpele communicatie plaatsvinden. De integratie van de XBee met de routevolger is te vinden in chapter 9.
6.4
Test
De simpele communicatie die mogelijk was via X-CTU bestond uit het sturen van één symbool tegelijk. Op de robot werd het symbool dan weergegeven in ASCII via de leds. Met de switches op de robot kon dan weer een ASCII code worden opgesteld en via een knop worden verzonden, deze werd dan weergegeven op de pc. 15
16
6.5
HOOFDSTUK 6. DRAADLOZE COMMUNICATIE: XBEE MODULE
Discussie
Er waren in het begin wat problemen met het programmeren van de UART op de robot. Telkens wanneer het programma op de robot gezet werd kwam er een melding voorbij die aangaf dat er gebruik gemaakt werd van een ander soort clock in het programma en de robot, een melding die we lang negeerde. Het programma deed vervolgens niets wanneer het op de robot stond. Na vele dingen vergeefs aan te passen aan de code toch maar de clock goed gezet, vervolgens wekte de UART, het had dus tijd bespaart om meteen de clock aan te passen.
Hoofdstuk 7
Mijndetector 7.1
Eisen
De eis die gesteld wordt aan de mijndetector is heel simpel: De mijndetector moet een metalen schijf kunnen detecteren en dit kenbaar maken aan de FPGA.
7.2
Ontwerp
Het ontwerp van de mijndetector zal bestaan uit twee grote onderdelen: Een ciruit om de mijn te detecteren, en een vhdl-code om dit ciruit uit te lezen en bruikbaar te maken. Het circuit zal zorgen voor een frequentieverandering zodra een mijn gevonden is. De code detecteert dan deze verandering en geeft door dat er een mijn is gevonden.
7.3 7.3.1
Implementatie Sensorcircuit
Voor het sensorcircuit wordt gebruik gemaakt van een zelf-oscillerende schakeling bestaande uit een LCciruit en een positief-teruggekoppelde opamp met terugekoppelweerstand. De oscillatiefrequentie van dit 1 circuit hangt af van de paralelle capaciteit- en inductantie combinatie volgens de formule ω0 = √L·C . Zodra een mijn vlakbij de spoel komt zal er een spiegel-inductantie ontstaan in de schijf, waardoor de spoel een grotere inductantie krijgt. Door deze toename in L zal de oscillatiefrequentie dan afnemen. het circuit is te zien in Figure 7.1
Figuur 7.1: De LC-oscillator.
17
18
HOOFDSTUK 7. MIJNDETECTOR
Het grote nadeel aan deze schakeling is dat er een blokgolf ontstaat met de aarde als evenwichtspunt, er is dus ook een negatieve spanning aanwezig. Het FPGA bord kan echter geen negatieve spanningen verwerken, en er zal dus er een manier gevonden moeten worden om een oscillatie te krijgen die niet onder nul volt gaat. De volgende schakeling zou daarvoor een oplossing moeten geven.
Figuur 7.2: De LC-oscillator aangepast voor gebruik.
Aangezien de beschikbare spanning bestaat uit vijf of nul volt zal het circuit daarmee aangestuurd moeten worden. Om deze reden is er gekozen voor de LM358N[3] opamp. Deze opamp kan goed werken met een bereik van nul tot vijf volt, in plaats van het gebruikelijke min vijf tot vijf volt. Beide bronnen zijn vijf volt. Om binnen dit bereik een goede oscillatie te krijgen moet de evenwichtsstand liggen op tweeënhalve volt. Dit wordt bereikt met de spanningsdeling van R1/R2 en R3/R4. C1 en C2 zijn aanwezig om de vijf volt DC spanning puur over de spanningsdeling te laten vallen. Voor de spoel werd gekozen voor een inductantie van 980µH omdat deze gemakkelijk onder de robot paste, en omdat de inductantie bij aanwezigheid van een mijn opliep tot 1050µH wat een goed meetbaar verschil is. Tevens was de breedte van de spoel ongeveer gelijk aan de breedte van een mijn, wat dus voor een optimaal gebruik van de oppervlakte zorgt. De paralelle capaciteit werd gekozen op 470nF omdat dit de grootste beschikbare waarde was voor een bipolaire condensator. Een grote waarde voor C versterkt het verschil in frequentie tussen mijn en geen mijn sterker. De bijbehorende simulatie (Figure 7.3) geeft aan dat er op deze manier een blokgolf moet ontstaan tussen de nul en drieënhalve volt. De vijf volt wordt niet bereikt vanwege de transistoren waaruit een opamp bestaat en de daarbij behorende drempelspanning.
7.3. IMPLEMENTATIE
19
Figuur 7.3: Simulatie bij de LC-oscillator.
Vanwege het niet functioneren van de schakeling (zie section 7.4) moest er een nieuwe schakeling worden bedacht die in theorie hetzelfde zou moeten werken. Deze schakeling lijkt veel meer op originele schakeling met de evenwichtsstand op nul volt.
Figuur 7.4: De LC-oscillator: versie twee.
De vijf volt bron aan de linkerkant wordt door een spanningsdeling op tweeënhalve volt gebracht en de spanningsvolger brengt dit aan op het LC-circuit en de negatieve ingang van de opamp. Nu zal de LC-oscillatie ook rond de tweeënhalve volt plaatsvinden.
20
HOOFDSTUK 7. MIJNDETECTOR
Figuur 7.5: Simulatie bij de LC-oscillator: versie twee.
De simulatie laat hier ook een blokgolf zien tussen de nul en drieënhalve volt met als enige verschil een duidelijk hogere frequentie. Deze schakeling werkt wel na in elkaar gesoldeerd te zijn.
7.3.2
Uitleescode
De mijndetector sensor, een inductieve metaaldetector, is als losstaand circuit niet bruikbaar. Het is goed en al om de aanwezigheid van een mijn te observeren als een frequentieverandering in een oscillerend circuit, maar om te zorgen dat de robot dit herkend als een mijn en dus niet doorrijdt is er een programma nodig om deze frequentieverandering uit te lezen. De eis voor dit systeem is als volgt: het systeem moet, zo gauw de periode van het sensorsignaal (een blokgolf) onder waarde x komt, een hoog signaal afgeven totdat de periode niet meer onder waarde x is. De manier waarop bij ons dit bereikt wordt is door een counter het aantal interne klokpulsen te laten tellen zolang het ingangssignaal van de sensor ’hoog’ is, waardoor het totaal aantal getelde pulsen omgerekend kan worden tot de lengte van een halve periode. Als het sensorsignaal ’laag’ is wordt aangegeven of dit aantal pulsen lager of hoger is dan de grenswaarde om een mijn te detecteren, en dit wordt vertaald naar een laag (geen mijn) of hoog (wel mijn) uitgangssignaal, dat wordt vastgehouden totdat de volgende halve periode geteld en vergeleken is. Het daadwerkelijke ontwerp van het programma is een Moore FSM met 6 states. Ten eerste zijn er 2 beginstates die het systeem kalibreren, door te wachten totdat er ten minste een lage halfperiode voorbij is gegaan voordat het systeem begint met het tellen van pulsen. Vervolgens switch het systeem met elke hoge en lage halfperiode van het sensorsignaal tussen 2 telstates en 2 detectiestates, zoals aangegeven in Figure 7.6.
7.4. TEST
21
Figuur 7.6: De FSM voor het uitleesprogramma van de inductieve mijnsensor
Als het aantal pulsen tijdens een halve periode kleiner is dan de bepaalde grenswaarde, krijgt de outputbit mijn de waarde 1, zo niet krijgt deze de waarde 0. Hiermee kan het sensorsignaal worden omgevormt tot een concreet antwoord ja of nee op de vraag ’ligt hier een mijn?’. De exacte code van het uitleescircuit staat in Appendix E section E.6.
7.4
Test
Om het effect van een aanwezige mijn zichtbaar te maken werd de sensor aan een oscilloscoop en 5-volts spanningsbron aangesloten. Het resultaat is te zien in Figure 7.7
22
HOOFDSTUK 7. MIJNDETECTOR
Figuur 7.7: Metingen met mijn (links) en zonder mijn (rechts):
Uit de metingen blijkt dat de frequentie zonder mijn 6,58 kilohertz, en met mijn 6,14 kilohertz bedraagt. De aanwezigheid van een mijn heeft dus een fequentieverlaging van 440 Hertz tot gevolg. Ook is te zien dat het signaal het meest stabiel is op de laagste waarden en dus precieser uitgelezen kan worden. Hierom werd besloten om de lage waarden te gebruiken om de periode uit te lezen in de FPGA-omplementatie. Aan de meting is verder te zien dat het signaal zonder mijn 62,5 µs, en met mijn 68,8 µs laag is. Dit geeft een verschil van 6,3 µs, wat met een interne klokfrequentie van 50Mhz op het FPGA overeenkomt met 312 klokpulsen. Een dergelijk verschil is goed meetbaar en dus afleidbaar naar de aan- of afwezigheid van een mijn.
7.5
Discussie
Ons oorspronkelijke idee voor de mijdetector was gebruik maken van het ’beat frequentie’ verschijnsel dat in veel commerciele metaaldetectors wordt toegepast. Het verschijnsel treed op wanneer twee signalen met een klein frequentieverschil bij elkaar worden gevoegd. Vanwege de verschillende frequenties versterken de signalen elkaar op sommige tijdstippen, en doven ze elkaar uit op anderen. Het resultaat is een periodieke verandering in amplitude van het gecombineerde signaal met als frequentie het verschil tussen de oorspronkelijke twee signalen, de beat frequentie. Om dit toe te passen zouden twee identieke oscillators gemaakt moeten worden waarvan één een wisselende frequentie heeft ten gevolge van een mijn. Deze sigalen zouden samengevoegd moeten worden, waarna vanuit de beat frequentie gemeten kan worden of er een mijn aanwezig is. Vanwege het overcomplexe ontwerp voor onze toepassing werd dit idee geschrapt. Het volgende model was gebaseerd op dat wat gebruikt werd in de JIT over inductieve sensoren, zie Figure 7.1 voor het oorspronkelijke circuit, en Figure 7.2 voor de aangepaste versie. Dit circuit werke goed in simulaties van zowel falstad als Pspice. Het creeërde een blokgolf die zichtbaar veranderde wanneer de inductantie van de spoel veranderde, en zou dus geschikt zijn om mijnen te detecteren. Nadat het circuit daadwerkelijk gemaakt was bleek dit in de praktijk echter niet het geval te zijn; het uitgangssignaal was een DC spanning van 3.6 Volt. Verwacht wordt dat dit veroorzaakt is door de manier waarop het terugkoppel netwerk is aangesloten aan aarde, waardoor het signaal verloren gaat en er geen oscillatie optreed. Het derde ontwerp is een verder aangepaste variant van dit circuit en wordt besproken in subsection 7.3.1 met een afbeelding in Figure 7.4 en meetresultaten in section 7.4. Dit ontwerp is uiteindelijk gekozen om op de robot gebruikt te worden. Ook dit cicruit wijkt echter af van de simulatiewaarden. Zo zit de frequentie zonder de mijn op 6,58KHz in tegenstelling tot de gesimuleerde waarde van 7,35KHz, en met de mijn op 6,14Khz in plaats van 7,10KHz. Verwacht wordt dat deze afwijkingen het gevolg zijn van metaal
7.5. DISCUSSIE
23
binnen het veld van de spoel: De mijn-sensor wordt doormiddel van een metalen schroef aan de robot opgehangen, hierdoor zal de inductantie van de spoel toenemen waardoor de oscillatiefrequentie afneemt 1 , net zoals wanneer er een mijn constant aanwezig zou zijn. Dit heeft echter een grotere volgens ω0 = √L·C verandering in frequentie tot gevolg wanneer er daadwerkelijk een mijn aanwezig is, en is dus gunstig voor het detecteren van mijnen. Hiernaast bevind de blokgolf zich in de praktijk tussen 0,68 en 3,72 Volt, en niet tussen de gesimuleerde 0,00 en 3,60 Volt. Deze afwijkingen worden veroorzaakt door het niet-ideale gedrag van de gebruikte opamps; de interne transistoren en weerstanden zorgen voor een zekere spanningsval en offset. Dit heeft verder echter geen effect op de analoog naar digitaal-omzetting van het FPGA bord, aangezien de lage en hoge spanningen nog steeds als logische 0 en 1 gezien worden. Dit laatste ontwerp is dus geschikt voor gebruik op de robot.
24
HOOFDSTUK 7. MIJNDETECTOR
Hoofdstuk 8
Routeplanner 8.1
Eisen
De eisen waaraan de routeplanner moet voldoen zijn af te leiden uit de challenges. De routeplanner zorgt er immers voor dat de robot tijdens de challenges weet welke route hij moet nemen. De routeplanner moet de korste weg tussen twee controleposten vinden die worden ingevoerd. Deze controleposten zijn de nummers 1 t/m 12 in Figure 2.1. Op het wedstrijdveld worden in de tweede challenge mijnen geplaatst. Het moet in de routeplanner mogelijk zijn om in te voeren waar de mijnen gedecteerd worden om vervolgens een nieuwe route te vinden. In de derde challenge moet het naast het invoeren van mijnen ook mogelijk zijn om aan te geven waar een schat ligt.
8.2
Ontwerp
Het belangrijkste onderdeel van het ontwerp is het te gebruiken algoritme. Wij hebben er voor gekozen om Dijkstra’s algoritme[1] te gebruiken. Dit algoritme is eenvoudig te implementeren, omdat we de basis er voor al hebben gehad bij het vak ’Programmeren in C’. In het ontwerp is het belangrijk om na te denken over de te gebruiken datastructuren. In onze routeplanner is gekozen om het wedstrijdveld weer te geven met de structs junction en road (zie Appendix B section B.3 en section B.5). Deze structuren gaven ons veel vrijheid om later nog iets aan te passen. Een belangrijk onderdeel van ons ontwerp is de indeling van de code in functies die onafhankelijk kunnen werken. Op deze manier wordt ervoor gezorgd dat code makkelijk te hergebruiken en herstructurenen is. Ook wordt vermeden dat code afhankelijk is van bijvoorbeeld één globale variabele in het ene bestand, waardoor die functie niet te gebruiken zou zijn in een ander bestand.
8.3
Implementatie
De volledige implementatie van de routeplanner is te vinden in Appendix B section B.2. Dijkstra’s algoritme is erg algemeen en kan werken met wegen van willekeurige lengtes. In het specifieke geval van het wedstrijdveld is er echter al bekend dat alle wegen dezelfde lengte hebben en is het door de rastervorm van het veld eenvoudig af te leiden welke wegen welke kruispunten met elkaar verbinden. In plaats van de datastructuren die beschreven worden in Bijlage E van [4] kan er gebruik gemaakt worden van een 5 × 5 matrix voor het representeren van de kruispunten, een 5 × 4 matrix voor het wegen in de x-richting en een 4 × 5 matrix voor de wegen in de y-richting. 25
26
HOOFDSTUK 8. ROUTEPLANNER
De routeplanner werkt als volgt. Eerst wordt de functie prepare_field aangeroepen om het wedstrijdveld te maken. Om dan de daadwerkelijke route berekenen wordt de functie shortest_route gebruikt. Deze functie geeft een linked list met de te volgen route terug. Allereerst wordt in deze functie bepaald van welk kruispunt naar welk kruispunt er gereisd moet worden: origin en destination. Aangezien men start in origin is de afstand naar dat punt nul. Vervolgens start hert daadwerkelijke algoritme, dat doorgaat totdat de route het eindpunt bereikt heeft. Als eerste wordt bepaald welk kruispunt op dat moment de kleinste afstand heeft, maar nog niet bezocht is. Het bezoeken van een kruispunt wordt bijgehouden in diens attribuut is_still_in_set, alle kruispunten die die nog in de set zitten zijn nog niet bezocht. Vervolgens worden vanuit dit kruispunt alle aangrenzende kruispunten nagelopen. Als blijkt dat de afstand die zo’n kruispunt heeft groter is dan de afstand tot het kleinste kruispunt plus de lengte van een weg (1), dan wordt dat de nieuwe afstand tot zo’n kruispunt. Tevens wordt dan bij zo’n kruispunt aangegeven dat het de kortste route is om naar het gevonden kleinste kruispunt te gaan. Als uiteindelijk de bestemming ook een afstand heeft gekregen gaat het programma door naar de volgende stap. Daarin wordt de lijst met de route gemaakt, waarbij wordt gestart bij het einde en er telkens een nieuwe node wordt toegevoegd aan het begin totdat met bij de oorsprong is gekomen. De laatste functie die men kan vinden in de routeplanner is block_road. Met deze functie is het mogelijk om een wegsegment te blokkeren, wat wordt gedaan wanneer er een mijn op dat wegsegment is gevonden. Deze geblokkeerde wegdelen worden vermeden door de routeplanner.
8.4
Test
Om de code te testen hebben wij verschillende start- en eindpunten opgegeven en gekeken of de code inderdaad de korste route vond. Toen dit werkte hebben wij wegen geblokkeerd en gekeken of de gevonden routes nog steeds klopten. Dit bleek zo te zijn.
8.5
Discussie
De routeplanner werkt naar behoren. Het is mogelijk om de korste route tussen twee punten uit te rekenen. Ook is het mogelijk om wegen te blokkeren en die te vermijden.
Hoofdstuk 9
Routevolger 9.1
Eisen
De routevolger moet in staat zijn om de robot bij elke kruising aan te geven wat hij moet doen. Dit houdt in dat de routevolger in staat moet zijn om te communiceren tussen de robot en de computer. Om dit te bereiken moet de routevolger in staat zijn om de route te ontvangen van de routeplanner, bij elk kruispunt te berekenen of en hoe de robot moet draaien om de route te volgen, de positie van de robot terug te geven aan de computer en deze informatie te verwerken.
9.2
Ontwerp
Het ontwerp voor de routevolger bestaat uit twee delen. Een deel wordt uitgevoerd als C-programma op de computer, een deel wordt geïntegreerd in de controller van de robot. Het deel in de controller bepaald wanneer de robot externe instructies vanaf de pc moet volgen, of wanneer de robot gewoon zijn normale lijnvolgen moet doen. Het deel op de de pc voert de overige taken van de routevolger uit. Dit staat beschreven in Appendix B section B.1.
9.3
Implementatie
De volledige implementatie van de routevolger is te vinden in Appendix B section B.1. De basis van de routevolger is een programma gericht op het aflopen van de array dat het c-programma in de routeplanner gemaakt heeft. Elke keer dat de robot bij een kruising is, houdt hij stil en springt hij in de state XBEE_lezen. Dan communiceert hij via de XBEE met de computer en kijkt de routevolger een stapje verder in de array. Vervolgens vergelijkt het c-programma dan twee verschillende paren coördinaten. Het eerste paar coördinaten is het paar dat in de array opgeslagen staat. Deze geven aan naar welk kruispunt de robot heen moet. Het programma loopt in bij het ophalen van deze coördinaten dus eigenlijk een kruispunt voor. Het tweede paar coördinaten geeft aan waar de robot zich op dat moment bevind. Dit paar wordt acief door het c-programma bijgehouden. Dit gebeurd door bij elk kruispunt de x of y coördinaat met 1 te verhogen of te verlagen. Daarnaast is te zien dat het programma nog een zogenaamde ’orientation’ bijhoudt. Deze integer houd bij hoe de robot gedraaid staat. Deze integer is een resultaat van een vergelijking tussen de twee hiervoor genoemde coördinaten paren. Deze vergelijkingen worden gemaakt in case statements. Deze case statements geven de integer orientation de waarde 0, 1, 3 door. Deze waardes staan voor respectievelijk voor rechtdoor, rechts en links. Dit wordt vervolgens via de XBEE-console naar de robot gestuurd in de vormr 27
28
HOOFDSTUK 9. ROUTEVOLGER
van een (3 bits grote) bit-reeks. Daarnaast zorgen deze waarden er ook voor dat de coördinaten van de robot bijgewerkt worden. De Robot staat op het moment van het ontvangen nog stil op het kruispunt. Wanneer hij de drie bits binnen krijgt, verlaat hij de state ’XBEE_lezen’ en gaat hij naar de state aangegeven door de 3 bits. Vervolgens schakelt hij na 900 ms over naar de lijnvolger. De lijnvolger blijft dan in gebruik totdat de 3 lichtsensoren weer allemaal zwart zien, waarna dit herhaald wordt. Voor de challenge is het nodig dat de robot drie punten kan bezoeken, niet slechts één. Om dit te bereiken wordt de serie van handelingen die nodig zijn om de robot naar een bestemming te sturen in een loop gezet, die zich herhaald totdat alle posten zijn bezocht. Eén cyclus ziet er dus als volgt uit: de route wordt berekend => de robot krijgt bij elk kruispunt dat hij tegenkomt de benodigde instructie totdat de bestemming is bereikt => indien nodig keert de robot zich om, om aan een nieuwe cyclus te kunnen beginnen. Wanneer de robot een mijn tegenkomt stuurt hij dit door naar het C-programma. Daarin wordt dan, aan de hand van de huidige positie van de robot en diens oriëntatie, de juiste weg als geblokkeerd gemarkeerd. Vervolgens wordt naar de robot een signaal gestuurd dat deze moet keren. Wanneer de robot gekeerd is begint de robot opnieuw aan de cyclus van route berekenen en rijden. Tijdens het programma wordt veelvuldig gebruik gemaakt van de functie sleep. Deze functie ’pauzeert’ het c-programma. Deze functie zorgt er hierdoor voor dat het c-programma geen nieuwe signalen naar de robot verstuurd. De robot blijft vervolgens in zijn huidige state en gaat door met de handeling waarmee hij bezig was. Op deze manier is het mogelijk om de bochten handmatig in te stellen. Dit is echter niet de enige manier waarop de functie sleep ingezet is. De functie komt namelijk ook van pas om voor zekerheid te zorgen. Bijvoorbeeld is de functie gebruikt bij de communicatie met de Zigbee, om er zeker van te zijn dat de verstuurde bits verwerkt zijn.
9.4
Test
Het testen van de routevolger hebben wij vooral in de praktijk gedaan. Zowel handmatig als op het wedstrijdveld hebben wij het gedrag van de robot geanalyseerd. Om een grondige analyse te kunnen maken zorgden we voor enkele afleessystemen. Zo lieten we de robot op (cijferdisplay) de state weergeven waarin hij verkeerde. Om de uitwisseling van de XBEE te kunnen controleren lieten we het c-programma de de sensor-waardes weergeven als deze veranderden. Ook lieten we de robot via de ledjes weergeven welke bits hij van de computer doorgestuurd kreeg.
9.5
Discussie
Tijdens deze test stuitten wij op enkele problemen. Het eerste probleem was dat de vlakken tussen de kruisingen ook als kruispunten werden gezien. Dit probleem was echter snel opgelost door een variabele i bij te houden en daarmee om-en-om een kruispunt wel en niet als zodanig te registreren. Toen waren de problemen echter nog niet allemaal weg. Zo leek de robot het daarna goed te doen, maar steeds kwam hij een kruispunt te ver uit. Dit bleek te liggen aan het feit dat we een verkeerde volgorde aanhingen. Hierdoor liep de robot een stap achter. Nadat dat aangepast was liepen we nog tegen enkele kleinere problemen aan. Zo leek de robot niet alle kruisingen en tussenpunten te zien en onverwachts af te slaan. Na de sensoren met de hand bedekt te hebben en zo het veld te simuleren bleek dat het programma het op zich goed deed. Om de robot ook in de robot ook in de praktijk te laten werken, hebben we het programma zo aangepast dat de robot de bocht zo zou maken dat hij op een rechtere manier het midden van het baanstuk zou naderen, en op die manier een kleinere kans zou hebben om het tussenpunt te missen.
Hoofdstuk 10
Integratie van de Subsystemen 10.1
Toplevel
Met de VHDL bestanden die geprogrammeerd zijn moet de aansturing van de robot uiteindelijk in elkaar gezet worden, om optimale samenwerking tussen de verschillende onderdelen te bereiken. Hiervoor zijn de Toplevel, Robot en UART vhdl codes geschreven. De Robot code is het overzicht voor alle fysieke aansturingen van de robot, dus de timebase, de uitlezing van de mijn- en lijnvolgersensors, de lijnvolger en de linker en rechter motoraansturing. De UART overziet de communicatie met de laptop mbv de ZigBee module, en bevat de Baud rate generator, de inkomende en uitgaande bitstreams en de uitleesbuffers. De toplevel brengt vervolgens de UART en Robot samen zodat het geheel een werkende robotaansturing met actieve communicatie met de laptop is. De uiteindelijke samenhang van de .vhdl codes is te zien in Appendix A
10.2
FPGA controller
De vhdl bestanden worden met behulp van de Xilinx ISE Design Studio gesynthetiseerd voor de FPGA. De synthetisatie geeft gelijk een uitgebreidt overzicht van de vereisten van de software voor de FPGA en het aantal logische en i/o poorten dat gebruikt wordt. Als de VHDL-code is gesynthetiseerd voor de FPGA is te zien hoeveel resources van de FPGA zijn gebruikt. Dit staat in Figure 10.1. Het gebruik is overal rond de 4%, met uitzondering van de IOB’s, welke de gebruikte IO-poorten zijn.
Figuur 10.1: FPGA resources utilization
29
30
10.3
HOOFDSTUK 10. INTEGRATIE VAN DE SUBSYSTEMEN
Console aansturing
Voor de twee challenges die wij uitvoeren, namelijk de eerste en tweede, wordt hetzelfde C-programma gebruikt. In dit C-programma is in te voeren hoeveel controleposten er bezocht moeten worden (in beide gevallen 3) en welke posten dit zijn. Vervolgens wordt de route berekend en wordt er daarna vrijwel constant gecommuniceerd met de robot. Hierover is meer te lezen in de hoofdstukken Routevolger en Routeplanner.
Hoofdstuk 11
Testen van de Robot 11.1
Testplan
Om te kijken of alles naar behoren werkt moeten er een aantal tests worden uitgevoerd. Bepaalde delen worden eerst afzonderlijk getest zodat fouten in de losse onderdelen snel opgelost kunnen worden. Daarna worden delen bij elkaar gevoegd en opnieuw getest om uiteindelijk als laatste de gehele robot te testen. De tests zijn alsvolgt opgedeeld: • Lijnvolger
(11.2.1)
• Draadloze communicatie
(11.2.2)
• ’Challenge 1’
(11.2.3)
• Mijnendetector
(11.2.4)
• ’Challenge 2’
(11.2.5)
11.2
Testresultaten
11.2.1
Lijnvolger
Om de lijnvolger te testen wordt eerst een zwarte lijn getekent op wit papier. De robot wordt dan met zijn middelste sensor op de lijn geplaatst en aangezet. Te zien was dat de robot zichzelf corrigeerde door terug naar de lijn te sturen wanneer een van de buitenste sensoren de zwarte lijn zag. Op deze manier kon de robot eenvoudig de lijn volgen. De lijnvolger is dus een succes.
11.2.2
Draadloze communicatie
Om te testen of de communicatie goed verloopt wordt de vhdl-code aangepast zodat constant de uitgang van de lichtsensoren wordt doorgegeven naar de pc. Bij een verandering in de sensoren was goed te zien dat de communicatie van de robot naar de pc goed werkt, de sensorwaarden die doorkwamen waren altijd correct. De test van de pc naar de robot hield in dat de pc een richting doorgaf waar de robot heen zou moeten rijden. De wielen van de robot draaiden de juiste kant op bij alle commando’s dus dat werkt ook goed. 31
32
11.2.3
HOOFDSTUK 11. TESTEN VAN DE ROBOT
’Challenge 1’
Om te kijken of de routevolger, en dus de eerste challenge, haalbaar is werd de robot op het wedstrijdveld geplaatst en werd er verbinding gemaakt met de routplanner. Via de pc werden punten ingevoerd waar de robot naartoe moet rijden en uiteindelijk moest de robot stoppen bij het laatste punt. Het rijden van de beoogde route werkt volgens plan met als mankement dat indien een bocht te vroeg werd ingezet, de lichtsensoren de plek waar een mijn kan liggen niet goed oppakt en bij het volgende kruispunt geen eventuele afslag maakt en bij de volgende mijnplek een bocht gaat draaien.
11.2.4
Mijnendetector
Om te kijken of de mijnendetector werkt moet er naar twee dingen gekeken worden: is er een verandering in frequentie indien er een mijn aanwezig is, en of de vhdl-code doorgeeft dat er dan een mijn aanwezig is. Om het eerste te testen werd de detector aangesloten op een oscilloscoop en is er gekeken naar de golf met en zonder een mijn bij de spoel. Voor het tweede deel is er een ledje van de FPGA als output toegevoegd zodat deze gaat branden indien een mijn gevonden wordt. Zoals al eerder te zien was in Figure 7.7 is er een duidelijk frequentieverschil zichtbaar op de oscilloscoop, dus het sensorcircuit werkt naar behoren. Bij het testen van de output van de vhdl-code ging niet alles zoals verwacht. Indien een mijn bij de spoel in de buurt kwam ging inderdaad het ledje branden, maar wanneer er geen mijn in de buurt was knipperde het ledje in plaats van dat het constant uit was. Op de pc was ook duidelijk te zien dat wanneer er geen mijn was er constant wel en geen mijn om en om werd doorgegeven.
11.2.5
’Challenge 2’
Als laatste moest de mijnendetector geïntegreerd worden met de rest van de robot zodat de tweede challenge gehaald kan worden. De test is vergelijkbaar met de eerste challenge alleen nu zijn er mijnen op de route gelegd. Zoals verwacht rijdt de robot de route die afgelegd moet worden, alleen wanneer een mijn gedetecteerd wordt stopt de routeplanner met instructies en blijft de robot hangen in de laatste instructie.
11.3
Vergelijking gewenste en bereikte systeemspecificaties
Bijna alle acties die de robot zou moeten kunnen doen, doet hij ook. Het punt waar de robot te kort schiet is wanneer er mijnen bij komen. De detector knippert continu wanneer er geen mijn is (een oplossing hiervoor is gegeven in chapter 12) en wanneer er wel een mijn is loopt de routeplanner vast.
Hoofdstuk 12
Discussie De test van de robot liet wat zwakke punten zien van de robot wat betreft de challenges. De eerste challenge kreeg als tegenvaller dat de plekken waar mijnen zouden kunnen liggen niet gezien werden door de lichtsensoren, daardoor klopt de route die de robot aflegt niet meer. Om dit probleem te verhelpen is er een vertraging ingesteld bij het maken van een bocht, zodra de robot bij een kruising aankomt zal de robot een klein stukje verder rijden voordat hij aan de bocht begint. Op deze manier rijdt de robot sneller recht op het volgende stuk en rijdt de robot dus goed over de mijn-plekken. Naast het probleem van de bochten was er ook een probleem met de mijndetector. Het detecteren van een mijn werkt naar behoren, maar indien er geen mijn aanwezig is blijft de detectoruitgang niet nul, maar gaat hij knipperen tussen nul en één. Nooit twee keer achter elkaar hetzelfde maar continu nul-één-nul-één. Deze fout moet ergens in de vhdl-code zitten van de detector. In plaats van het zoeken en verwijderen van de fout in de code is het C-programma aangepast op deze fout. Nu wordt er pas aangegeven dat er een mijn is wanneer het C-programma meer dan tien keer achter elkaar een één gestuurd krijgt van de mijnendetector, dit maakt het knipperen ongedaan binnen de routeplanner. Het probleem met de vastlopende routeplanner wanneer er een mijn gevonden is, is bij het schrijven van dit rapport nog niet opgelost. De C-code is aan een hevige inspectie onderworpen maar een uitweg in dit probleem is niet gevonden.
33
34
HOOFDSTUK 12. DISCUSSIE
Hoofdstuk 13
Conclusies en Aanbevelingen Aan de voor het eerste kwartaal gestelde eisen is voldaan: De robot kan succesvol een zwarte lijn volgen. Verder kunnen zowel flauwe als scherpe bochten gemaakt worden, waardoor ook niet-rechte lijnen probleemloos gevolgt kunnen worden. Daarnaast kan de robot via de Xbee-module draadloos met een computer communiceren, en kan deze ook doormiddel van keyboard-inputs op afstand bestuurd worden. Ook aan de voor het tweede kwartaal gestelde eisen is grotendeels voldaan: De vereiste routeplanner die de robot draadloos het kortste pad van punt A naar B moet laten rijden is gemaakt en werkt. Ook de noodzakelijke mijndetectie-hardware is succesvol ontwikkeld en voldoet aan de gestelde eisen. Het FPGA-bord kan zien wanneer er een mijn aanwezig is, en dit draadloos doorgeven aan de routeplanner. De routeplanner software zelf heeft echter nog een probleem waardoor er nog niet goed op mijnen kan worden gereageerd. All overige randvoorwaarden zijn niet overschreden; de robot past in een doos van 30x25x20 cm, alleen C en VHDL zijn gebruikt bij het programmeren, hij is volledig elktronisch aangedreven en veroorzaakt geen schade aan het veld.
35
36
HOOFDSTUK 13. CONCLUSIES EN AANBEVELINGEN
Hoofdstuk 14
Reflectie op de Groepsproces 14.1
Afspraken
Tijdens dit project, dat twee kwartalen duurde, hebben wij in een groep gewerkt. Als samenwerken heeft veel voordelen. Zo is de kennis altijd verspreid en zijn er altijd mensen waar je op kan terug vallen als je zelf niet meer verder komt. Echter, om de samenwerking in goede banen te leiden zijn er wel afspraken gemaakt.
14.1.1
Communicatie
Wat betreft de communicatie hebben we afgesproken dat alle communicatie via de mobiele app ’WhattsApp’ gaat. Hierdoor is in principe iedereen altijd te bereiken. Wat betreft de communicatie met de begeleiders is afgesproken dat zij tijdens het project altijd aanwezig zijn. Buiten de projecturen zijn zij via de mail te bereiken.
14.1.2
Opslag
De opslag van alle belangrijke documenten geschied via het medium Dropbox. Daarnaast wordt het ontwerpverslag op de website www.writelatex.com altijd online en beschikbaar gehouden. Hierdoor kunnen delen van het verslag elk moment gemaakt worden. Bovendien kunnen zo meerdere mensen tegelijk aan het ontwerprapport werken.
14.1.3
Rolverdeling
Besloten is om alle opdrachten in kleinere groepen te maken. Zo kunnen er meerdere opdrachten gelijk worden gemaakt, terwijl de kennis toch verspreid wordt. Daarnaast moet iedereen buiten de projecttijd doorkijken wat de andere groep tijdens de projecturen heeft gedaan. Verder hebben wij ervoor gekozen een vaste voorzitter te kiezen. Deze voorzitter moet het werk van alle leden bijhouden en zorgen dat iedereen genoeg bijdraagt aan het project. Door één voorzitter te kiezen hopen we dat beslissingen sneller en beter kunnen worden genomen. Na overleg hebben we besloten dat Joran Out de voorzitter gedurende dit project wordt. Voor eventuele notulen zal ter plekke een notulist worden aangewezen. 37
38
14.2
HOOFDSTUK 14. REFLECTIE OP DE GROEPSPROCES
Groepsproces
Tijdens dit project hebben we als groep goed samengewerkt. De sfeer die heerste in de projecturen was goed en gezellig. Er werd hard doorgewerkt, maar er was ook altijd tijd om elkaar te helpen. Wat hierbij erg hielp is het feit dat iedereen van alles wat afwist. Soms liep een groep tijdens een opdracht vast, en dan was het goed dat de andere groep een verse blik kon werpen op het probleem. Over het algemeen is te zeggen dat het groepsproces heel aangenaam was voor iedereen in de groep.
14.3
Opmerkingen
Zoals met elk project waren er in dit project ook momenten dat bij ons één wenkbrauw omhoog ging. Deze momenten hebben we hier aangegeven. Het eerste vraagtekens zetten wij bij het maken van deel ’Niet-lineaire schakeling’. Dit deel wordt behalve in de planning niet in dit rapport genoemd. Dit komt omdat wij voor dit deel geen verband met het project zagen. Dit betreurden wij, aangezien de opdracht veel tijd kostte. Daarnaast zijn wij van mening dat één wedstrijdveld voor alle groepen eigenlijk te weinig is. In het begin van het project is het nog goed te doen om te testen op één veld. Echter aan het einde van het project werd het steeds drukker rond het veld en hadden de groepen ook steeds meer van het veld nodig om hun robot uit te testen.
Bibliografie [1] Dijkstra’s kortste pad algoritme. http://nl.wikipedia.org/wiki/Kortstepadalgoritme. [2] M. Bartek, J. Bastemeijer, A.J. van Genderen, A.C. de Graaf, J. Hoekstra, B. Jacobs, M. Pertijs, X. van Rijnsoever, en A.M.J. Slats: Smart Robot Challenge Practicum Handleiding. Delft University of Technology, 2013. [3] Texas Instruments: Datasheet LM158/LM258/LM358/LM2904 Low Power Dual Operational Amplifiers. http://www.ti.com/lit/ds/symlink/lm358-n.pdf. [4] B. Jacobs, X. van Rijnsoever, en A. J. van Genderen: Practicum Handleiding Programmeren in C. TU Delft, The Netherlands, 2013.
39
40
BIBLIOGRAFIE
Bijlage A
RTL Schematic
41
toplevel:1
robot:2
or2 reset_sw
I1
reset_btn
I0
O
timebase
reset_imp_reset1
controller
clk
clk
count_out(31:0)
reset
count_in(31:0)
an(3:0)
an(3:0)
an(3:0)
xbee_received(7:0)
led(7:0)
led(7:0)
led(7:0)
sseg(7:0)
sseg(7:0)
sseg(7:0)
mine
xbee_send(7:0)
xbee_send(7:0)
reset
count_reset
clk
timeb
sensor_l
motor_l_direction
sensor_m
motor_l_reset
sensor_r
motor_r_direction motor_r_reset
contr xbee_received(7:0)
mijnsensor clk
sensor_mijn
motor_controller count_in(31:0)
mijn
reset
reset
clk
sensor_mijn
sensor
direction
pwm
motor_left
motor_left
motor_right
motor_right
reset
mines motor_l inputbuffer clk
motor_controller count_in(31:0)
sensor_l_out
reset sensor_l
sensor_l
sensor_l_in
sensor_m
sensor_m
sensor_m_in
sensor_r
sensor_r
sensor_r_in
pwm
clk sensor_m_out
direction reset
sensor_r_out
motor_r input
vcc write_data
P
XST_VCC read_data
RBT clk
uart:2 buf_reg xbee_send(7:0)
din(7:0)
clk
clk
uart_tx dout(7:0)
din(7:0)
clk clr_flag
clr_flag
reset
reset
s_tick
write_data
set_flag
tx_done_tick
TRM
xbee_received(7:0)
set_flag
flag
RCB
tx
read_data
baud_gen clk
s_tick
reset
BG
uart_rx clk
dout(7:0)
reset rx
dout(7:0)
reset
tx_start
TRB
rx
din(7:0)
clk
reset
flag
buf_reg tx
rx s_tick
rx_done_tick
RCV XBEE toplevel
tx
Bijlage B
C broncode bestanden B.1 1 2 3 4
# include # include # include # include
main.c < s t d i o . h> < s t d l i b . h> <Windows . h> < s t r i n g . h>
5 6 7
# include " robot . h" # include " s a l l o c . h"
8 9 10
# d e f i n e COMPORT "COM3" # d e f i n e BAUDRATE 9600
11 12
char l a s t R e a d ;
13 14 15 16 17 18
s t r u c t node { int x ; int y ; s t r u c t node ∗ n e x t ; };
19 20
void p r e p a r e _ f i e l d ( ) ;
21 22
void p r e p a r e _ r o a d s ( ) ;
23 24
s t r u c t node ∗ s h o r t e s t _ r o u t e ( i n t , i n t , i n t , i n t ) ;
25 26
void block_road ( int , int , i n t ) ;
27 28 29 30 31 32 33 34
/ /−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− / / Function : i n i t S i o / / D e s c r i p t i o n : i n t i a l i z e s t h e parameters as Baudrate , B y t e s i z e , // S t o p b i t s , P a r i t y and T i m e o u t p a r a m e t e r s o f // t h e COM p o r t / /−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− v o i d i n i t S i o (HANDLE h S e r i a l ) {
35 36 37
COMMTIMEOUTS t i m e o u t s = { 0 } ; DCB d c b S e r i a l P a r a m s = { 0 } ;
38 39
d c b S e r i a l P a r a m s . DCBlength = s i z e o f ( d c b S e r i a l P a r a m s ) ;
40 41 42 43 44
i f ( ! GetCommState ( h S e r i a l , &d c b S e r i a l P a r a m s ) ) { / / error getting state p r i n t f ( " error getting s t a t e \ n" ) ; }
45 46 47 48
d c b S e r i a l P a r a m s . BaudRate = BAUDRATE; dcbSerialParams . ByteSize = 8; d c b S e r i a l P a r a m s . S t o p B i t s = ONESTOPBIT ;
43
44
BIJLAGE B. C BRONCODE BESTANDEN d c b S e r i a l P a r a m s . P a r i t y = NOPARITY ;
49 50
i f ( ! SetCommState ( h S e r i a l , &d c b S e r i a l P a r a m s ) ) { / / error s e t t i n g serial port state p r i n t f ( " error s e t t i n g s t a t e \ n" ) ; }
51 52 53 54 55
timeouts . ReadIntervalTimeout = 50; timeouts . ReadTotalTimeoutConstant = 50; timeouts . ReadTotalTimeoutMultiplier = 10;
56 57 58 59
timeouts . WriteTotalTimeoutConstant = 50; timeouts . WriteTotalTimeoutMultiplier = 10;
60 61 62
i f ( ! SetCommTimeouts ( h S e r i a l , &t i m e o u t s ) ) { / / error occureed . Inform user p r i n t f ( " error s e t t i n g timeout s t a t e \ n" ) ; }
63 64 65 66 67
}
68 69 70 71 72 73 74 75 76
/ /−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− / / Function : readByte / / D e s c r i p t i o n : r e a d s a s i n g l e b y t e f r o m t h e COM p o r t i n t o // b u f f e r buffRead / /−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− i n t r e a d B y t e (HANDLE h S e r i a l , char ∗ b u f f R e a d ) { DWORD dwBytesRead = 0 ; i n t pow ;
77
i f ( ! R e a d F i l e ( h S e r i a l , b u f f R e a d , 1 , &dwBytesRead , NULL) ) { p r i n t f ( " e r r o r r e a d i n g b y t e from i n p u t b u f f e r \ n " ) ; } i f ( l a s t R e a d != buffRead [ 0 ] ) { p r i n t f ( " Sensors : " ) ; p r i n t f ( "%d " , b u f f R e a d [ 0 ] & 8 ? 1 : 0 ) ; f o r ( pow = 4 ; pow ; pow = pow >> 1 ) { p r i n t f ( "%d " , b u f f R e a d [ 0 ] & pow ? 1 : 0 ) ; } p r i n t f ( " (%d ) (%d b y t e s r e a d ) \ n " , b u f f R e a d [ 0 ] , dwBytesRead ) ; } lastRead = buffRead [ 0 ] ; return ( 0 ) ;
78 79 80 81 82 83 84 85 86 87 88 89 90 91
}
92 93 94 95 96 97 98 99
/ /−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− / / Function : writeByte / / Description : writes a s i n g l e byte stored in buffRead to // t h e COM p o r t / /−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− i n t w r i t e B y t e (HANDLE h S e r i a l , i n t num ) { DWORD d w B y t e s W r i t t e n = 0 ;
100
i f ( ! W r i t e F i l e ( h S e r i a l , ( char ∗ ) (&num ) , 1 , &d w B y t e s W r i t t e n , NULL) ) { p r i n t f ( " e r r o r writing byte to output buffer \ n" ) ; } p r i n t f ( " B y t e w r i t t e n t o w r i t e b u f f e r i s : %d \ n " , num ) ;
101 102 103 104 105
return ( 0 ) ;
106 107
}
108 109 110 111 112 113 114 115 116 117 118 119 120 121
int g e t _ d i r e c t i o n ( int orig_x , int orig_y , int dest_x , int dest_y , int o r i e n t a t i o n ) { switch ( o r i e n t a t i o n ) { case 0: i f ( d e s t _ x == o r i g _ x ) return 0; else i f ( dest_x < orig_x ) return 3; else i f ( dest_x > orig_x ) return 1; else return 0; break ; case 1:
B.1. C PROGRAM MAIN.C i f ( d e s t _ y == o r i g _ y ) return 0; else i f ( dest_y > orig_y ) return 3; else i f ( dest_y < orig_y ) return 1; else return 0; break ;
122 123 124 125 126 127 128 129 130
case 2:
131
i f ( d e s t _ x == o r i g _ x ) return 0; else i f ( dest_x > orig_x ) return 3; else i f ( dest_x < orig_x ) return 1; else return 0; break ;
132 133 134 135 136 137 138 139 140
case 3:
141
i f ( d e s t _ y == o r i g _ y ) return 0; else i f ( dest_y < orig_y ) return 3; else i f ( dest_y > orig_y ) return 1; else return 0; break ;
142 143 144 145 146 147 148 149 150
} return 0;
151 152 153
}
154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
v o i d s e t _ p o s i t i o n ( Robot ∗ r o b o t ) { s w i t c h ( r o b o t −> o r i e n t a t i o n ) { case 0: r o b o t −>y ++; break ; case 1: r o b o t −>x ++; break ; case 2: r o b o t −>y−−; break ; case 3: r o b o t −>x−−; break ; } }
171 172 173 174 175 176 177 178
i n t main ( ) { int j , n ; int waitingTime = 300; s t r u c t node ∗ r , ∗ r o u t e = s a f e _ m a l l o c ( s i z e o f ( s t r u c t node ) ) ; Robot ∗ r o b o t = n e w _ r o b o t ( 1 , 0 , 0 ) ; HANDLE h S e r i a l ; char l a s t , b y t e B u f f e r [ BUFSIZ + 1 ] ;
179 180 181 182
prepare_roads () ; i n t bases_x [ ] = {1 , 2 , 3 , 4 , 4 , 4 , 3 , 2 , 1 , 0 , 0 , 0}; i n t bases_y [ ] = {0 , 0 , 0 , 1 , 2 , 3 , 4 , 4 , 4 , 3 , 2 , 1};
183 184 185 186 187 188 189 190
p r i n t f ( " Amount o f b a s e s : " ) ; s c a n f ( "%d " , &n ) ; int destinations [n ]; printf ( " Destinations : " ) ; f o r ( j = 0 ; j < n ; j ++) { s c a n f ( "%d " , &d e s t i n a t i o n s [ j ] ) ; }
191 192 193 194
/ /−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− / / Open COMPORT f o r r e a d i n g and w r i t i n g / /−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
45
46 195 196 197 198
BIJLAGE B. C BRONCODE BESTANDEN h S e r i a l = C r e a t e F i l e (COMPORT, GENERIC_READ | GENERIC_WRITE , 0 , 0 , OPEN_EXISTING , FILE_ATTRIBUTE_NORMAL , 0 ) ;
199 200 201 202 203 204 205 206 207
i f ( h S e r i a l == INVALID_HANDLE_VALUE ) { i f ( G e t L a s t E r r o r ( ) == ERROR_FILE_NOT_FOUND ) { / / s e r i a l p or t does not e x i s t . Inform user . p r i n t f ( " s e r i a l p o r t does not e x i s t \ n" ) ; } / / some o t h e r e r r o r o c c u r r e d . I n f o r m u s e r . p r i n t f ( " some o t h e r e r r o r o c c u r e d . I n f o r m u s e r . \ n " ) ; }
208 209 210 211 212
/ /−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− / / I n i t i a l i z e t h e p a r a m e t e r s o f t h e COM p o r t / /−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− initSio ( hSerial ) ;
213 214 215 216 217
/ / V a l u e s t o s e n d t o t h e r o b o t , d e p e n d i n g on t h e d i r e c t i o n t h a t i s n e e d e d t o t u r n : / / 0 : go s t r a i g h t ahead , 1 : t u r n r i g h t , 2 : go backwards , 3 : t u r n l e f t i n t d i r e c t i o n s [ 4 ] = {0 b101 , 0 b011 , 0 b010 , 0 b110 } ; char speak_cmd [ 2 8 ] , ∗ s p e a k _ c h o i c e s [ ] = { "Go s t r a i g h t a h e a d " , " Turn : r i g h t " , "Go b a c k w a r d s " , " Turn : l e f t " } ;
218 219 220 221 222 223
for ( j = 0; int int int int
j < n ; j ++) { d, i ; o r i g _ x = r o b o t −>x , o r i g _ y = r o b o t −>y ; dest_x = bases_x [ d e s t i n a t i o n s [ j ] − 1] , dest_y = bases_y [ d e s t i n a t i o n s [ j ] − 1 ] ; sensors , mine_sensor , minecount = 0;
224 225 226 227 228
prepare_field () ; route = s h o r t e s t _ r o u t e ( orig_x , orig_y , dest_x , dest_y ) ; f o r ( r = r o u t e ; r −> n e x t ; r = r −> n e x t ) p r i n t f ( "%d ,%d \ n " , r −>x , r −>y ) ;
229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258
i = 1; writeByte ( hSerial , 0) ; while ( 1 ) { readByte ( hSerial , byteBuffer ) ; mine_sensor = byteBuffer [0] & 8 ? 1 : 0; s e n s o r s = b y t e B u f f e r [ 0 ] & 0 b0111 ; i f ( m i n e _ s e n s o r == 1 ) { m i n e c o u n t ++; i f ( m i n e c o u n t == 2 ) { p r i n t f ( "MINE ! ! ! %d ,%d \ n " , r o b o t −>x , r o b o t −>y ) ; popen ( " Say . e x e MINE ! " , " r " ) ; b l o c k _ r o a d ( r o b o t −>x , r o b o t −>y , ( r o b o t −> o r i e n t a t i o n + 2 ) % 4 ) ; p r i n t f ( " s e n s %d \ n " , s e n s o r s ) ; w r i t e B y t e ( h S e r i a l , 0 b110 ) ; / / Turn u n t i l p a t h i s f o u n d do readByte ( hSerial , byteBuffer ) ; w h i l e ( ( b y t e B u f f e r [ 0 ] & 0 b0111 ) ! = 0 b110 ) ; r o b o t −> o r i e n t a t i o n = ( r o b o t −> o r i e n t a t i o n + 2 ) % 4 ; set_position ( robot ) ; break ; } } else { minecount = 0; } i f ( s e n s o r s == 0 && l a s t ! = 0 ) { i f ( i % 2) { p r i n t f ( "%d ,%d %d \ n " , r o b o t −>x , r o b o t −>y , r o b o t −> o r i e n t a t i o n ) ; i f ( r o b o t −>x == d e s t _ x && r o b o t −>y == d e s t _ y ) break ;
259 260 261
d = g e t _ d i r e c t i o n ( r o b o t −>x , r o b o t −>y , r o u t e −>x , r o u t e −>y , r o b o t −> o r i e n t a t i o n ) ; r o b o t −> o r i e n t a t i o n = ( r o b o t −> o r i e n t a t i o n + d ) % 4 ;
262 263 264
s p r i n t f ( speak_cmd , " Say . e x e %s " , s p e a k _ c h o i c e s [ d ] ) ; popen ( speak_cmd , " r " ) ;
B.1. C PROGRAM MAIN.C
47 w r i t e B y t e ( h S e r i a l , 0 b101 ) ; Sleep (300) ; writeByte ( hSerial , directions [d ]) ; / / Turn , i f ( d == 1 | | d == 3 ) { Sleep (500) ; do / / keep turning , readByte ( hSerial , byteBuffer ) ; w h i l e ( ( b y t e B u f f e r [ 0 ] & 0 b0111 ) ! = d i r e c t i o n s [ d ] ) ; } writeByte ( hSerial , 0) ; / / and s w i t c h t o s e n s o r s
265 266 267 268 269 270 271 272 273 274 275
r o u t e = r o u t e −> n e x t ;
276 277
set_position ( robot ) ;
278
} else {
279
w r i t e B y t e ( h S e r i a l , 0 b101 ) ; Sleep ( waitingTime ) ; writeByte ( hSerial , 0) ;
280 281 282
} i ++; p r i n t f ( " i : %d \ n " , i ) ; Sleep (1000) ;
283 284 285 286
} last = sensors ;
287 288
} i f ( m i n e _ s e n s o r == 1 ) { minecount = 0; mine_sensor = 0; j −−; p r i n t f ( " aangekomen b i j m i n e r e s e t \ n " ) ; continue ; } d = 0; i f ( r o b o t −>x == 0 ) d = g e t _ d i r e c t i o n ( r o b o t −>x , r o b o t −>y , r o b o t −>x − 1 , r o b o t −>y , r o b o t −> orientation ) ; e l s e i f ( r o b o t −>x == 4 ) d = g e t _ d i r e c t i o n ( r o b o t −>x , r o b o t −>y , r o b o t −>x + 1 , r o b o t −>y , r o b o t −> orientation ) ; e l s e i f ( r o b o t −>y == 0 ) d = g e t _ d i r e c t i o n ( r o b o t −>x , r o b o t −>y , r o b o t −>x , r o b o t −>y − 1 , r o b o t −> orientation ) ; e l s e i f ( r o b o t −>y == 4 ) d = g e t _ d i r e c t i o n ( r o b o t −>x , r o b o t −>y , r o b o t −>x , r o b o t −>y + 1 , r o b o t −> orientation ) ; w r i t e B y t e ( h S e r i a l , 0 b101 ) ; Sleep (300) ; writeByte ( hSerial , directions [d ]) ; / / Final t ur n to base r o b o t −> o r i e n t a t i o n = ( r o b o t −> o r i e n t a t i o n + d ) % 4 ; i f ( d == 1 | | d == 3 ) { do readByte ( hSerial , byteBuffer ) ; w h i l e ( ( b y t e B u f f e r [ 0 ] & 0 b0111 ) ! = d i r e c t i o n s [ d ] ) ; } writeByte ( hSerial , 0) ; do readByte ( hSerial , byteBuffer ) ; w h i l e ( ( b y t e B u f f e r [ 0 ] & 0 b0111 ) ! = 0 b111 ) ; popen ( " Say . e x e A r r i v e d a t b a s e ! " , " r " ) ; i f ( j < n − 1) { w r i t e B y t e ( h S e r i a l , 0 b110 ) ; / / Turn u n t i l p a t h i s f o u n d , i f n o t t h e f i n a l base r o b o t −> o r i e n t a t i o n = ( r o b o t −> o r i e n t a t i o n + 2 ) % 4 ; do readByte ( hSerial , byteBuffer ) ; w h i l e ( ( b y t e B u f f e r [ 0 ] & 0 b0111 ) ! = 0 b110 ) ; } w r i t e B y t e ( h S e r i a l , 0 b1000 ) ; / / Stop
289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328
}
329 330 331
popen ( " Say . e x e D e s t i n a t i o n r e a c h e d ! " , " r " ) ;
48
BIJLAGE B. C BRONCODE BESTANDEN p r i n t f ( " ZIGBEE IO DONE ! \ n " ) ; CloseHandle ( h S e r i a l ) ;
332 333 334
return 0;
335 336
}
B.2 1 2
roadplan.c
# i n c l u d e < s t d i o . h> # i n c l u d e < s t d l i b . h>
3 4 5 6 7
# include # include # include # include
" junction . h" " road . h" " salloc . h" " robot . h"
8 9 10 11
Junction ∗ field [5][5]; Road ∗ r o a d s _ x [ 4 ] [ 5 ] ; Road ∗ r o a d s _ y [ 5 ] [ 4 ] ;
12 13 14 15 16 17
s t r u c t node { int x ; int y ; s t r u c t node ∗ n e x t ; };
18 19 20
void p r e p a r e _ f i e l d ( ) { int x , y ;
21
/ ∗ Make a 5 x5 f i e l d ∗ / f o r ( x = 0 ; x < 5 ; x ++) { f o r ( y = 0 ; y < 5 ; y ++) { f i e l d [ x ] [ y ] = new_junction (x , y ) ; } }
22 23 24 25 26 27 28
}
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
void p r e p a r e _ r o a d s ( ) { int x , y ; / ∗ Make a 4 x5 a r r a y o f x−r o a d s ∗ / f o r ( x = 0 ; x < 4 ; x ++) { f o r ( y = 0 ; y < 5 ; y ++) { r o a d s _ x [ x ] [ y ] = new_road ( ) ; } } / ∗ Make a 5 x4 a r r a y o f y−r o a d s ∗ / f o r ( x = 0 ; x < 5 ; x ++) { f o r ( y = 0 ; y < 4 ; y ++) { r o a d s _ y [ x ] [ y ] = new_road ( ) ; } } }
45 46 47 48 49 50
s t r u c t node ∗ s h o r t e s t _ r o u t e ( i n t o r i g _ x , i n t o r i g _ y , i n t d e s t _ x , i n t d e s t _ y ) { Junction ∗ origin , ∗ destination , ∗ junction , ∗ min_junction ; Road ∗ r o a d ; int x , y ; s t r u c t node ∗ new_r , ∗ r = s a f e _ m a l l o c ( s i z e o f ( s t r u c t node ) ) ;
51 52 53 54
origin = f i e l d [ orig_x ][ orig_y ] ; d e s t i n a t i o n = f i e l d [ dest_x ][ dest_y ] ; o r i g i n −> d i s t a n c e = 0 ;
55 56 57 58 59 60 61 62
w h i l e ( d e s t i n a t i o n −> i s _ s t i l l _ i n _ s e t ) { / ∗ g e t t h e j u n c t i o n w i t h t h e l o w e s t d i s t a n c e , but which i s not y e t v i s i t e d ( i s s t i l l in the set ) ∗/ i n t min_x = d e s t _ x , min_y = d e s t _ y ; f o r ( x = 0 ; x < 5 ; x ++) { f o r ( y = 0 ; y < 5 ; y ++) { i f ( f i e l d [ x ] [ y]−> i s _ s t i l l _ i n _ s e t && ( f i e l d [ x ] [ y]−> d i s t a n c e < f i e l d [ min_x ] [ min_y]−> d i s t a n c e ) ) { min_x = x ;
B.2. C PROGRAM ROADPLAN.C
49 min_y = y ;
63
}
64
} } m i n _ j u n c t i o n = f i e l d [ min_x ] [ min_y ] ; m i n _ j u n c t i o n −> i s _ s t i l l _ i n _ s e t = 0 ;
65 66 67 68 69
v o i d s e t _ d i s t a n c e ( char o r i e n t a t i o n ) { switch ( o r i e n t a t i o n ) { c a s e ’w ’ : r o a d = r o a d s _ x [ min_x − 1 ] [ min_y ] ; j u n c t i o n = f i e l d [ min_x − 1 ] [ min_y ] ; break ; case ’ e ’ : r o a d = r o a d s _ x [ min_x ] [ min_y ] ; j u n c t i o n = f i e l d [ min_x + 1 ] [ min_y ] ; break ; case ’ s ’ : r o a d = r o a d s _ y [ min_x ] [ min_y − 1 ] ; j u n c t i o n = f i e l d [ min_x ] [ min_y − 1 ] ; break ; case ’n ’ : r o a d = r o a d s _ y [ min_x ] [ min_y ] ; j u n c t i o n = f i e l d [ min_x ] [ min_y + 1 ] ; break ; }
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
/ ∗ s e t a new d i s t a n c e t o t h e j u n c t i o n i n t h e s p e c i f i e d d i r e c t i o n f r o m t h e current junction i f i t ’ s smaller ∗/ i f ( ! r o a d −>b l o c k e d && j u n c t i o n −> i s _ s t i l l _ i n _ s e t && m i n _ j u n c t i o n −> d i s t a n c e + 1 < j u n c t i o n −> d i s t a n c e ) { j u n c t i o n −> d i s t a n c e = m i n _ j u n c t i o n −> d i s t a n c e + 1 ; j u n c t i o n −> s h o r t e s t _ p a r e n t = m i n _ j u n c t i o n ; }
90 91 92 93 94
}
95 96
/∗ only set the distances to e x i s t i n g junctions ∗/ i f ( min_x ! = 0 ) s e t _ d i s t a n c e ( ’w ’ ) ; i f ( min_x ! = 4 ) set_distance ( ’e ’ ) ; i f ( min_y ! = 0 ) set_distance ( ’s ’) ; i f ( min_y ! = 4 ) set_distance ( ’n ’ ) ;
97 98 99 100 101 102 103 104 105
}
106 107
i f ( d e s t i n a t i o n −> d i s t a n c e == −1) p r i n t f ( "No r o u t e b e t w e e n j u n c t i o n k%d%d and j u n c t i o n k%d%d \ n " , o r i g _ x , o r i g _ y , d e s t _ x , dest_y ) ; else p r i n t f ( " T o t a l d i s t a n c e o f t h e r o u t e b e t w e e n k%d%d and k%d%d i s %d \ n " , o r i g _ x , o r i g _ y , dest_x , dest_y , d e s t i n a t i o n −> d i s t a n c e ) ;
108 109 110 111 112 113
/ ∗ make a l i s t o f t h e r o u t e t o f o l l o w ∗ / r −> n e x t = NULL ; r −>x = d e s t _ x ; r −>y = d e s t _ y ; f o r ( j u n c t i o n = d e s t i n a t i o n ; j u n c t i o n −> s h o r t e s t _ p a r e n t ; j u n c t i o n = j u n c t i o n −> s h o r t e s t _ p a r e n t ) { new_r = s a f e _ m a l l o c ( s i z e o f ( s t r u c t node ) ) ; new_r −>x = j u n c t i o n −>x ; new_r −>y = j u n c t i o n −>y ; new_r −> n e x t = r ; r = new_r ; }
114 115 116 117 118 119 120 121 122 123 124 125
return r ;
126 127
}
128 129 130
void block_road ( i n t x , i n t y , i n t o r i e n t a t i o n ) { p r i n t f ( " B l o c k e d b e t w e e n %d ,%d and " , x , y ) ;
50 switch ( o r i e n t a t i o n ) { case 0: r o a d s _ y [ x ] [ y]−> b l o c k e d = 1 ; p r i n t f ( "%d ,%d \ n " , x , y + 1 ) ; break ; case 1: r o a d s _ x [ x ] [ y]−> b l o c k e d = 1 ; p r i n t f ( "%d ,%d \ n " , x + 1 , y ) ; break ; case 2: r o a d s _ y [ x ] [ y − 1]−> b l o c k e d = 1 ; p r i n t f ( "%d ,%d \ n " , x , y − 1 ) ; break ; case 3: r o a d s _ x [ x − 1 ] [ y]−> b l o c k e d = 1 ; p r i n t f ( "%d ,%d \ n " , x − 1 , y ) ; break ; }
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
}
B.3 1 2
BIJLAGE B. C BRONCODE BESTANDEN
junction.h
# i f n d e f _JUNCTION_H_ # d e f i n e _JUNCTION_H_
3 4
typedef struct j u n c t i o n Junction ;
5 6
# include " road . h"
7 8 9 10 11 12 13 14
struct junction { int x ; int y ; unsigned i n t d i s t a n c e ; int i s _ s t i l l _ i n _ s e t ; Junction ∗ shortest_parent ; };
15 16 17
Junction ∗ new_junction ( int x , int y ) ; void d e l e t e _ j u n c t i o n ( J u n c t i o n ∗ j u n c t i o n ) ;
18 19
# e n d i f / ∗ _JUNCTION_H_ ∗ /
B.4 1 2
junction.c
# i n c l u d e < s t d l i b . h> # i n c l u d e < l i m i t s . h>
3 4 5
# include " junction . h" # include " s a l l o c . h"
6 7 8
Junction ∗ new_junction ( int x , int y ) { Junction ∗ junction = safe_malloc ( sizeof ( Junction ) ) ;
9
j u n c t i o n −>x = x ; j u n c t i o n −>y = y ; j u n c t i o n −> d i s t a n c e = −1; j u n c t i o n −> i s _ s t i l l _ i n _ s e t = 1 ; j u n c t i o n −> s h o r t e s t _ p a r e n t = NULL ;
10 11 12 13 14 15
return j u n c t i o n ;
16 17
}
18 19 20 21 22 23
void d e l e t e _ j u n c t i o n ( J u n c t i o n ∗ j u n c t i o n ) { i f ( j u n c t i o n ! = NULL) { free ( junction ) ; } }
B.5
road.h
B.6. C PROGRAM ROAD.C 1 2
# i f n d e f _ROAD_H_ # d e f i n e _ROAD_H_
3 4
t y p e d e f s t r u c t r o a d Road ;
5 6
# include " junction . h"
7 8 9 10 11
struct road { int blocked ; int treasure ; };
12 13 14
Road ∗ new_road ( ) ; v o i d d e l e t e _ r o a d ( Road ∗ r o a d ) ;
15 16
# e n d i f / ∗ _ROAD_H_ ∗ /
B.6 1
road.c
# i n c l u d e < s t d l i b . h>
2 3 4
# include " road . h" # include " s a l l o c . h"
5 6 7
Road ∗ new_road ( ) { Road ∗ r o a d = s a f e _ m a l l o c ( s i z e o f ( Road ) ) ;
8
r o a d −>b l o c k e d = 0 ; r o a d −> t r e a s u r e = 0 ;
9 10 11
return road ;
12 13
}
14 15 16 17 18
v o i d d e l e t e _ r o a d ( Road ∗ r o a d ) { i f ( r o a d ! = NULL) f r e e ( road ) ; }
B.7 1 2
robot.h
# i f n d e f ROBOT_H_ # d e f i n e ROBOT_H_
3 4
t y p e d e f s t r u c t r o b o t Robot ;
5 6 7 8 9 10
struct robot { int x ; int y ; i n t o r i e n t a t i o n ; /∗ 0: north , 1: east , 2: south , 3: west ∗/ };
11 12 13
Robot ∗ n e w _ r o b o t ( i n t x , i n t y , i n t o r i e n t a t i o n ) ; v o i d d e l e t e _ r o b o t ( Robot ∗ r o b o t ) ;
14 15
# e n d i f / ∗ ROBOT_H_ ∗ /
B.8 1
robot.c
# i n c l u d e < s t d l i b . h>
2 3 4
# include " robot . h" # include " s a l l o c . h"
5 6 7
Robot ∗ n e w _ r o b o t ( i n t x , i n t y , i n t o r i e n t a t i o n ) { Robot ∗ r o b o t = s a f e _ m a l l o c ( s i z e o f ( Robot ) ) ;
8 9 10 11
r o b o t −>x = x ; r o b o t −>y = y ; r o b o t −> o r i e n t a t i o n = o r i e n t a t i o n ;
51
52
BIJLAGE B. C BRONCODE BESTANDEN
12
return robot ;
13 14
}
15 16 17 18 19 20
v o i d d e l e t e _ r o b o t ( Robot ∗ r o b o t ) { i f ( r o b o t ! = NULL) { free ( robot ) ; } }
B.9 1
salloc.h
# i n c l u d e < s t d l i b . h>
2 3 4 5
/ ∗ T h e s e f u n c t i o n s p r o v i d e a way t o s a f e l y ∗ a l l o c a t e memory ∗/
6 7 8
void ∗ s a f e _ m a l l o c ( s i z e _ t s i z e ) ; char ∗ s a f e _ s t r d u p ( c o n s t char ∗ s t r i n g ) ;
B.10 1 2 3
salloc.c
# i n c l u d e < s t d i o . h> # i n c l u d e < s t d l i b . h> # i n c l u d e < s t r i n g . h>
4 5 6 7 8 9 10 11
s t a t i c v o i d ∗ c h e c k _ p o i n t e r ( v o i d ∗p ) { i f ( p == NULL) { p r i n t f ( " E r r o r : o u t o f memory ! \ n " ) ; exit (1) ; } return p ; }
12 13 14 15
void ∗ s a f e _ m a l l o c ( s i z e _ t s i z e ) { return ch ec k _p oi nt er ( malloc ( s i z e ) ) ; }
16 17 18 19
char ∗ s a f e _ s t r d u p ( c o n s t char ∗ s t r i n g ) { return s t r c p y ( safe_malloc ( s t r l e n ( s t r i n g ) + 1) , s t r i n g ) ; }
Bijlage C
FPGA user constraint file epo2.ucf 1 2 3 4
#======================================================== # P i n a s s i n g m e n t f o r BASYS2 # X i l i n x S p a r t a n 3E b o a r d #========================================================
5 6 7 8 9 10 11
#======================================================== # c l o c k and r e s e t #======================================================== NET " c l k " LOC = "B8" ; NET " r e s e t _ b t n " LOC = "A7 " ; NET " r e s e t _sw " LOC = " P 1 1 " ;
12 13 14 15 16 17 18 19 20
#======================================================== # buttons & switches #======================================================== # 4 push b u t t o n s #NET " w r i t e _ d a t a " LOC = "G1 2 " ; # b t n <0> #NET " r e a d _ d a t a " LOC = "C 1 1 " ; # b t n <1> #NET " b t n <2 >" LOC = "L 1 3 " ; #NET " b t n <3 >" LOC = "L 1 4 " ; # b t n <3> a l r e a d y u s e d a s r e s e t
21 22 23 24 25 26 27 28 29 30
# 8 slide switches #NET " sw <7 >" LOC = #NET " sw <6 >" LOC = #NET " sw <5 >" LOC = #NET " sw <4 >" LOC = #NET " sw <3 >" LOC = #NET " sw <2 >" LOC = #NET " sw <1 >" LOC = #NET " sw <0 >" LOC =
"N3 " ; "E 2 " ; "F 3" ; "G3 " ; "B 4 " ; "K3 " ; "L 3 " ; "P 11";
# # # # # # # #
Bank Bank Bank Bank Bank Bank Bank Bank
= = = = = = = =
2, 3, 3, 3, 3, 3, 3, 2,
Signal Signal Signal Signal Signal Signal Signal Signal
name name name name name name name name
= = = = = = = =
SW7 SW6 SW5 SW4 SW3 SW2 SW1 SW0
31 32 33 34 35 36 37 38 39 40 41 42 43 44
#======================================================== # 4− d i g i t t i m e −m u l t i p l e x e d 7−s s e g m e n t LED d i s p l a y #======================================================== # C o n n e c t e d t o B a s y s 2 onBoard 7 s s e g d i s p l a y NET " s s e g <0 >" LOC = "L 1 4 " ; # Bank = 1 , S i g n a l name = CA NET " s s e g <1 >" LOC = "H1 2 " ; # Bank = 1 , S i g n a l name = CB NET " s s e g <2 >" LOC = "N1 4 " ; # Bank = 1 , S i g n a l name = CC NET " s s e g <3 >" LOC = "N1 1 " ; # Bank = 2 , S i g n a l name = CD NET " s s e g <4 >" LOC = " P 1 2 " ; # Bank = 2 , S i g n a l name = CE NET " s s e g <5 >" LOC = "L 1 3 " ; # Bank = 1 , S i g n a l name = CF NET " s s e g <6 >" LOC = "M1 2 " ; # Bank = 1 , S i g n a l name = CG NET " s s e g <7 >" LOC = "N1 3 " ; # Bank = 1 , S i g n a l name = DP
45 46 47 48 49
NET NET NET NET
" an <3 >" " an <2 >" " an <1 >" " an <0 >"
LOC LOC LOC LOC
= = = =
"K1 4 " ; "M1 3 " ; " J 12"; "F 12";
# # # #
Bank Bank Bank Bank
= = = =
1, 1, 1, 1,
Signal Signal Signal Signal
name name name name
= = = =
AN3 AN2 AN1 AN0
50 51
#========================================================
53
54 52 53 54 55 56 57 58 59 60 61
BIJLAGE C. USER CONSTRAINT FILE
# 8 d is c r e te led #======================================================== NET " Led <7 >" LOC = "G1" ; # Bank = 3 , S i g n a l name = LD7 NET " Led <6 >" LOC = " P 4" ; # Bank = 2 , S i g n a l name = LD6 NET " Led <5 >" LOC = "N4" ; # Bank = 2 , S i g n a l name = LD5 NET " Led <4 >" LOC = "N5" ; # Bank = 2 , S i g n a l name = LD4 NET " Led <3 >" LOC = " P 6" ; # Bank = 2 , S i g n a l name = LD3 NET " Led <2 >" LOC = " P 7" ; # Bank = 3 , S i g n a l name = LD2 NET " Led <1 >" LOC = "M11" ; # Bank = 2 , S i g n a l name = LD1 NET " Led <0 >" LOC = "M5" ; # Bank = 2 , S i g n a l name = LD0
62 63 64 65 66 67
# Pin assignment f o r #NET " JA <1 >" LOC = NET " s e n s o r _ l " LOC = NET " s e n s o r _m" LOC = NET " s e n s o r _ r " LOC =
PMOD "B2" "A3" " J 3" "B5"
connectors ; ; ; ;
68 69 70 71 72 73
#NET " JB <1 >" LOC = #NET " JB <2 >" LOC = #NET " JB <3 >" LOC = #NET " JB <4 >" LOC = NET " s e n s o r _ m i j n "
"C6" ; "B6" ; "C5" ; "B7" ; LOC = "C 6 " ; # JB <1>
74 75 76 77 78 79
NET NET NET NET
" motor _ l e f t " " motor _ r i g h t " " rx " " tx "
LOC LOC LOC LOC
= = = =
"A9" ; "B9" ; "A10" "C9" ;
80 81 82 83 84
#NET #NET #NET #NET
" JD <1 >" " JD <2 >" " JD <3 >" " JD <4 >"
LOC LOC LOC LOC
= = = =
"C12" "A13" "C13" "D12"
; ; ; ;
# servo l e f t # servo r i g h t ; # xbee out ( r e c e i v e d d a t a ) # xbee i n ( d a t a t o send )
Bijlage D
Wedstrijdregels
55
Smart Robot Challenge 2013
Wedstrijdregels (versie 1.0 – 9 februari 2012) A/ Technische eisen aan de robot: 1. De robot past in een fictieve box (is niet groter dan) 30 cm x 25 cm x 20 cm; 2. Het gewicht is maximaal 1 kg; 3. De aandrijving is gerealiseerd m.b.v. elektromotoren en een batterij. Behalve batterij is er op de robot geen andere energiebron aanwezig. 4. De robotaansturing kan gerealiseerd worden alleen via de beschikbare Spartan-3 ontwikkelboord, twee XBee modules en een sturingprogramma op een laptop/PC geschreven in programmeertaal C (let op C++ of C# zijn niet toegestaan). De configuratie van de FPGAchip kan geschieden alleen via een in-VHDL-geschreven broncode. 5. Het besturingsprogramma moet zo geschreven zijn, dat het door de gebruiker niet mogelijk is de posities van de obstakels of de vrije wegsegmenten op het wedstrijdveld in te voeren. 6. De robot moet zo geconstrueerd zijn, dat deze geen schade of markeringen aan het wedstrijdveld aanbrengt. C/ Wedstrijdveld: 1. Het wedstrijdveld getoond in Figuur 1 is zwart geplot op een wit papiervel met afmetingen van 244 cm x 244 cm en geplaatst op een hardboard als ondergrond. Het reguliere patroon is gevormd door een 4 x 4 rooster van wegen en kruispunten. De wegen zijn aangegeven als een zwarte strip 15 mm breed. Een wegsegment is 48 cm lang. Het middelpunt van elk wegsegment is gemarkeerd met een zwarte cirkel met diameter van 30 mm. Aan elke zijde van het vierkante veld zijn er drie ingangswegen/controleposten gemarkeerd oplopend van 1 t/m 12. De lengte van de ingangsweg is 16 cm. 2. Bij sommige wedstrijdonderdelen (zie verder) wordt er op het wedstrijdveld aantal “mijnen” geplaatst. Deze kunnen zich bevinden alleen in het midden van de wegsegmenten en dat precies op de markeringscirkel. De mijnen zijn gemaakt van een zwartgeverfde verzinkte stalen ring (diameter 30 mm; binnengat 6 mm; dikte 1 mm).
Figuur 1: Wedstrijdveld Smart Robot Challenge 2013.
B/ Challenges: 1. De robotwedstrijd bestaat uit de volgende challenges met oplopende moeilijkheidsgraad: a. Challenge A - Grid; b. Challenge B - Mijnenveld; c. Challenge C - Schat zoeken. 2. Het team moet eerst scoren in Challenge A om mee te kunnen doen aan Challenge B. 3. De vier beste teams uit Challenge B gaan door naar Challenge C. 4. De uiteindelijke volgorde van de teams wordt bepaald volgens het aantal punten behaald in de hoogste Challenge. C/ Algemene wedstrijdregels: 1. Voorbereidingstijd: Bij elke challenge is er een voorbereidingstijd van 60 s. Binnen deze tijd wordt de robot door een van de teamleden op de controlepost 1 geplaatst zo dat het einde van de ingangsweg niet zichtbaar is (startpositie) en het stuurprogramma op de laptop wordt opgestart. 2. Wedstrijdtijd: Zodra het team klaar is met de voorbereiding, zal de scheidsrechter startsignaal geven. Na het startsignaal heeft het team met zijn robot een bepaalde tijd (zonder onderbreking) om de wedstrijdopdracht te voltooien. Bij Challenge A is deze 120 s; bij Challenge B 180 s; bij Challenge C 120 s + 300 s. 3. Score: Elke Challenge bestaat uit meerdere opdrachten. Alleen voor de opdrachten welke binnen de wedstrijdtijd voltooid zijn, worden punten toegekend. Het aantal toegekende punten voor elke opdracht is identiek aan het aantal resterende seconden van de wedstrijdtijd op het moment dat deze opdracht voltooid is. 4. Aansturing: De robot samen met het aansturingsprogramma op de laptop werken geheel autonoom, d.w.z. geen van de teamleden mag de robot of de laptop tijdens de wedstrijdtijd aanraken. Alleen op de startpositie mag het aansturingsprogramma (op de robot en/of de laptop) opnieuw opgestart worden. Hierbij mag geen expliciete informatie over het veld (d.w.z. positie van de mijnen) door de teamleden ingevoerd worden. Overtreden van deze regel zal leiden tot onmiddellijke diskwalificatie van het team. 5. Plaatsen op de startpositie: De robot kan tijdens de wedstrijdtijd op elk moment door de teamleden teruggeplaatst worden op de startpositie. Ook op aanwijzing van de scheidsrechter (in geval dat een van de regels is overtreden) moet de robot teruggeplaatst worden op de startpositie. 6. Verlaten van de weg: Het is de bedoeling dat de robot op het veld beweegt alleen op de zwartgemarkeerde wegen. Verlaat de robot de weg, wordt deze op aanwijzing van de scheidsrechter op de startpositie geplaatst. De weg wordt verlaten indien de robot van één naar een ander wegsegment rijdt zonder over het tussenliggende kruispunt te rijden of indien de robot in zijn geheel boven de witte ondergrond zich bevindt. D/ Challenge A – Grid: 1. In deze challenge zijn er geen mijnen op het veld geplaatst. 2. De robot moet vanaf zijn startpositie op de controlepost 1 in zo kort mogelijke tijd drie vooraf opgegeven controleposten bezoeken. De controlepost is bezocht indien het einde van de ingangsweg door een deel van de robot bedekt is. Voor elke goed bezochte controlepost worden er punten toegekend. 3. Verlaat de robot de weg of rijd deze naar een verkeerde controlepost, dan wordt de robot naar eigen keuze op de laatst bezochte goede controlepost of de startpositie geplaatst. E/ Challenge B – Mijnenveld: 1. In deze challenge worden er 13 mijnen op het veld geplaatst. 2. De robot moet opnieuw vanaf de startpositie drie vooraf opgegeven controleposten bezoeken. De robot moet de aanwezige mijnen detecteren en ontwijken. De controlepost is bezocht indien het einde van de ingangsweg door een deel van de robot bedekt is. Voor elke goed bezochte controlepost worden er punten toegekend.
3. Rijden door een mijn: Robot rijdt door een mijn indien de mijn door de robot aangeraakt wordt of indien de robot een wegsegment gebruikt (van kruispunt tot kruispunt) waarop een mijn ligt. 4. De robot heeft 3 levens. Rijdt de robot door een mijn, dan verliest hij één leven en wordt deze naar eigen keuze op de laatst bezochte goede controlepost of de startpositie geplaatst. De ontplofte mijn wordt van het veld verwijderd. 5. Verlaat de robot de weg of rijdt deze naar een verkeerde controlepost, dan wordt de robot naar eigen keuze op de laatst bezochte goede controlepost of de startpositie geplaatst. F/ Challenge C – Schat zoeken: 1. Deze challenge bestaat uit 2 stappen: veld verkennen en schat zoeken. 2. Veld verkennen: In de eerste stap heeft het team 120 s de tijd om het veld met 13 mijnen te verkennen. Rijdt de robot door een mijn dan wordt de robot op de startpositie geplaatst, maar de mijn wordt niet verwijderd. In deze stap worden er geen punten verdiend. 3. Schat zoeken: Er wordt een nieuwe mijn (=schat) op een van de vrije posities op het veld geplaatst. De robot moet dan in zo kort mogelijke tijd vanuit de startpositie (post 1) de schat ontdekken. De schat is ontdekt indien de robot deze aanraakt. Het aantal toegekende punten is identiek aan de resterende tijd in seconden. Rijdt de robot door een mijn, dan wordt de robot op de startpositie geplaatst en de mijn wordt verwijderd.
Bijlage E
VHDL broncode bestanden E.1 1 2 3
VHDL broncode van UART
library ieee ; use i e e e . s t d _ l o g i c _ 1 1 6 4 . a l l ; use i e e e . n u m e r i c _ s t d . a l l ;
4 5 6 7 8 9 10 11 12 13 14
entity uart is port ( clk , r e s e t rx tx −− led write_data read_data −− sseg −− an
: in s t d _ l o g i c ; : i n s t d _ l o g i c ; −−i n p u t b i t s t r e a m : o u t s t d _ l o g i c ; −−o u t p u t b i t s t r e a m : o u t s t d _ l o g i c _ v e c t o r ( 7 downto 0 ) ; −−r e c e i v e d b y t e : i n s t d _ l o g i c ; −−w r i t e t o t r a n s m i t t e r b u f f e r : i n s t d _ l o g i c ; −−r e a d f r o m r e c e i v e r b u f f e r : o u t s t d _ l o g i c _ v e c t o r ( 7 downto 0 ) ; −−s e v e n s e g m e n t LED d i s p l a y : o u t s t d _ l o g i c _ v e c t o r ( 3 downto 0 ) ; −−a n o d e s o f s e v e n s e g m e n t LED d i s p l a y
15 16 17 18 19
xbee_send : i n s t d _ l o g i c _ v e c t o r ( 7 downto 0 ) ; −−b y t e t o be s e n t x b e e _ r e c e i v e d : o u t s t d _ l o g i c _ v e c t o r ( 7 downto 0 ) −−r e c e i v e d b y t e ); end u a r t ;
20 21 22 23 24 25 26 27 28 29 30
architecture s t r u c t u r a l of component u a r t _ r x i s port ( clk , r e s e t : rx : s_tick : rx_done_tick : dout : ); end component u a r t _ r x ;
uart is
in in in out out
std_logic ; s t d _ l o g i c ; −− i c o m i n g s e r i a l b i t s t r e a m s t d _ l o g i c ; −− s a m p l i n g t i c k f r o m baud r a t e g e n e r a t o r s t d _ l o g i c ; −− d a t a f r a m e c o m p l e t i o n t i c k s t d _ l o g i c _ v e c t o r ( 7 downto 0 ) −− d a t a b y t e
in in in in out out
std_logic ; s t d _ l o g i c ; −− i f ’ 1 ’ t r a n s m i s s i o n s t a r t s s t d _ l o g i c ; −− s a m p l i n g t i c k f r o m baud r a t e g e n e r a t o r s t d _ l o g i c _ v e c t o r ( 7 downto 0 ) ; −− i n c o m i n g d a t a b y t e s t d _ l o g i c ; −− d a t a f r a m e c o m p l e t i o n t i c k s t d _ l o g i c −− o u t c o m i n g b i t s t r e a m
31 32 33 34 35 36 37 38 39 40 41
component u a r t _ t x i s port ( clk , r e s e t tx_start s_tick din tx_done_tick tx ); end component u a r t _ t x
: : : : : : ;
42 43 44 45 46 47 48
component b a u d _ g e n i s generic ( M : i n t e g e r : = 326 −− baud r a t e d i v i s o r M = 50M/ ( 1 6 ∗ 9 6 0 0 ) ); port ( clk , r e s e t : in s t d _ l o g i c ;
59
60
BIJLAGE E. VHDL BRONCODE BESTANDEN s_tick : out s t d _ l o g i c ); end component b a u d _ g e n ;
49 50 51
−− s a m p l i n g t i c k
52
component b u f _ r e g i s port ( clk , r e s e t clr_flag , set_flag din dout flag ); end component b u f _ r e g ;
53 54 55 56 57 58 59 60 61
: : : : :
in in in out out
std_logic ; std_logic ; s t d _ l o g i c _ v e c t o r ( 7 downto 0 ) ; s t d _ l o g i c _ v e c t o r ( 7 downto 0 ) ; std_logic
62
signal s_tick , rx_done_tick , t x _ s t a r t , tx_done_tick : std_logic ; signal rx_dout , tx_din , data_out : s t d _ l o g i c _ v e c t o r ( 7 downto 0 ) ;
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
begin BG : b a u d _ g e n p o r t map ( clk => c l k , r e s e t => r e s e t , s _ t i c k => s _ t i c k ); RCV : u a r t _ r x p o r t map ( clk => c l k , reset => r e s e t , rx => rx , s_tick => s _ t i c k , r x _ d o n e _ t i c k => r x _ d o n e _ t i c k , dout => r x _ d o u t ); TRM : u a r t _ t x p o r t map ( clk => c l k , reset => r e s e t , tx_start => t x _ s t a r t , s_tick => s _ t i c k , din => t x _ d i n , t x _ d o n e _ t i c k => t x _ d o n e _ t i c k , tx => t x ); RCB : b u f _ r e g p o r t map ( clk => c l k , reset => r e s e t , c l r _ f l a g => r e a d _ d a t a , s e t _ f l a g => r x _ d o n e _ t i c k , din => r x _ d o u t , dout => d a t a _ o u t −− flag => s s e g ( 6 ) ); TRB : b u f _ r e g p o r t map ( clk => c l k , reset => r e s e t , c l r _ f l a g => t x _ d o n e _ t i c k , s e t _ f l a g => w r i t e _ d a t a , din => x b e e _ s e n d , dout => t x _ d i n , flag => t x _ s t a r t );
107 108 109 110 111
−−
led <= r e s e t & d a t a _ o u t ( 6 downto 0 ) ; x b e e _ r e c e i v e d <= d a t a _ o u t ; −− an <= " 1 1 1 0 " ; end s t r u c t u r a l ;
E.2 1 2 3
VHDL broncode van baud rate generator
−− Baud r a t e g e n e r a t o r −− b a s e d on mod−M c o u n t e r −− a s a m p l i n g t i c k i s g e n e r a t e d when c o u n t e r h a s maximumm v a l u e
4 5 6
library ieee ; use i e e e . s t d _ l o g i c _ 1 1 6 4 . a l l ;
E.3. UART TRANSMITTER 7
61
use i e e e . n u m e r i c _ s t d . a l l ;
8 9 10 11 12 13 14 15 16 17
e n t i t y baud_gen i s generic ( M : i n t e g e r : = 326 ); port ( clk , r e s e t : in s t d _ l o g i c ; s_tick : out s t d _ l o g i c ); end b a u d _ g e n ;
−− baud r a t e d i v i s o r M = 50M/ ( 1 6 ∗ 9 6 0 0 )
−− s a m p l i n g t i c k
18 19 20 21
−− 9 b i t r e g i s t e r t o a l l o w d i v i s o r M = 326 (M < 5 1 2 ) a r c h i t e c t u r e a r c h of baud_gen i s s i g n a l r _ r e g , r _ n e x t : u n s i g n e d ( 8 downto 0 ) ;
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
begin −− r e g i s t e r process ( clk , r e s e t ) begin i f ( r e s e t = ’1 ’) then r _ r e g <= ( o t h e r s => ’ 0 ’ ) ; e l s i f ( c l k ’ e v e n t and c l k = ’ 1 ’ ) t h e n r _ r e g <= r _ n e x t ; end i f ; end p r o c e s s ; −− n e x t −s t a t e l o g i c r _ n e x t <= ( o t h e r s => ’ 0 ’ ) when r _ r e g = (M − 1 ) e l s e r _ r e g + 1 ; −− o u t p u t l o g i c s _ t i c k <= ’ 1 ’ when r _ r e g = (M − 1 ) e l s e ’ 0 ’ ; end a r c h ;
E.3 1 2 3
VHDL broncode van UART transmitter
−− UART t r a n s m i t t e r −− i n c o m i n g d a t a b y t e d i n i s s e r i a l i z e d i n t o o u t c o m i n g b i t s t r e a m t x −− c o m p l e t i o n o f e a c h d a t a f r a m e i s a s s e r t e d by t x _ d o n e _ t i c k
4 5 6 7 8 9 10 11 12 13 14 15 16 17
library ieee ; use i e e e . s t d _ l o g i c _ 1 1 6 4 . a l l use i e e e . n u m e r i c _ s t d . a l l ; entity uart_tx is port ( clk , r e s e t : in tx_start : in s_tick : in din : in t x _ d o n e _ t i c k : out tx : out ); end u a r t _ t x ;
;
std_logic ; std_logic ; −− i f ’ 1 ’ t r a n s m i s s i o n s t a r t s std_logic ; −− s a m p l i n g t i c k f r o m baud r a t e g e n e r a t o r s t d _ l o g i c _ v e c t o r ( 7 downto 0 ) ; −− i n c o m i n g d a t a b y t e std_logic ; −− d a t a f r a m e c o m p l e t i o n t i c k std_logic −− o u t c o m i n g b i t s t r e a m
18 19 20 21
architecture arch of u a r t _ t x i s c o n s t a n t DBIT : i n t e g e r := 8; c o n s t a n t SB_TICK : i n t e g e r : = 1 6 ;
−− number o f d a t a b i t s −− numbner o f s t o p b i t t i c k s
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
type s t a t e _ t y p e i s ( i d l e , s t a r t , data , s to p ) ; signal state_reg , state_next : state_type ; s i g n a l s_reg , s_next : u n s i g n e d ( 3 downto 0 ) ; −− s a m p l i n g t i c k c o u n t e r s i g n a l n_reg , n_next : u n s i g n e d ( 2 downto 0 ) ; −− d a t a b i t c o u n t e r s i g n a l b_reg , b_next : s t d _ l o g i c _ v e c t o r ( 7 downto 0 ) ; −− d a t a r e g i s t e r signal tx_reg , tx_next : s t d _ l o g i c ; −− b i t s t r e a m f l i p −f l o p begin −− FSMD s t a t e & d a t a r e g i s t e r s process ( clk , r e s e t ) begin i f r e s e t = ’1 ’ then s t a t e _ r e g <= i d l e ; s_reg <= ( o t h e r s => ’ 0 ’ ) ; n_reg <= ( o t h e r s => ’ 0 ’ ) ; b_reg <= ( o t h e r s => ’ 0 ’ ) ; tx_reg <= ’ 1 ’ ;
62 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
e l s i f ( c l k ’ e v e n t and c l k = ’ 1 ’ ) t h e n s t a t e _ r e g <= s t a t e _ n e x t ; s_reg <= s _ n e x t ; n_reg <= n _ n e x t ; b_reg <= b _ n e x t ; tx_reg <= t x _ n e x t ; end i f ; end p r o c e s s ; −− n e x t −s t a t e l o g i c & d a t a p a t h f u n c t i o n a l u n i t s / r o u t i n g process ( s t a t e _ r e g , s_reg , n_reg , b_reg , s _ t i c k , tx_reg , t x _ s t a r t , din ) begin state_next <= s t a t e _ r e g ; −− d e f a u l t v a l u e s s_next <= s _ r e g ; n_next <= n _ r e g ; b_next <= b _ r e g ; tx_next <= t x _ r e g ; t x _ d o n e _ t i c k <= ’ 0 ’ ; case s t a t e _ r e g i s when i d l e => t x _ n e x t <= ’ 1 ’ ; −− o u t p u t i n i d l e i f t x _ s t a r t = ’ 1 ’ t h e n −− t r a n s m i s s i o n can s t a r t s t a t e _ n e x t <= s t a r t ; s_next <= ( o t h e r s => ’ 0 ’ ) ; b_next <= d i n ; end i f ; when s t a r t => t x _ n e x t <= ’ 0 ’ ; −− o u t p u t i n START b i t i f ( s _ t i c k = ’1 ’) then i f s _ r e g = 15 t h e n −− end o f START b i t r e a c h e d s t a t e _ n e x t <= d a t a ; s_next <= ( o t h e r s => ’ 0 ’ ) ; n_next <= ( o t h e r s => ’ 0 ’ ) ; else s _ n e x t <= s _ r e g + 1 ; end i f ; end i f ; when d a t a => t x _ n e x t <= b _ r e g ( 0 ) ; −− d a t a b i t p u t on o u t p u t r i f ( s _ t i c k = ’1 ’) then i f s _ r e g = 15 t h e n −− end o f DATA b i t r e a c h e d s _ n e x t <= ( o t h e r s => ’ 0 ’ ) ; b _ n e x t <= ’ 0 ’ & b _ r e g ( 7 downto 1 ) ; −− d a t a r e g i s t e r s h i f t e d i f n _ r e g = ( DBIT − 1 ) t h e n −− l a s t DATA b i t r e a c h e d s t a t e _ n e x t <= s t o p ; else n _ n e x t <= n _ r e g + 1 ; end i f ; else s _ n e x t <= s _ r e g + 1 ; end i f ; end i f ; when s t o p => t x _ n e x t <= ’ 1 ’ ; −− STOP b i t p u t on o u t p u t i f ( s _ t i c k = ’1 ’) then i f s _ r e g = ( SB_TICK − 1 ) t h e n −− end o f STOP b i t r e a c h e d state_next <= i d l e ; t x _ d o n e _ t i c k <= ’ 1 ’ ; else s _ n e x t <= s _ r e g + 1 ; end i f ; end i f ; end c a s e ; end p r o c e s s ; t x <= t x _ r e g ; end a r c h ;
E.4 1 2 3 4
BIJLAGE E. VHDL BRONCODE BESTANDEN
VHDL broncode van UART receiver
−− UART r e c e i v e r −− i n c o m i n g s e r i a l b i t s t r e a m r x i s g r o u p e d i n 8− b i t d a t a b y t e d o u t −− c o m p l e t i o n o f e a c h d a t a f r a m e i s a s s e r t e d by r x _ d o n e _ t i c k
E.4. UART RECEIVER 5 6 7 8 9 10 11 12 13 14 15 16
library ieee ; use i e e e . s t d _ l o g i c _ 1 1 6 4 . a l l use i e e e . n u m e r i c _ s t d . a l l ; entity uart_rx is port ( clk , r e s e t : in rx : in s_tick : in r x _ d o n e _ t i c k : out dout : out ); end u a r t _ r x ;
63
;
std_logic ; std_logic ; −− i c o m i n g s e r i a l b i t s t r e a m std_logic ; −− s a m p l i n g t i c k f r o m baud r a t e g e n e r a t o r std_logic ; −− d a t a f r a m e c o m p l e t i o n t i c k s t d _ l o g i c _ v e c t o r ( 7 downto 0 ) −− d a t a b y t e
17 18 19 20
architecture arch of u a r t _ r x i s c o n s t a n t DBIT : i n t e g e r := 8; c o n s t a n t SB_TICK : i n t e g e r : = 1 6 ;
−− number o f d a t a b i t s −− numbner o f s t o p b i t t i c k s
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
type s t a t e _ t y p e i s ( i d l e , s t a r t , data , s to p ) ; signal state_reg , state_next : state_type ; s i g n a l s_reg , s_next : u n s i g n e d ( 3 downto 0 ) ; −− s a m p l i n g t i c k c o u n t e r s i g n a l n_reg , n_next : u n s i g n e d ( 2 downto 0 ) ; −− d a t a b i t c o u n t e r s i g n a l b_reg , b_next : s t d _ l o g i c _ v e c t o r ( 7 downto 0 ) ; −− d a t a r e g i s t e r begin −− FSMD s t a t e & d a t a r e g i s t e r s process ( clk , r e s e t ) begin i f r e s e t = ’1 ’ then s t a t e _ r e g <= i d l e ; s_reg <= ( o t h e r s => ’ 0 ’ ) ; n_reg <= ( o t h e r s => ’ 0 ’ ) ; b_reg <= ( o t h e r s => ’ 0 ’ ) ; e l s i f ( c l k ’ e v e n t and c l k = ’ 1 ’ ) t h e n s t a t e _ r e g <= s t a t e _ n e x t ; s_reg <= s _ n e x t ; n_reg <= n _ n e x t ; b_reg <= b _ n e x t ; end i f ; end p r o c e s s ; −− n e x t −s t a t e l o g i c & d a t a p a t h f u n c t i o n a l u n i t s / r o u t i n g process ( s t a t e _ r e g , s_reg , n_reg , b_reg , s _ t i c k , rx ) begin state_next <= s t a t e _ r e g ; −− d e f a u l t v a l u e s s_next <= s _ r e g ; n_next <= n _ r e g ; b_next <= b _ r e g ; r x _ d o n e _ t i c k <= ’ 0 ’ ; case s t a t e _ r e g i s when i d l e => i f rx = ’0 ’ then −− f a l l i n g e d g e o f t h e START b i t d e t e c t e d s t a t e _ n e x t <= s t a r t ; s_next <= ( o t h e r s => ’ 0 ’ ) ; end i f ; when s t a r t => i f ( s _ t i c k = ’1 ’) then i f s _ r e g = 7 then −− m i d p o i n t o f t h e START b i t r e a c h e d s t a t e _ n e x t <= d a t a ; s_next <= ( o t h e r s => ’ 0 ’ ) ; n_next <= ( o t h e r s => ’ 0 ’ ) ; else s _ n e x t <= s _ r e g + 1 ; end i f ; end i f ; when d a t a => i f ( s _ t i c k = ’1 ’) then i f s _ r e g = 15 t h e n −− m i d p o i n t o f DATA b i t r e a c h e d s _ n e x t <= ( o t h e r s => ’ 0 ’ ) ; b _ n e x t <= r x & b _ r e g ( 7 downto 1 ) ; −− s a m p l e d DATA b i t s h i f t e d i n t o d a t a register i f n _ r e g = ( DBIT − 1 ) t h e n −− l a s t DATA b i t r e a c h e d s t a t e _ n e x t <= s t o p ; else n _ n e x t <= n _ r e g + 1 ; end i f ;
64
BIJLAGE E. VHDL BRONCODE BESTANDEN else
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
s _ n e x t <= s _ r e g end i f ; end i f ; when s t o p => i f ( s _ t i c k = ’1 ’) then i f s _ r e g = ( SB_TICK state_next <= r x _ d o n e _ t i c k <= else s _ n e x t <= s _ r e g end i f ; end i f ; end c a s e ; end p r o c e s s ; d o u t <= b _ r e g ; end a r c h ;
E.5 1 2
+ 1;
− 1 ) t h e n −− m i d p o i n t o f STOP b i t r e a c h e d idle ; ’1 ’; + 1;
VHDL broncode van buffer register
−− B u f f e r r e g i s t e r w i t h f l a g f l i p −f l o p −− u s e d a s i n t e r f a c e b u f f e r b e t w e e n UART and main s y s t e m
3 4 5 6 7 8 9 10 11 12 13 14
library ieee ; use i e e e . s t d _ l o g i c _ 1 1 6 4 . a l l entity buf_reg i s port ( clk , r e s e t clr_flag , set_flag din dout flag ); end b u f _ r e g ;
;
: : : : :
in in in out out
std_logic ; std_logic ; s t d _ l o g i c _ v e c t o r ( 7 downto 0 ) ; s t d _ l o g i c _ v e c t o r ( 7 downto 0 ) ; std_logic
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
architecture arch of buf_reg i s s i g n a l b_reg , b_next : s t d _ l o g i c _ v e c t o r ( 7 downto 0 ) ; −− d a t a r e g i s t e r s i g n a l f l a g _ r e g , f l a g _ n e x t : s t d _ l o g i c ; −− f l a g FF begin −− FF & r e g i s t e r process ( clk , r e s e t ) begin i f r e s e t = ’1 ’ then b_reg <= ( o t h e r s => ’ 0 ’ ) ; f l a g _ r e g <= ’ 0 ’ ; e l s i f ( c l k ’ e v e n t and c l k = ’ 1 ’ ) t h e n b_reg <= b _ n e x t ; f l a g _ r e g <= f l a g _ n e x t ; end i f ; end p r o c e s s ; −− n e x t −s t a t e l o g i c process ( b_reg , f l a g _ r e g , s e t _ f l a g , c l r _ f l a g , din ) begin b_next <= b _ r e g ; f l a g _ n e x t <= f l a g _ r e g ; i f ( s e t _ f l a g = ’1 ’) then b_next <= d i n ; f l a g _ n e x t <= ’ 1 ’ ; −− d a t a w i l l be w r i t t e n i n t o r e g i s t e r e l s i f ( c l r _ f l a g = ’1 ’) then f l a g _ n e x t <= ’ 0 ’ ; end i f ; end p r o c e s s ; −− o u t p u t l o g i c d o u t <= b _ r e g ; f l a g <= f l a g _ r e g ; end a r c h ;
E.6 1
VHDL broncode van mijnsensor
library ieee ;
E.6. MIJNSENSOR 2 3
65
use i e e e . s t d _ l o g i c _ 1 1 6 4 . a l l ; use i e e e . n u m e r i c _ s t d . a l l ;
4 5 6 7 8 9 10 11
entity mijnsensor is port ( clk : in sensor : in reset : in mijn : out ); end e n t i t y m i j n s e n s o r ;
std_logic ; std_logic ; std_logic ; std_logic
12 13 14 15 16
architecture b e h a v i o r a l of mijnsensor i s t y p e m i j n _ s t a t e i s ( f i r s t _ h , f i r s t _ l , count_m , c o u n t _ n , d_mine , d_nomine ) ; s i g n a l m_count , m_new_count : u n s i g n e d ( 1 5 downto 0 ) ; signal state : mijn_state ;
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
begin process ( clk ) begin i f ( r i s i n g _ e d g e ( c l k ) ) then i f ( r e s e t = ’1 ’) then mijn <= ’ 0 ’ ; state <= f i r s t _ h ; m_count <= ( o t h e r s => ’ 0 ’ ) ; e l s i f ( r e s e t = ’0 ’) then case s t a t e i s when f i r s t _ l => i f ( s e n s o r = ’1 ’) then s t a t e <= f i r s t _ h ; end i f ; when f i r s t _ h => i f ( s e n s o r = ’0 ’) then s t a t e <= c o u n t _ n ; end i f ; when c o u n t _ n => m_count <= m_new_count ; mijn <= ’ 0 ’ ; i f ( s e n s o r = ’ 1 ’ and m_count < 3 5 0 0 ) t h e n s t a t e <= d_nomine ; e l s i f ( s e n s o r = ’ 1 ’ and m_count >= 3 5 0 0 ) t h e n s t a t e <= d_mine ; end i f ; when count_m => m_count <= m_new_count ; mijn <= ’ 1 ’ ; i f ( s e n s o r = ’ 1 ’ and m_count < 3 5 0 0 ) t h e n s t a t e <= d_nomine ; e l s i f ( s e n s o r = ’ 1 ’ and m_count >= 3 5 0 0 ) t h e n s t a t e <= d_mine ; end i f ; when d_nomine => m i j n <= ’ 0 ’ ; i f ( s e n s o r = ’0 ’) then m_count <= ( o t h e r s => ’ 0 ’ ) ; state <= c o u n t _ n ; end i f ; when d_mine => m i j n <= ’ 1 ’ ; i f ( s e n s o r = ’0 ’) then m_count <= ( o t h e r s => ’ 0 ’ ) ; state <= count_m ; end i f ; end c a s e ; end i f ; end i f ; end p r o c e s s ;
68 69 70 71 72
p r o c e s s ( m_count ) begin m_new_count <= m_count + 1 ; end p r o c e s s ;
73 74
end a r c h i t e c t u r e b e h a v i o r a l ;
66
E.7 1 2
BIJLAGE E. VHDL BRONCODE BESTANDEN
VHDL broncode van inputbuffer
l i b r a r y IEEE ; u s e IEEE . s t d _ l o g i c _ 1 1 6 4 . a l l ;
3 4 5 6 7 8 9
entity register_3bit is port ( clk : in reset : in sensor_in : in s e n s o r _ o u t : out end e n t i t y r e g i s t e r _ 3 b i t ;
std_logic ; std_logic ; s t d _ l o g i c _ v e c t o r ( 2 downto 0 ) ; s t d _ l o g i c _ v e c t o r ( 2 downto 0 ) ) ;
10 11 12 13 14 15 16 17 18 19 20 21 22 23
architecture behavioural of r e g i s t e r _ 3 b i t i s begin process ( clk ) begin i f ( r i s i n g _ e d g e ( c l k ) ) then i f ( r e s e t = ’1 ’) then s e n s o r _ o u t <= " 000 " ; else s e n s o r _ o u t <= s e n s o r _ i n ; end i f ; end i f ; end p r o c e s s ; end a r c h i t e c t u r e b e h a v i o u r a l ;
24 25 26
l i b r a r y IEEE ; u s e IEEE . s t d _ l o g i c _ 1 1 6 4 . a l l ;
27 28 29 30 31 32 33 34 35 36 37
entity inputbuffer is port ( clk reset sensor_l_in sensor_m_in sensor_r_in sensor_l_out sensor_m_out sensor_r_out end e n t i t y i n p u t b u f f e r
: : : : : : : : ;
in in in in in out out out
std_logic std_logic std_logic std_logic std_logic std_logic std_logic std_logic
; ; ; ; ; ; ; );
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
architecture s t r u c t u r a l of i n p u t b u f f e r i s component r e g i s t e r _ 3 b i t port ( clk : in s t d _ l o g i c ; reset : in s t d _ l o g i c ; sensor_in : i n s t d _ l o g i c _ v e c t o r ( 2 downto 0 ) ; s e n s o r _ o u t : o u t s t d _ l o g i c _ v e c t o r ( 2 downto 0 ) ) ; end component r e g i s t e r _ 3 b i t ; s i g n a l c o m b i n e d _ i n , c o m b i n e d _ b e t w e e n , c o m b i n e d _ o u t : s t d _ l o g i c _ v e c t o r ( 2 downto 0 ) ; begin c o m b i n e d _ i n <= s e n s o r _ l _ i n & s e n s o r _ m _ i n & s e n s o r _ r _ i n ; r e g i s t e r 1 : r e g i s t e r _ 3 b i t p o r t map ( clk => c l k , reset => r e s e t , s e n s o r _ i n => c o m b i n e d _ i n , s e n s o r _ o u t => c o m b i n e d _ b e t w e e n ) ; r e g i s t e r 2 : r e g i s t e r _ 3 b i t p o r t map ( clk => c l k , reset => r e s e t , s e n s o r _ i n => c o m b i n e d _ b e t w e e n , s e n s o r _ o u t => c o m b i n e d _ o u t ) ; s e n s o r _ l _ o u t <= c o m b i n e d _ o u t ( 2 ) ; s e n s o r _ m _ o u t <= c o m b i n e d _ o u t ( 1 ) ; s e n s o r _ r _ o u t <= c o m b i n e d _ o u t ( 0 ) ; end a r c h i t e c t u r e s t r u c t u r a l ;
E.8 1 2 3 4
VHDL broncode van tijdbasis
library ieee ; use i e e e . s t d _ l o g i c _ 1 1 6 4 . a l l ; use i e e e . n u m e r i c _ s t d . a l l ;
E.9. MOTORCONTROLLER 5 6 7 8 9 10 11
67
entity timebase is g e n e r i c ( max_count : i n t e g e r : = 1 0 0 0 0 0 0 ) ; port ( clk : in s t d _ l o g i c ; reset : in s t d _ l o g i c ; count_out : o u t s t d _ l o g i c _ v e c t o r ( 3 1 downto 0 ) ); end e n t i t y t i m e b a s e ;
12 13 14 15 16 17 18 19 20 21 22 23 24 25
architecture behavioural of timebase i s s i g n a l c o u n t : u n s i g n e d ( 3 1 downto 0 ) ; begin process ( clk ) begin i f ( r i s i n g _ e d g e ( c l k ) ) then i f ( r e s e t = ’ 1 ’ ) or ( c o u n t = max_count ) t h e n c o u n t <= ( o t h e r s => ’ 0 ’ ) ; else c o u n t <= c o u n t + 1 ; end i f ; end i f ; end p r o c e s s ;
26 27 28
c o u n t _ o u t <= s t d _ l o g i c _ v e c t o r ( c o u n t ) ; end a r c h i t e c t u r e b e h a v i o u r a l ;
E.9 1 2 3
VHDL broncode van motorcontroller
l i b r a r y IEEE ; u s e IEEE . s t d _ l o g i c _ 1 1 6 4 . a l l ; use i e e e . n u m e r i c _ s t d . a l l ;
4 5 6 7 8 9
entity motor_controller is port ( clk : in s t d _ l o g i c ; reset : in s t d _ l o g i c ; d i r e c t i o n : in s t d _ l o g i c ; count_in : i n s t d _ l o g i c _ v e c t o r ( 3 1 downto 0 ) ;
10 11 12
pwm : out s t d _ l o g i c ) ; end e n t i t y m o t o r _ c o n t r o l l e r ;
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
architecture behaviour of m o t o r _ c o n t r o l l e r i s begin process ( clk ) begin i f r i s i n g _ e d g e ( c l k ) then i f r e s e t = ’1 ’ then pwm <= ’ 0 ’ ; e l s i f unsi gned ( c o u n t _ i n ) = 0 then pwm <= ’ 1 ’ ; e l s i f ( u n s i g n e d ( c o u n t _ i n ) = 45000 and d i r e c t i o n = ’ 0 ’ ) t h e n pwm <= ’ 0 ’ ; e l s i f ( u n s i g n e d ( c o u n t _ i n ) = 105000 and d i r e c t i o n = ’ 1 ’ ) t h e n pwm <= ’ 0 ’ ; end i f ; end i f ; end p r o c e s s ; end a r c h i t e c t u r e b e h a v i o u r ;
E.10 1 2 3
VHDL broncode van controller
l i b r a r y IEEE ; u s e IEEE . s t d _ l o g i c _ 1 1 6 4 . a l l ; use i e e e . n u m e r i c _ s t d . a l l ;
4 5 6 7
entity controller is port ( clk reset
: in : in
std_logic ; std_logic ;
: in : in
std_logic ; std_logic ;
8 9 10
sensor_l sensor_m
68 11 12
BIJLAGE E. VHDL BRONCODE BESTANDEN sensor_r mine
: in : in
xbee_received xbee_send
: i n s t d _ l o g i c _ v e c t o r ( 7 downto 0 ) ; : o u t s t d _ l o g i c _ v e c t o r ( 7 downto 0 ) ;
led sseg an
: o u t s t d _ l o g i c _ v e c t o r ( 7 downto 0 ) ; : o u t s t d _ l o g i c _ v e c t o r ( 7 downto 0 ) ; : o u t s t d _ l o g i c _ v e c t o r ( 3 downto 0 ) ;
count_in count_reset
: i n s t d _ l o g i c _ v e c t o r ( 3 1 downto 0 ) ; : out s t d _ l o g i c ;
std_logic ; std_logic ;
13 14 15 16 17 18 19 20 21 22 23 24 25
motor_l_reset : out s t d _ l o g i c ; m o t o r _ l _ d i r e c t i o n : out s t d _ l o g i c ;
26 27 28 29 30
motor_r_reset : out s t d _ l o g i c ; m o t o r _ r _ d i r e c t i o n : out s t d _ l o g i c ); end e n t i t y c o n t r o l l e r ;
31 32 33 34 35 36 37
architecture behaviour of c o n t r o l l e r i s type c o n t r o l l e r _ s t a t e i s ( logic_doen , vooruit , a c h t e r u i t , l i n k s _ f , l i n k s _ s , r e c h t s _ f , r e c h t s _ s ) ; signal state , new_state : c o n t r o l l e r _ s t a t e ; signal sensor : s t d _ l o g i c _ v e c t o r ( 2 downto 0 ) ; begin s e n s o r <= s e n s o r _ l & s e n s o r _ m & s e n s o r _ r ;
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
process ( clk ) begin i f r i s i n g _ e d g e ( c l k ) then i f r e s e t = ’1 ’ then s t a t e <= l o g i c _ d o e n ; else s t a t e <= n e w _ s t a t e ; end i f ; end i f ; end p r o c e s s ; process ( count_in , state , sensor , xbee_received ) v a r i a b l e i n p u t : s t d _ l o g i c _ v e c t o r ( 2 downto 0 ) : = " 000 " ; begin count_reset <= ’ 0 ’ ; m o t o r _ l _ r e s e t <= ’ 0 ’ ; m o t o r _ r _ r e s e t <= ’ 0 ’ ;
55 56 57
s s e g <= " 11111111 " ; an <= " 0111 " ;
58 59 60 61 62 63 64 65 66 67 68 69 70
i f ( unsigned ( c o u n t _ i n ) = 999999) then n e w _ s t a t e <= l o g i c _ d o e n ; else n e w _ s t a t e <= s t a t e ; end i f ; case s t a t e i s when l o g i c _ d o e n => count_reset <= ’ 1 ’ ; motor_l_reset <= ’ 1 ’ ; motor_r_reset <= ’ 1 ’ ; m o t o r _ l _ d i r e c t i o n <= ’ − ’; m o t o r _ r _ d i r e c t i o n <= ’ − ’;
71 72 73 74 75 76 77 78 79 80 81 82 83
i f x b e e _ r e c e i v e d ( 3 ) / = ’ 1 ’ and x b e e _ r e c e i v e d ( 2 downto 0 ) = " 000 " t h e n i n p u t := sensor ; else i n p u t : = x b e e _ r e c e i v e d ( 2 downto 0 ) ; end i f ; case input i s when " 000 " => n e w _ s t a t e <= l o g i c _ d o e n ; when " 001 " => n e w _ s t a t e <= r e c h t s _ f ; when " 010 " => n e w _ s t a t e <= a c h t e r u i t ;
E.11. ROBOT 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
when " 011 " => n e w _ s t a t e <= r e c h t s _ s ; when " 100 " => n e w _ s t a t e <= l i n k s _ f ; when " 101 " => n e w _ s t a t e <= v o o r u i t ; when " 110 " => n e w _ s t a t e <= l i n k s _ s ; when " 111 " => n e w _ s t a t e <= v o o r u i t ; when o t h e r s => n e w _ s t a t e <= l o g i c _ d o e n ; end c a s e ; s s e g <= " 10110110 " ; when v o o r u i t => m o t o r _ l _ d i r e c t i o n <= ’ 1 ’ ; m o t o r _ r _ d i r e c t i o n <= ’ 0 ’ ; sseg <= " 11001001 " ; when a c h t e r u i t => m o t o r _ l _ d i r e c t i o n <= ’ 0 ’ ; m o t o r _ r _ d i r e c t i o n <= ’ 1 ’ ; sseg <= " 11100011 " ; when l i n k s _ f => motor_l_reset <= ’ 1 ’ ; m o t o r _ l _ d i r e c t i o n <= ’ − ’; m o t o r _ r _ d i r e c t i o n <= ’ 0 ’ ; sseg <= " 11111000 " ; when l i n k s _ s => m o t o r _ l _ d i r e c t i o n <= ’ 0 ’ ; m o t o r _ r _ d i r e c t i o n <= ’ 0 ’ ; sseg <= " 10111011 " ; when r e c h t s _ f => motor_r_reset <= ’ 1 ’ ; m o t o r _ l _ d i r e c t i o n <= ’ 1 ’ ; m o t o r _ r _ d i r e c t i o n <= ’ − ’; sseg <= " 11001110 " ; when r e c h t s _ s => m o t o r _ l _ d i r e c t i o n <= ’ 1 ’ ; m o t o r _ r _ d i r e c t i o n <= ’ 1 ’ ; sseg <= " 10101111 " ; end c a s e ; end p r o c e s s ; xbee_send <= " 0000 " & mine & s e n s o r _ l & s e n s o r _ m & s e n s o r _ r ; l e d ( 3 downto 0 ) <= x b e e _ r e c e i v e d ( 3 downto 0 ) ; led (7) <= r e s e t ; led (6) <= mine ; end a r c h i t e c t u r e b e h a v i o u r ;
E.11 1 2
69
VHDL broncode van robot
l i b r a r y IEEE ; u s e IEEE . s t d _ l o g i c _ 1 1 6 4 . a l l ;
3 4 5 6 7 8
entity robot is port ( s e n s o r _ l sensor_m sensor_r sensor_mijn
: : : :
in in in in
std_logic std_logic std_logic std_logic
xbee_received xbee_send write_data read_data
: : : :
in out out out
s t d _ l o g i c _ v e c t o r ( 7 downto 0 ) ; s t d _ l o g i c _ v e c t o r ( 7 downto 0 ) ; std_logic ; std_logic ;
led sseg an
: o u t s t d _ l o g i c _ v e c t o r ( 7 downto 0 ) ; : o u t s t d _ l o g i c _ v e c t o r ( 7 downto 0 ) ; : o u t s t d _ l o g i c _ v e c t o r ( 3 downto 0 ) ;
reset clk
: in : in
motor_left
: out s t d _ l o g i c ;
; ; ; ;
9 10 11 12 13 14 15 16 17 18 19 20
std_logic ; std_logic ;
21 22
70 23 24
BIJLAGE E. VHDL BRONCODE BESTANDEN
motor_right end e n t i t y r o b o t ;
: out s t d _ l o g i c ) ;
25 26 27 28 29
architecture s t r u c t u r a l of robot i s component i n p u t b u f f e r i s port ( clk : in s t d _ l o g i c ; reset : in s t d _ l o g i c ;
30 31 32 33
sensor_l_in sensor_m_in sensor_r_in
: in : in : in
std_logic ; std_logic ; std_logic ;
34 35 36 37 38 39 40 41 42
s e n s o r _ l _ o u t : out s t d _ l o g i c ; sensor_m_out : out s t d _ l o g i c ; s e n s o r _ r _ o u t : out s t d _ l o g i c ); end component i n p u t b u f f e r ; component c o n t r o l l e r i s port ( clk : in reset : in
std_logic ; std_logic ;
43 44 45 46 47
in in in in
sensor_l sensor_m sensor_r mine
: : : :
std_logic std_logic std_logic std_logic
; ; ; ;
xbee_received xbee_send
: i n s t d _ l o g i c _ v e c t o r ( 7 downto 0 ) ; : o u t s t d _ l o g i c _ v e c t o r ( 7 downto 0 ) ;
led sseg an
: o u t s t d _ l o g i c _ v e c t o r ( 7 downto 0 ) ; : o u t s t d _ l o g i c _ v e c t o r ( 7 downto 0 ) ; : o u t s t d _ l o g i c _ v e c t o r ( 3 downto 0 ) ;
count_in count_reset
: i n s t d _ l o g i c _ v e c t o r ( 3 1 downto 0 ) ; : out s t d _ l o g i c ;
48 49 50 51 52 53 54 55 56 57 58 59 60
motor_l_reset : out s t d _ l o g i c ; m o t o r _ l _ d i r e c t i o n : out s t d _ l o g i c ;
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
motor_r_reset : out s t d _ l o g i c ; m o t o r _ r _ d i r e c t i o n : out s t d _ l o g i c ); end component c o n t r o l l e r ; component t i m e b a s e g e n e r i c ( max_count : i n t e g e r : = 1 0 0 0 0 0 0 ) ; port ( clk : in s t d _ l o g i c ; reset : in s t d _ l o g i c ; c o u n t _ o u t : o u t s t d _ l o g i c _ v e c t o r ( 3 1 downto 0 ) ) ; end component t i m e b a s e ; component m o t o r _ c o n t r o l l e r i s port ( clk : in s t d _ l o g i c ; reset : in s t d _ l o g i c ; d i r e c t i o n : in s t d _ l o g i c ; count_in : i n s t d _ l o g i c _ v e c t o r ( 3 1 downto 0 ) ;
77 78 79 80 81 82 83 84
pwm : out s t d _ l o g i c ); end component m o t o r _ c o n t r o l l e r ; component m i j n s e n s o r i s port ( clk : in s t d _ l o g i c ; reset : in s t d _ l o g i c ; sensor : in s t d _ l o g i c ;
85 86 87 88
mijn : out s t d _ l o g i c ); end component m i j n s e n s o r ;
89 90 91 92 93 94
s i g n a l s e n s o r _ l _ o u t , s e n s o r _ m _ o u t , s e n s o r _ r _ o u t , mine signal motor_l_reset , motor_l_direction , motor_r_reset , motor_r_direction signal count_reset signal count downto 0 ) ; begin
: : : :
std_logic ; std_logic ; std_logic ; s t d _ l o g i c _ v e c t o r (31
E.12. TOPLEVEL 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
71
input : inputbuffer p o r t map ( c l k => c l k , reset => r e s e t , s e n s o r _ l _ i n => s e n s o r _ l , s e n s o r _ m _ i n => sensor_m , s e n s o r _ r _ i n => s e n s o r _ r , s e n s o r _ l _ o u t => s e n s o r _ l _ o u t , s e n s o r _ m _ o u t => s e n s o r _ m _ o u t , s e n s o r _ r _ o u t => s e n s o r _ r _ o u t ) ; contr : controller p o r t map ( c l k => c l k , reset => r e s e t , sensor_l => s e n s o r _ l _ o u t , sensor_m => s e n s o r _ m _ o u t , sensor_r => s e n s o r _ r _ o u t , mine => mine , xbee_received => x b e e _ r e c e i v e d , xbee_send => x b e e _ s e n d , led => l e d , sseg => s s e g , an => an , count_in => c o u n t , count_reset => c o u n t _ r e s e t , motor_l_reset => m o t o r _ l _ r e s e t , m o t o r _ l _ d i r e c t i o n => m o t o r _ l _ d i r e c t i o n , motor_r_reset => m o t o r _ r _ r e s e t , m o t o r _ r _ d i r e c t i o n => m o t o r _ r _ d i r e c t i o n ) ; timeb : timebase p o r t map ( c l k => c l k , reset => c o u n t _ r e s e t , c o u n t _ o u t => c o u n t ) ; motor_l : motor_controller p o r t map ( c l k => c l k , reset => m o t o r _ l _ r e s e t , d i r e c t i o n => m o t o r _ l _ d i r e c t i o n , c o u n t _ i n => c o u n t , pwm => m o t o r _ l e f t ) ; motor_r : m o t o r _ c o n t r o l l e r p o r t map ( c l k => c l k , reset => m o t o r _ r _ r e s e t , d i r e c t i o n => m o t o r _ r _ d i r e c t i o n , c o u n t _ i n => c o u n t , pwm => m o t o r _ r i g h t ) ; mines : m i j n s e n s o r p o r t map ( c l k => c l k , r e s e t => r e s e t , s e n s o r => s e n s o r _ m i j n , mijn => mine ) ;
143 144 145 146
w r i t e _ d a t a <= ’ 1 ’ ; r e a d _ d a t a <= ’ 1 ’ ; end a r c h i t e c t u r e s t r u c t u r a l ;
E.12 1 2
VHDL broncode van toplevel
l i b r a r y IEEE ; u s e IEEE . s t d _ l o g i c _ 1 1 6 4 . a l l ;
3 4 5 6 7 8
entity toplevel is port ( clk reset_sw reset_btn
: in : in : in
std_logic ; std_logic ; std_logic ;
9 10 11 12 13
sensor_l sensor_m sensor_r sensor_mijn
: : : :
in in in in
std_logic std_logic std_logic std_logic
; ; ; ;
14 15 16 17
motor_left : out s t d _ l o g i c ; m o t o r _ r i g h t : out s t d _ l o g i c ;
72 18 19 20 21 22 23 24
BIJLAGE E. VHDL BRONCODE BESTANDEN rx tx led sseg an
: : : : :
in out out out out
std_logic ; −−i n p u t b i t std_logic ; −−o u t p u t b i t s t d _ l o g i c _ v e c t o r ( 7 downto s t d _ l o g i c _ v e c t o r ( 7 downto s t d _ l o g i c _ v e c t o r ( 3 downto
stream stream 0 ) ; −−r e c e i v e d b y t e 0 ) ; −−s e v e n s e g m e n t LED d i s p l a y 0 ) −−a n o d e s o f s e v e n s e g m e n t LED d i s p l a y
); end e n t i t y t o p l e v e l ;
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
architecture s t r u c t u r a l of component u a r t port ( clk , r e s e t rx tx write_data read_data xbee_send xbee_received end component u a r t ; component r o b o t port ( s e n s o r _ l sensor_m sensor_r sensor_mijn xbee_received xbee_send write_data read_data led sseg an reset clk motor_left motor_right end component r o b o t ;
toplevel is : : : : : : :
in in out in in in out
std_logic ; std_logic ; std_logic ; std_logic ; std_logic ; s t d _ l o g i c _ v e c t o r ( 7 downto 0 ) ; s t d _ l o g i c _ v e c t o r ( 7 downto 0 ) ) ;
: : : : : : : : : : : : : : :
in in in in in out out out out out out in in out out
std_logic ; std_logic ; std_logic ; std_logic ; s t d _ l o g i c _ v e c t o r (7 s t d _ l o g i c _ v e c t o r (7 std_logic ; std_logic ; s t d _ l o g i c _ v e c t o r (7 s t d _ l o g i c _ v e c t o r (7 s t d _ l o g i c _ v e c t o r (3 std_logic ; std_logic ; std_logic ; std_logic ) ;
downto 0 ) ; downto 0 ) ;
downto 0 ) ; downto 0 ) ; downto 0 ) ;
53 54 55 56 57 58
signal reset : std_logic ; s i g n a l x b e e _ r e c e i v e d , x b e e _ s e n d : s t d _ l o g i c _ v e c t o r ( 7 downto 0 ) ; signal write_data , read_data : std_logic ; begin r e s e t <= r e s e t _ b t n or r e s e t _ s w ;
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
XBEE : u a r t p o r t map ( c l k reset rx tx xbee_send write_data read_data xbee_received RBT : r o b o t p o r t map ( s e n s o r _ l sensor_m sensor_r sensor_mijn xbee_received xbee_send write_data read_data led sseg an reset clk motor_left motor_right end a r c h i t e c t u r e s t r u c t u r a l ;
=> => => => => => => =>
clk , reset , rx , tx , xbee_send , write_data , read_data , xbee_received ) ;
=> => => => => => => => => => => => => => =>
sensor_l , sensor_m , sensor_r , sensor_mijn , xbee_received , xbee_send , write_data , read_data , led , sseg , an , reset , clk , motor_left , motor_right ) ;
E.12. TOPLEVEL
73