Powered by TCPDF (www.tcpdf.org)
Academiejaar 2013–2014
Faculteit Ingenieurswetenschappen en Architectuur Valentin Vaerwyckweg 1 – 9000 Gent
Ontwikkelen van een educatief verantwoorde grafische programmeertaal voor microcontrollers
Masterproef voorgedragen tot het behalen van het diploma van Master in de industriële wetenschappen: informatica
Simon RUBBEN Promotoren: dr. Germán HURTADO dr. ir. Francis WYFFELS (Dwengo vzw) Begeleider:
dr. ir. Wim HEIRMAN (Dwengo vzw)
Woord vooraf Voor deze masterproef wil ik graag enkele mensen in het bijzonder bedanken. Ten eerste Francis Wyffels en Wim Heirman van Dwengo vzw. Ik wil hen niet enkel bedanken voor de hulp tijdens deze masterproef, maar ook voor het interessante project en hun vrijwillige inzet. Dit project geeft niet enkel nieuwe mensen de kans om op een vlottere manier te leren programmeren, maar het gaf mij ook de kans om eens te ontwikkelen voor een nieuw soort doelpubliek. Daarnaast wil ik mijn interne promotor, Germán Hurtado, ook bedanken voor de vlotte begeleiding en tijdige bijsturingen. Ook bedank ik Jan-René Deplorez voor de samenwerking met de gekoppelde masterproef. Ik wil zeker en vast ook iedereen bedanken die mij gesteund heeft tijdens het ontwikkelingsproces.
ii
Inleiding Technologie speel een belangrijke rol in onze maatschappij. Programmeren is hier een heel belangrijk onderdeel van. De stap naar programmeren ligt voor velen nog te hoog en in middelbare en lagere scholen wordt dit te weinig aangeleerd. Deze masterproef ontwikkelt enkele onderdelen van Dwengo Blocks, een grafische programmeertaal voor microcontrollers. Door het gebruik van een grafische programmeertaal kan de drempel om te leren programmeren verlaagd worden. Deze grafische programmeertaal focust zich vooral op het gebruik van microcontrollers en wil door een flexibele structuur compatibel worden met meerdere microcontrollers dan enkel deze van Dwengo. Daarnaast is er ook de mogelijkheid om een Dwengo-microcontroller te simuleren. Deze masterproef dient niet als handleiding om te leren programmeren, het legt de volledige werking van de ontwikkelde stukken uit. Hiervoor is programmeerkennis vereist.
iii
Samenvatting Dwengo Blocks is een grafische programmeertaal voor microcontrollers en in het bijzonder voor een Dwengo-microcontroller. Het dient om beginnende programmeurs op een eenvoudigere manier te laten programmeren in vergelijking met tekstuele programmeertalen. Er moet namelijk geen rekening gehouden worden met syntactische problemen en er kan volledig gefocust worden op de programmastructuur. Daarnaast zijn er door het gebruik van microcontrollers ook snel fysieke resultaten te zien. Door slechts enkele lijntjes code kunnen er snel effecten gezien worden op de hardware, zoals het flikkeren van lichtjes of het vooruitrijden door de motoren. Deze masterproef ontwikkelt twee grote onderdelen van Dwengo Blocks. Ten eerste de compatibiliteit met verschillende microcontrollers. Dit houdt in dat verschillende microcontrollerbibliotheken op een generieke manier aangeboden kunnen worden en dat deze automatisch gebruikt kunnen worden bij Dwengo Blocks. Voor dit deel worden de volgende technologiën gebruikt: XML, XSLT, JSON en PHP. Daarnaast ontwikkelt deze masterproef ook een simulatie voor de Dwengo-microcontroller die eenvoudig uitbreidbaar is op vlak van functionaliteit. Ook ligt de optie open om andere microcontrollers te simuleren. Omdat Dwengo Blocks een webapplicatie is, is JavaScript de belangrijkste technologie. Als uitbreiding wordt er ook nog kort gekeken naar het gebruik van open bron compiler SDCC, zodanig dat er afgestapt kan worden van de gebruikte gesloten en commerciële compiler voor het compileren van een Dwengo-programma. Dwengo vzw is namelijk voorstander de open bron wereld, daarom zal dit volledige project ook vrij beschikbaar zijn.
iv
Abstract Dwengo Blocks is a graphical programming language for microcontrollers and especially for a Dwengo microcontroller. It is used by persons who are rather unexperienced with programming and it enables them to learn programming more smoothly than with textual programming. They are not confronted with syntactical problems and hence it allows them to fully focus on the program flow. Furthermore it is easy to see physical results when using microcontrollers. With just a few lines of code, one can see the effects on the hardware like flickering lights or a moving controller due to the motors with wheels. This thesis develops two large parts of Dwengo Blocks. Firstly, the compatibility with different microcontrollers. This means that libraries of every microcontroller can be presented and the generic software will process them to be used by Dwengo Blocks. For this part the following technologies are used: XML, XSLT, JSON en PHP. Secondly, this thesis develops a simulation for a Dwengo microcontroller. This simulation is flexible in terms of functionality. The option to simulate other microcontrollers is also open. Since Dwengo Blocks is a web application, the main technology is JavaScript. In addition to the above, the use of the open source compiler SDCC will also be examined. This is necessary in order to abandon the closed and commercial compiler initially used to compile a Dwengo program. Dwengo vzw advocates for open source technology and that is why the complete source of the project will be available for free.
v
Inhoudsopgave Woord vooraf
ii
Inleiding
iii
Samenvatting
iv
Abstract
v
Inhoudsopgave
vii
1 Situering en doelstelling 1.1 Opdrachtgever . . . . . . . . 1.2 Opdracht . . . . . . . . . . . . 1.3 Grafisch programmeren . . . 1.3.1 Voor- en nadelen . . . . 1.3.2 Bestaande omgevingen 1.4 Doelgroep . . . . . . . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
. . . . . .
8 8 8 10 10 11 12
2 Oude situatie met problemen 2.1 Bibliotheken inladen . . . . . . . . . . . . . 2.2 Grafische User Interface . . . . . . . . . . . 2.2.1 Boomstructuur . . . . . . . . . . . . . 2.2.2 Simulatie . . . . . . . . . . . . . . . . 2.3 Simulatie . . . . . . . . . . . . . . . . . . . . 2.3.1 Engine.js . . . . . . . . . . . . . . . . 2.3.2 ViewBoard.js . . . . . . . . . . . . . . 2.3.3 Algemeen . . . . . . . . . . . . . . . . 2.4 Andere microcontrollerbibliotheken . . . . 2.5 Samenvatting en inleiding nieuwe stukken
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
14 14 16 16 16 17 17 18 18 18 18
. . . . . . . .
21 22 22 22 25 25 28 29 29
3 Bibliotheken inladen 3.1 Headerbestanden parsen . 3.1.1 Reguliere expressies 3.1.2 Doxygen . . . . . . . 3.2 XML converteren . . . . . . 3.2.1 XSLT-conversie . . . . 3.2.2 Resultaat . . . . . . . 3.2.3 Conversiescript . . . 3.3 Webservice . . . . . . . . . .
. . . . . . . .
. . . . . .
. . . . . . . .
. . . . . .
. . . . . . . .
. . . . . .
. . . . . . . .
. . . . . .
. . . . . . . .
. . . . . .
. . . . . . . .
. . . . . .
. . . . . . . .
vi
. . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
. . . . . . . .
INHOUDSOPGAVE
vii
3.4 Platformonafhankelijkheid . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 4 Simulatie 4.1 C porten naar JavaScript . . . . . 4.2 Functies handmatig simuleren . 4.2.1 Simulatiekern en -objecten 4.2.2 Simulatiemotor . . . . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
. . . .
31 31 32 32 35
5 Compilatie 39 5.1 GUI naar tekstuele programmeertaal . . . . . . . . . . . . . . . . . . . . . . . . . . 39 5.2 C compilatie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 6 Besluit 6.1 Bespreking eindresultaat . 6.1.1 Inladen bibliotheken 6.1.2 Simulatie . . . . . . . 6.1.3 Extra . . . . . . . . . 6.2 Mogelijke uitbreidingen . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
. . . . .
43 43 43 43 44 45
Lijst met figuren
46
Lijst met codevoorbeelden
47
Literatuurlijst
48
A Oude Simulatie code A.1 Grafische code . . A.2 XML-code . . . . . A.3 Simulatiecode . . .
Binair Tellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
51 52 53 57
B Conversie Doxygen output
58
C Handleiding: Bibliotheken verwerken en gegevens opvragen
61
D Handleiding: Uitbreiden simulatie
65
Hoofdstuk 1
Situering en doelstelling 1.1
Opdrachtgever
Deze masterproef gaat uit van Dwengo vzw (vereniging zonder winstoogmerk). Dwengo wil iedereen aanzetten om te experimenteren met microcontrollers, hiervoor hebben ze zelf ook een Dwengo-experimenteerbord ontwikkeld. De oprichters hebben allemaal een achtergrond in de computerwetenschappen of elektronica aan Universiteit Gent. Dwengo richt zich hoofdzakelijk op middelbare (en lagere) scholen, dit zijn beginnende programmeurs. Ze willen dat de technologie meer aandacht krijgt bij kinderen en adolescenten, aangezien een basiskennis programmeren is heel handig in onze maatschappij vol met computers. Door de basis van het programmeren aan te leren met microcontrollers zijn er snel fysieke resultaten te zien met slechts enkele lijntjes code. Dit maakt het leren programmeren ook veel aangenamer. Dwengo is ook enorme voorstander van de open bron wereld, alle broncode is dan ook vrij beschikbaar of zal vrij beschikbaar worden.
1.2
Opdracht
Om de stap naar het programmeren nog kleiner te maken, ontwikkelde Dwengo een bètaversie van Dwengo Blocks (Fig. 1.1). Dit is een grafische programmeertaal voor de microcontrollers van Dwengo. Dit houdt in dat code niet meer enkel bestaat uit tekst, maar ook uit figuren, symbolen, tekeningen. . . Hierdoor is de drempel om te leren programmeren een stuk lager, code visueel voorstellen is namelijk een stuk eenvoudiger. Deze bètaversie werd al snel in vele scholen gebruikt, ook in het buitenland. Deze bètaversie zat echter nog vol bugs en is ook moeilijk uitbreidbaar. Bij het verkeerd gebruiken of door de vele bugs werd er al vaak eens gevloekt omdat zaken anders verliepen dan verwacht. Op dit punt zijn twee masterproeven uitgeschreven, waaronder deze masterproef. Samen met Jan-René Deplorez [19], student Master of Science in de industriële wetenschappen: elektronica-ICT (multimedia en informatietechnologie - major Future media) aan Universiteit Gent, kregen wij de opdracht om Dwengo Blocks opnieuw te ontwikkelen zodat alle bugs eruit
8
HOOFDSTUK 1. SITUERING EN DOELSTELLING
9
Fig. 1.1: Bètaversie van Dwengo Blocks
waren en de omgeving veel flexibeler werd. Deze flexibiliteit houdt in dat het veel gemakkelijker moet zijn om nieuwe programmeerfuncties toe te voegen, extra opties voor sensoren toe te voegen aan de microcontroller en zelfs zonder problemen microcontrollerbibliotheken van andere microcontrollers zoals deze van Arduino te gebruiken. Kort gezegd is de grens tussen de twee masterproeven de volgende: Jan-René ontwikkelt de Grafische User Interface (GUI) [19], Simon zorgt in deze masterproef voor de compatibiliteit met de microcontrollerbibliotheken en de simulatie. Voor de microcontrollerbibliotheken is het belangrijk dat dit generiek gebeurt, dit wil zeggen dat het systeem niet weet welke bibliotheken toegevoegd worden en deze los daarvan moet kunnen verwerken. Het volledige project, de combinaties van de beide masterproeven, zal ook vrij beschikbaar zijn. Bij open bron software zijn er dan ook twee soorten gebruikers: gebruikers en ontwikkelaars. De gewone gebruikers zullen leren programmeren met de Dwengo Blocks. De ontwikkelaars zullen daarentegen eigen bibliotheken toevoegen, simulatie uitbreiden, verbeteringen aanbrengen aan de software enzovoort.
HOOFDSTUK 1. SITUERING EN DOELSTELLING
1.3
10
Grafisch programmeren
Er is al veel onderzoek gebeurd naar grafische programmeertalen1 . Het is handig om hier eerst wat meer vertrouwd mee te zijn. Uit onderzoek blijkt dat de efficiëntie waarmee problemen worden opgelost afhangt van de manier waarop een probleem gepresenteerd wordt [40]. Tekstuele programmacode is bijvoorbeeld gemakkelijker te begrijpen indien er gebruikgemaakt wordt van uitgelijnde tabs, kleuren. . . Grafische programmeertalen gaan nog een stap verder. Hiermee wordt het probleem, de programmacode, nog eenvoudiger voorgesteld zodat de gebruiker vlotter bestaande code kan begrijpen en nieuwe code kan schrijven. Syntactische fouten zijn namelijk een van de ergernissen bij veel (beginnende) programmeurs [13].
1.3.1
Voor- en nadelen
Een van de belangrijkste voordelen van grafisch programmeren is dat beginnende programmeurs zich veel minder moeten aantrekken van belangrijke details zoals punten, komma’s of haakjes. Een deftige grafische programmeertaal zorgt hier achter de schermen namelijk zelf voor. De omgeving kan dan ook beperkingen opleggen op het gebruik van bepaalde blokken of figuren. Bij de programmeertaal Scratch [35] passen zo bijvoorbeeld niet alle blokken in elkaar, waardoor de gebruiker begeleid wordt om syntactisch correcte code te schrijven. Uit verschillende studies [34, 40] blijkt ook dat grafische programmeren interessanter wordt bij complexere programma’s. Hier is het vooral de bedoeling om Dwengo Blocks te gebruiken om het programmeren aan te leren. Dezelfde studies tonen ook aan dat kleinere problemen sneller worden opgelost met grafische programmeertalen. Er is ook onderzoek gebeurd naar het gebruik van grafische taal tegenover een tekstuele taal in verschillende stadia in het programma. Enerzijds naar het schrijven van een volledig nieuw programma en anderzijds naar het aanpassen van een bestaand programma [13]. Hieruit blijkt dat grafische talen meer winst halen op vlak van gebruiksgemak tegenover tekstuele talen bij het aanpassen van een programma. Er zijn dus meer gebruikers die het grafische kiezen bij het aanpassen dan bij het schrijven van een nieuw programma. Bij beide situaties wint de grafische programmeertaal wel. Programma’s doorgronden en aanpassen is ook iets wat vaak voorkomt bij het leren programmeren, voorgaande studie is hiervoor dus heel positief. Het grafisch programmeren heeft echter ook wat nadelen. De meeste grafische programmeertalen werken via een bottom-up aanpak, dit wil zeggen dat ze programma’s telkens meer en meer uitbreiden in plaats eerst eens na te denken over het geheel. Voor kleine programma’s kan dit geen kwaad, maar hier wordt wel de basis gelegd om later te programmeren met trial and error [13]. Het is belangrijk om bij grotere programma’s na te denken over het ontwerp om zo een flexibel programma te hebben, waar fouten ook gemakkelijk op te sporen zijn. Afhankelijk van de grafische programmeertaal, kan de stap naar tekstuele code ook groot zijn. Bij het ontwerpen van de grafische taal moet men ook rekening houden met de doelgroep en zijn wensen. Is het de bedoeling om enkel de programmeertechnieken en -structuren aan 1
De Engelse en meer voorkomende naam is Visual Programming Language (VPL)
HOOFDSTUK 1. SITUERING EN DOELSTELLING
11
te leren zoals lussen en if-else structuren? Of is het de bedoeling om nadien vlot met een bepaalde tekstuele programmeertaal te kunnen werken? Bij het onderzoek van T. Booth and S. Stumpf [13] naar het gebruik van een grafische programmeeromgeving bij Arduino, vroegen ze nadien ook reacties over het grafisch programmeren tegenover het tekstueel programmeren. Deze zijn samengevat in 2 figuren, enerzijds op het tekstueel programmeren (Fig. 1.2) en anderzijds op het grafisch programmeren (Fig. 1.3). De gebruikers konden kiezen uit een grote set woorden. Bij het tekstueel programmeren werden 62 positieve en 69 negatieve woorden gekozen. Bij het visueel programmeren was het verschil duidelijker, hier werden 101 positieve en 37 negatieve gekozen. De grote van de woorden in de figuren wijst op de frequentie van de gekozen woorden. Hieruit is duidelijk te zien dat de reacties op het grafisch programmeren positiever (grijs) zijn dan het tekstueel.
Fig. 1.2: Reacties op het tekstueel programmeren, positieve (grijs) en negatieve (zwart) [13]
Fig. 1.3: Reacties op het visueel programmeren, positieve (grijs) en negatieve (zwart) [13]
1.3.2
Bestaande omgevingen
Er bestaan al verschillende grafische programmeertalen, elk met hun eigen doel. Zo zijn er de talen Blockly [4], Kodu [22] en Scratch [35] die op een speelse wijze kinderen de basistechnieken van het programmeren aanleren. Dit gebeurt door een eigen vereenvoudigde taal. De stap naar een tekstuele taal is nog iets groter, maar je zou al vlot moeten kunnen omgaan met
HOOFDSTUK 1. SITUERING EN DOELSTELLING
12
while- en if-structuren en dergelijke. Deze talen stimuleren ook probleemoplossend denken op een creatieve manier. Op voorgaande talen zijn er ook nog anderen gebaseerd met een meer praktische toepassing. Zo is er bijvoorbeeld Modkit [24] die gebaseerd is op Scratch, voor het programmeren van een robot, en App Inventor for Android [1] die gebasseerd is op Blockly 2 , voor het ontwikkelen van Android-apps. Vervolgens heb je ook talen zoals Flowcode [14] die gebruik maken van flowcharts (stroomdiagrammen) om microprocessoren te programmeren. Flowcode verwacht echter wel dat de gebruiker programmeerkennis heeft. Het wil de microprocessoren vlotter kunnen programmeren, maar blijft enorm veel opties hebben waardoor er veel kennis van de gebruiker wordt verwacht. De oude versie van Dwengo Blocks is een combinatie van bovenstaande talen. Het wilt iedereen in contact brengen met programmeren. De taal maakt gebruik van flowcharts zoals Flowcode, maar is veel toegankelijker voor het brede publiek waaronder beginnende programmeurs. Om het programmeren wat speelser te maken en toch snel fysieke resultaten te zien, heeft Dwengo een eigen microcontroller ontwikkeld. Elke lijn code wordt bijna letterlijk vertaald naar een grafische voorstelling, waardoor Dwengo Blocks ideaal is om de drempel naar het tekstuele programmeren te overwinnen.
1.4
Doelgroep
Het is algemeen geweten dat kinderen vlotter zaken opnemen dan volwassenen. Er zijn veel voorstanders om programmeren een verplicht onderdeel te maken in het onderwijsprogramma. Zo is er bijvoorbeeld de website code.org die de basis van programmeren aanleert in verschillende stappen. Je kunt hier ook een petitie ondertekenen indien je het eens bent dat iedereen in elke school de kans moet krijgen om te leren programmeren. Het Verenigd Koninkrijk start bijvoorbeeld in september 2014 met alle kinderen van 5 tot en met 14 computerwetenschappen te geven, meer bepaald het programmeren en de manier waarop computers werken [39]. Onze huidige maatschappij kan niet meer zonder computers, dus dit is een belangrijke trend in Europa. In Vietnam (en Azië) is het niveau van de oefeningen van het laatste jaar middelbaar zelfs gelijk aan het niveau van de testen die sollicitanten bij Google voorgeschoteld krijgen. In België staan wij op dit vlak achter. Maar ook hier zijn er velen die het programmeren in de eindtermen van het onderwijs willen zien [30, 20]. Dwengo probeert hierop in te spelen met hun microcontroller en grafische programmeertaal, door de drempel te verlagen zal de stap makkelijker gezet kunnen worden. Dwengo is dan ook voornamelijk gericht op scholen (en jonge programmeurs). Grafische programmeertalen nemen vooral de tekstuele en syntactische drempel weg. Hierdoor kan er enkel gefocust worden op programmeertechnieken. Door dit in een speels jasje te gieten, vinden kinderen het snel leuk en gemakkelijk om ermee te werken en kunnen ze vlot mooie resultaten afleveren [3, 32, 31]. Programmeren en eigenlijk de hele computerwereld wordt nog vaak aanzien als een mannenwereld. De interesse wordt dus ook sneller bij jongens opgewekt. Hierdoor zijn er ook 2
Dit is zo vanaf vanaf de tweede versie. De eerste versie was gebasseerd op de Open Blocks Java bibliotheek [27] die zelf invloed had van de programmeertaal Scratch
HOOFDSTUK 1. SITUERING EN DOELSTELLING
13
een aantal initiatieven zoals Girl Develop It [15] en Girls Who Code [16] die vrouwen helpen met het leren programmeren. Girls Who Code is vooral gericht op meisjes tussen 13 en 17. Deze initiatieven tonen niet enkel het genderverschil aan, maar ook de nood aan het programmeren bij iedereen.
Hoofdstuk 2
Oude situatie met problemen In dit hoofdstuk wordt de oude situatie van Dwengo Blocks beschreven, opgesplitst in verschillende delen. Omdat de ontwikkeling van de nieuwe versie van Dwengo Blocks opgesplitst is in twee masterproeven, is niet elk onderdeel even belangrijk voor deze masterproef. Voor de volledigheid worden alle delen hier toch aangehaald om een mooi overzicht te krijgen van het volledige project.
2.1
Bibliotheken inladen
Voor er gestart kan worden met het programmeren van een microcontroller, is het belangrijk om te beschikken over de microcontrollerbibliotheken. Of het nu gaat over een Dwengomicrocontroller of een Arduino-microcontroller, voor beiden zijn er bibliotheken beschikbaar. In het geval van Dwengo zijn de bibliotheken in de programmeertaal C geschreven. Het programmeren in een grafische omgeving verandert dit niet. Er moet bepaald worden welke functies er beschikbaar zijn voor de gebruiker en op welke manier. Dwengo Blocks wilt rechtstreeks vertaling naar de tekstuele code mogelijk maken. Daardoor moet er dus eerst een rechtstreekse koppeling bestaan tussen de microcontrollerbibliotheken en de grafische omgeving. In de oude situatie bestond er geen rechtstreekse koppeling tussen de bronbestanden uit de bibliotheken en de grafische omgeving. Er werd vertrokken vanuit de simulatie. Elk bestand in de bibliotheek met functies die beschikbaar werd gesteld voor de grafische omgeving, moest eerst handmatig in JavaScript geschreven worden. De declaraties van de functies werden dan samen met hun annotaties (zie Fig. 2.3) geanalyseerd en zo kon men de functies beschikbaar stellen voor de gebruiker. De implementatie van de functie bepaalde wat er moest gebeuren tijdens de simulatie. Fig. 2.1 toont welke bestanden handmatig vertaald werden naar JavaScript om zo beschikbaar te stellen in de grafische programmeeromgeving. In Fig. 2.2 is de C-code te zien van de functie setSpeedMotor1(short speed) uit het bestand dwengoMotor.c. Zoals de naam al doet vermoeden, kan je hiermee de snelheid van de eerste motor instellen. In Fig. 2.3 is de code te zien die instaat voor de simulatie van de motor. Deze moest, zoals eerder vermeld, handmatig geschreven worden voor elke functie. De declaratie van de functie werd dan geanalyseerd en daarmee kon voor elke functie een blokje gegenereerd worden voor de grafische omgeving zoals te zien in Fig. 2.4.
14
HOOFDSTUK 2. OUDE SITUATIE MET PROBLEMEN
15
Fig. 2.1: bibliotheekbestanden vs Dwengo Blocks bestanden
Fig. 2.3: Voorbeeldfunctie JavaScript
Fig. 2.2: Voorbeeldfunctie C Fig. 2.4: Voorbeeldfunctie Dwengo Blocks
Het belangrijkste nadeel is dat alle functies die men wou gebruiken, ook gesimuleerd moesten worden. Voor functies die instonden voor de functionaliteit van lichtsensoren bijvoorbeeld, was dit al een stuk moeilijker. Indien er nieuwe sensoren of andere uitbreidingen werden toegevoegd aan de microcontroller met bijhorende functionaliteit, moesten alle bijhorende functies handmatig vertaald worden naar JavaScript. Dit was natuurlijk niet generiek en als men een nieuwe microcontroller zoals Arduino wou programmeren met deze grafische programmeeromgeving, mocht er bijna volledig opnieuw begonnen worden. Er moest dus gekeken worden naar een generieke methode om functies beschikbaar te stellen voor de grafische programmeeromgeving. Daarnaast moest het ook eenvoudig zijn om een nieuwe functie toe te voegen aan de bibliotheken en zonder veel manuele tussenkomst deze beschikbaar te stellen aan de grafische omgeving.
HOOFDSTUK 2. OUDE SITUATIE MET PROBLEMEN
2.2
16
Grafische User Interface
Nadat de functies beschikbaar zijn voor de grafische programmeeromgeving, moeten deze worden aangeboden en beschikbaar gesteld worden aan de gebruiker. Dit gebeurt door middel van een GUI (Grafische User Interface). In de oude versie bestond deze uit twee delen, namelijk de boomstructuur voor het programmeren enerzijds en de simulatie van een Dwengo-microcontroller anderzijds. Dit is ook te zien in Fig. 1.1 op pagina 9.
2.2.1
Boomstructuur
Via de boomstructuur kon de gebruiker de microcontroller programmeren. Dit gebeurde door nieuwe blokken van de linkerkant te slepen naar de boom in het midden. Door te klikken op een blokje in de boom, verschenen extra opties om een blokje aan te passen. Voor een if- en while-structuur waren ook bepaalde blokken met bijhorende vertakkingen voorzien, zoals te zien in Fig. 2.5.
Fig. 2.5: Dwengo Blocks bèta: Extra opties, if en while Vooral bij het gebruik van deze boomstructuur, waren er veel bugs. De extra opties verschenen soms niet, blokken en takken verdwenen, de expressie-editor was niet praktisch enzovoort. . . Sommige zaken voelden voor sommige mensen ook niet intuïtief aan. Een voorbeeld hiervan is het toevoegen van nieuwe blokken aan de boom, jongeren slepen onmiddellijk, volwassenen (leerkrachten) klikken eerst om een nieuwe blokken aan te maken en slepen daarna pas. In dit tweede geval werden twee blokken aangemaakt. Deze boomstructuur hoort bij de reeds vermelde masterproef die zich focust op de GUI [19]. Voor een gedetailleerde schets van de oude situatie, samen met de nieuwe versie kunt u deze masterproef bekijken.
2.2.2
Simulatie
Naast de boomstructuur bij de GUI was er ook nog de simulatie. Aan de hand van de simulatie kon de gebruiker zien welk effect de code zal hebben indien deze uitgevoerd werd op een Dwengo-microcontroller. Er werd een vereenvoudigde Dwengo-microcontroller op het
HOOFDSTUK 2. OUDE SITUATIE MET PROBLEMEN
17
scherm getekend waardoor de gebruiker stap voor stap kon zien wat er gebeurde door zijn code. Deze wordt ook opnieuw ontwikkeld in deze masterproef. De simulatie houdt veel meer in dan enkel het visuele aspect, daarom behoort dit niet volledig tot de GUI, maar is dit meer een apart onderdeel.
2.3
Simulatie
In de bètaversie werden alle objecten en functies handmatig in JavaScript geschreven, het tekenen gebeurde met behulp van Scalable Vector Graphics (SVG) objecten. Dit is een bestandsformaat voor statische en dynamische vectorafbeeldingen. Er waren twee JavaScript bestanden die een cruciale rol in speelden bij de simulatie, namelijk engine.js en viewBoard.js. Engine.js zorgde voor de correcte voortgang van de simulatie, viewBoard.js zorgde voor het visuele aspect van de simulatie, het GUI-aspect.
2.3.1
Engine.js
Hier werd de voortgang verzorgd, de staat van de simulatie. De knoppen om de simulatie te bedienen werden hier ook beheerd. Kort gezegd werd bij het opstarten van de simulatie een timer gestart die periodiek een volgende stap van de simulatie uitvoerde. Dit gebeurde natuurlijk alleen maar indien de staat van de simulatie op RUN stond. Bij de staten STOP, STEP of PAUSE, moest de timer niets periodiek uitvoeren. Bij de STOP -staat moest er zelfs niets gebeuren, bij STEP of PAUSE mocht(en) de volgende stap(pen) pas uitgevoerd worden na input van de gebruiker. Bij het starten van de simulatie werd de huidige boom die de gebruiker opstelde, vertaald naar simulatiecode. Deze boom werd achter de schermen als XML bijgehouden. Deze XMLcode werd naar de server gestuurd, daar werd deze vertaald naar simulatiecode en opnieuw naar de gebruiker gestuurd. Deze simulatiecode was JavaScript-code, die nog wat aanpassingen nodig had. Dit hield in dat variabelen nog aangepast moesten worden aan hun scope1 . Variabelen met dezelfde naam, maar in verschillende functies, hebben uiteraard niets met elkaar te maken. Tijdens het opstellen van de simulatiecode werd voor elke variabele het herkenbaar tekstelement !SCOPE! toegevoegd. De !SCOPE! werd dan vlak voor het uitvoeren van de lijn simulatiecode vervangen door de huidige functienaam. Daarna werd deze simulatiecode lijn per lijn uitgevoerd. Indien gebruikgemaakt werd van een functie van de microcontrollerbibliotheek, dan werd deze opgeroepen en uitgevoerd. Dit kon omdat de JavaScript-bestanden die de handmatig geschreven simulatiecode bevatten voor elke functie (zie Fig. 2.1 en Fig. 2.3), ook beschikbaar waren voor de gebruiker. In Bijlage A is een voorbeeldprogramma met zijn achterliggende XML-code en bijhorende simulatiecode te vinden. Elke !SCOPE! moest vlak voor het uitvoeren nog vervangen worden door de functienaam om problemen met gelijke namen bij variabelen in verschillende functies op te lossen. 1
Bereik of domein in het Nederlands. Een globale variabele is bijvoorbeeld overal toegankelijk, maar een variabele die aangemaakt wordt binnen een functie is niet toegankelijk in een andere functie.
HOOFDSTUK 2. OUDE SITUATIE MET PROBLEMEN
2.3.2
18
ViewBoard.js
Een simulatie van een microcontroller zonder visueel aspect is natuurlijk moeilijk. Hier kwam viewBoard.js van pas. Bij het opstarten van de grafische programmeeromgeving werd het virtuele Dwengo-bord getekend. Dit gebeurde volledig door middel van SVG, dus lijntje per lijntje, vierkantje per vierkantje. . . Al deze objecten werden bijgehouden om zo gemakkelijk te kunnen manipuleren. Uit de code in Fig. 2.3 was het misschien al duidelijk dat de GUI niet rechtstreeks gemanipuleerd werd. In deze code is te zien dat de variabele SPEED1 de status van de eerste motor voorstelt. Na elke simulatiestap (elke simulatiestap komt overeen met een lijntje code uit Bijlage A.3) werd de virtuele microcontroller geüpdatet. Alle variabele elementen worden dan hertekend volgens hun huidige staat. ViewBoard.js koppelde ook manuele acties, zoals het indrukken van een virtuele knop, aan de bijhorende verandering van staat.
2.3.3
Algemeen
Bij het simuleren van om het even welke code waren zo goed als geen bugs ontdekt. De simulatie op zich werkte wel goed, maar er was vooral een groot minpunt. Vanaf er iemand een extra functie wou toevoegen aan de simulatie, moesten er zeer veel aanpassingen gebeuren op veel verschillende plaatsen. Per extra stukje functionaliteit moesten er zowel in engine.js als in viewBoard.js verschillende functies worden aangepast. Daarnaast moest er ook nieuwe code geschreven worden die specifiek instond voor de simulatie van het nieuwe onderdeeltje. Dit was veel werk en de kans op fouten was dan ook groot.
2.4
Andere microcontrollerbibliotheken
Het idee om beginnende programmeurs niet met tekstuele code te laten werken, maar met een grafische boomstructuur, werd al warm onthaald. Sommigen kiezen toch niet voor het gebruik van Dwengo Blocks omdat zij al gebruikmaken van andere microcontrollers zoals deze van Arduino in plaats van deze van Dwengo. Dwengo Blocks was namelijk enkel geschreven voor de Dwengo-bibliotheek, die volledig in C geschreven is. Arduino maakt voor de essentiële functies ook gebruik van C, maar extensies worden meer en meer geschreven in C++. Moest Dwengo Blocks compatibel zijn met verschillende (zelfgeschreven) microcontrollerbibliotheken, zou dit een enorme meerwaarde zijn. Hierdoor wordt de markt van potentiële gebruikers ook groter. Het belangrijkste is om Dwengo Blocks compatibel te maken met alle C-bibliotheken, maar hoe flexibeler er met de taal omgesprongen zou worden, hoe beter natuurlijk. Zo kan er misschien een weg geopend worden naar talen zoals C++ (uitbereidingen Arduino), C# (Netduino), Java. . .
2.5
Samenvatting en inleiding nieuwe stukken
In deze masterproef worden twee grote delen opnieuw ontwikkelt. Ten eerste de manier om bibliotheken in te laden (Sectie 2.1 en Sectie 2.4), dit komt aan bod in Hoofdstuk 3. Daarna
HOOFDSTUK 2. OUDE SITUATIE MET PROBLEMEN
19
Fig. 2.6: Dwengo Blocks bèta: samenhang bestanden
Fig. 2.7: Nieuwe Dwengo Blocks: samenhang bestanden
wordt de nieuwe simulatie (Sectie 2.3) besproken in Hoofdstuk 4. In Fig. 2.6 is ook nog eens een overzicht te zien van de samenhang van de werking. Hierop is duidelijk te zien dat de zelfgeschreven JavaScript functies enkel geïnspireerd zijn op de bibliotheek, maar dat de bibliotheek zelf niet gebruikt wordt. Indien deze JavaScript-functies geschreven zijn, is automatisch ook de simulatie beschikbaar, alles moet dus gesimuleerd worden om te kunnen gebruiken in de grafische programmeeromgeving. In de Tabellen 2.1 en 2.2 volgt nog een samenvatting van alle voor- en nadelen van de oude versie. In Fig. 2.7 is een overzicht te zien van hoe de nieuwe samenhang eruit ziet. Dit wordt in de volgende hoofdstukken grondiger besproken. De bovenste aaneenschakeling tot en met webservice gaat over het inladen van de bibliotheken en wordt besproken in Hoodstuk 3. De onderste aaneenschakeling gaat over de simulatie en wordt behandelt in Hoofdstuk 4. In Hoodstuk 5 wordt de vertaling naar C-code besproken en de basis gelegd voor de overschakeling naar de nieuwe open bron compiler, SDCC.
HOOFDSTUK 2. OUDE SITUATIE MET PROBLEMEN
Voordelen
20
Nadelen
Er wordt slechts een selectief aantal functies getoond
Veel manueel werk om nieuwe functies toe te voegen
Alle functies kunnen gesimuleerd worden
Alle functies moeten gesimuleerd worden Geen uitbreiding voor nieuwe microcontrollers Wijzigingen in de bibliotheek moet handmatig doorgevoerd worden
Tabel 2.1: Dwengo Blocks bèta: voor- en nadelen bibliotheken
Voordelen
Nadelen
Werkt goed
Veel manueel werk
Eenvoudig te zien wat er gebeurt
Uitbreidingen vragen veel werk op meerdere plaatsen Bij uitbreidingen is de kans op problemen bij al bestaande en werkende simulatie ook groot Vaste tekenruimte die niet kan schalen Slechts één tekenruimte waardoor de ontwikkelaar het overzicht moet bewaren over de volledige simulatie
Tabel 2.2: Dwengo Blocks bèta: voor- en nadelen simulatie
Hoofdstuk 3
Bibliotheken inladen Uit vorig hoofdstuk bleek dat Dwengo Blocks compatibel moest worden met meerdere microcontrollerbibliotheken in plaats van enkel deze van een Dwengo-microcontroller. Daarnaast was het ook de bedoeling om af te stappen van het systeem om eerst de functies handmatig in JavaScript te schrijven om deze te gebruiken in de grafische programmeeromgeving. Het ideale scenario zou zijn om rechtstreeks te vertrekken van een bibliotheek en die om te zetten naar een formaat waarmee gemakkelijker meegewerkt kan worden in de grafische programmeeromgeving. Om het overzicht gemakkelijk te behouden in de volgende secties, geeft Fig. 3.1 een overzicht van de totale werking die gebruikt wordt voor het verwerken van bibliotheken. Doxygen staat met zijn Config file in voor het verwerken van de bibliotheek en wordt besproken in Sectie 3.1.2. Het XML-configuratiebestand wordt ook in deze sectie besproken, maar zal in de volgende hoofdstukken ook nog terugkeren. De XML- en de XSLT-blokken worden besproken in Sectie 3.2. De samenhang van het conversiescript komt aan bod in Sectie 3.2.3. Hierna komt er een webservice aan te pas die instaat voor de communicatie met de GUI. Deze webservice wordt besproken in Sectie 3.3.
Fig. 3.1: Overzicht converteren van bibliotheek
21
HOOFDSTUK 3. BIBLIOTHEKEN INLADEN
3.1 3.1.1
22
Headerbestanden parsen Reguliere expressies
Het eerste idee is om alle headerbestanden uit een bibliotheek aan de hand van reguliere expressies te parsen. Headerbestanden bevatten enkel declaraties, maar niet de feitelijke implementatie van bijvoorbeeld een functie of klasse. De Dwengo-bibliotheek is geschreven in C, dus in de eerste plaats moet het hiermee compatibel zijn. Bij het analyseren van de verschillende mogelijke soorten inhoud, zowel declaraties als de commentaar, wordt het snel duidelijk dat er niet enkel op Dwengo gefocust mag worden. Indien enkel de verschillende functies uit de bestanden worden gehaald, zal het in de toekomst moeilijk zijn indien er ooit klassen bij Dwengo Blocks geïntroduceerd zouden worden of gebruikgemaakt zou worden van bestaande globale variabelen. Deze masterproef wordt los van de front-end, de GUI [19], ontwikkeld. Hoe meer informatie er dus uit de headerbestanden gehaald kan worden, hoe beter. Het is beter om een bestaande parser te gebruiken, die al compatibel is met alle speciale gevallen en uitzonderingen. Dit geeft als voordeel dat er geen bugs ontstaan indien er speciale technieken gebruikt worden in een nieuwe bibliotheek, de parser is hier dan al op voorzien.
3.1.2
Doxygen
De documentatie voor de Dwengo-bibliotheek wordt gegenereerd met Doxygen [6]. Doxygen is een standaard middel om documentatie te genereren uit geannoteerde broncode. In Fig. 3.2 is een voorbeeld te zien van een geannoteerde functie uit de Dwengo-bibliotheek.
Fig. 3.2: Voorbeeld Dwengo-code met annotaties voor Doxygen De documentatie van Dwengo bevindt zich dus in de headerbestanden, als annotaties, en Doxygen genereert documentatie uit deze headerbestanden. Het zou handig zijn moest de documentatie ook zichtbaar zijn in de grafische programmeeromgeving. Maar als Doxygen de headerbestanden al zo goed verwerkt, kan dit misschien ook gebruikt worden voor het
HOOFDSTUK 3. BIBLIOTHEKEN INLADEN
23
verwerken van alle bibliotheken voor de grafische omgeving. Eerst wordt er gekeken hoe Doxygen geconfigureerd wordt en welke output het geeft. Daarna wordt er gekeken hoe dit toepasbaar is bij Dwengo Blocks.
Doxygen configuratie en output Het is duidelijk wat Doxygen doet, maar eerst zal de output nog wat toegelicht worden, zoals getoond op Fig. 3.3. De figuur geeft duidelijk aan dat er zeer veel opties en outputmogelijkheden zijn voor Doxygen. Het omkaderde proces zal gebruikt worden bij Dwengo Blocks en komt in het volgende puntje van deze sectie aan bod. De HTML-output wordt gebruikt voor de documentatie van Dwengo [11]. Daarnaast zijn er ook nog verschillende andere mogelijkheden zoals LATEX, RTF, Man pages, XML en Perl1 . XML en Perl zijn speciaal ontworpen voor ontwikkelaars.
Fig. 3.3: Doxygen information flow [7] Er zijn ook veel mogelijkheden om de output van Doxygen te configureren, zoals ook te zien op Fig. 3.3. De sources zijn natuurlijk de belangrijkste input, dit zijn de bestanden waarvoor 1
Perl staat niet op de figuur, maar er is wel een experimentele versie beschikbaar
HOOFDSTUK 3. BIBLIOTHEKEN INLADEN
24
de documentatie gegenereerd moet worden (de headerbestanden). Daarnaast is de Config file of Doxyfile de belangrijkste input om alle opties te configureren. Deze kan gegenereerd worden aan de hand van de Doxywizard, een programmaatje om eenvoudiger een Config file te schrijven. Zo’n Config file bestaat uit een lange reeks sleutel/waarden-gegevens. Elke sleutel staat voor een andere eigenschap. Zo bepalen deze configuratiegegevens onder andere de soorten output, waar de input staat, welke bestanden genegeerd moeten werden en tal van andere opties. De andere inputbestanden zoals de Layout file of de customheaders, -footers of -images, zijn handig om de output visueel te manipuleren. Bijvoorbeeld om de lay-out van de HTMLdocumentatie aan te passen zoals ook gebeurd bij de documentatie van de bibliotheek van Dwengo [11]. De microcontrollerbibliotheken voor Dwengo Blocks moeten enkel omgezet worden in een formaat waaruit de grafische omgeving snel gegevens kan oproepen. De Doxygenoutput moet dus niet opgemaakt worden en daarom zal er op deze manipulatiemogelijkheden niet verder ingegaan worden. Het grote voordeel van Doxygen is dat het kan omgaan verschillende programmeertalen. De microcontrollerbibliotheek van een Dwengo is geschreven in C, maar hoe meer talen er compatibel zijn met Dwengo Blocks, hoe beter.
Toepassen bij Dwengo Blocks Zoals gezegd, heeft Doxygen vele outputmogelijkheden en kan het overweg met vele programmeertalen. Nu moet er nog gekeken worden hoe dit bruikbaar is bij het inladen van een bibliotheek bij Dwengo Blocks. De HTML, RTF en gelijkaardige output kunnen al onmiddellijk verworpen worden voor het gebruik bij Dwengo Blocks. De bedoeling is namelijk dat de gegevens uit een bibliotheek vlot en eenvoudig te raadplegen zijn door de GUI. Visueel opgemaakte tekst zoals de HTML-output, zou eerst nog eens extra verwerkt moeten worden telkens dit opgevraagd wordt. Pas daarna zou het in de GUI gebruikt kunnen worden. Het voordeel om de bibliotheek slechts eenmaal op voorhand in een eenvoudiger formaat om te zetten zou dan volledig verdwijnen. Naast deze visuele output, zijn er ook twee soorten die speciaal geschreven zijn voor ontwikkelaars. Deze XML- en Perloutput bevatten alle gegevens van de bibliotheek in een eenvoudigere gegevensstructuur, waardoor deze wel interessanter zijn om verder te gebruiken. De HTML-output wordt echter enkel verworpen voor het gebruik bij Dwengo Blocks. De documentatie van de Dwengo-bibliotheek gebruikt echter wel nog de HTML-output [11]. De inhoud van de XML- en de Perloutput zijn gelijkaardig. Beide creëren een indexbestand die een overzicht van alle bestanden, klassen, mappen enzovoort bevat. Daarnaast wordt er voor elke verwijzing in het indexbestand een apart bestand gecreëerd met de specificaties ervan. Voor een klasse zijn dat bijvoorbeeld de functies met bijhorende documentatie en parameters, de publieke en private variabelen en de overerving. Alle gegevens zijn in een handige structuur gestoken waardoor deze op een consequente manier geraadpleegd kunnen worden. Dit is natuurlijk goed nieuws voor het gebruik bij Dwengo Blocks. Doxygen kan overweg met vele formaten waaronder C++, C, Objective-C, C#, PHP, Java en Python. De bronbestanden worden door Doxygen omgezet in twee handige formaten om te verwerken, namelijk XML en Perl. Nu moet er keuze gemaakt worden tussen de XML- en Perloutput. De Perloutput is voorlopig nog experimenteel, hierdoor is de kans op wijzigingen in een latere versie van Doxygen
HOOFDSTUK 3. BIBLIOTHEKEN INLADEN
25
groter. Volgens de ontwikkellaars van Doxygen is Perl-output vermoedelijk gemakkelijker te gebruiken en de XML-output meer een algemene standaard [8]. De informatie die gehaald wordt uit een bibliotheek is zoals eerder al vermeld bij beide bijna hetzelfde. De bedoeling van deze masterproef is om de broncode achteraf open bron te maken. Omdat meer mensen ervaring hebben met XML en om grote incompatibiliteitsproblemen te vermijden bij latere versies is er hier geopteerd om gebruik te maken van de XML-output. Deze output moet nu nog op een eenvoudige wijze beschikbaar gesteld worden aan de grafische programmeeromgeving. De stappen en bestanden die gebruikt worden om Doxygen te doen werken in dit project zijn omkaderd in Fig. 3.3. De configuratie moet hierbij nog wat toegelicht worden. Standaard genereert Doxygen enkel output voor geannoteerde broncode. Voor de meeste gegevens in Doxygen is dit geen probleem, maar niet alle microcontrollerbibliotheken werken met Doxygen-annotaties. Gelukkig kan dit aangegeven worden in de Config file. De standaard HTML-output en andere soorten output hoeven natuurlijk ook niet gegenereerd worden, wat hier ook geconfigureerd kan worden. Naast deze algemene aanpassingen in de Config file die nodig zijn voor elke bibliotheek waarmee Dwengo Blocks zou werken, zijn er ook nog een aantal specifieke aanpassingen die verschillend zijn bij elke microcontrollerbibliotheek. Zo kan er voor elke nieuwe bibliotheek bepaald worden welke bestanden of bestandstypes al dan niet verwerkt moeten worden of als bepaalde functies of klassen genegeerd moeten worden. Al deze gegevens kunnen eenvoudig opgegeven worden in een eigen XML-configuratiebestand voor het nieuwe project. Dit configuratiebestand moet ook andere configuratiegegevens bevatten over het project voor bijvoorbeeld de GUI [19], de simulatie (Hoofdstuk 4) en de compilatie (Hoofdstuk 5), later hierover meer. Alle voorgaande stappen zijn ook terug te zien op Fig. 3.1, dit is het eerste deel van het conversiescript.
Licentie Natuurlijk moet er ook gekeken worden of deze Doxygen-software wel vrij gebruikt mag worden. Gelukkig is dit geen probleem, Doxygen wordt namelijk verstrekt onder de General Public License (GPL) [18]. Dit houdt namelijk in dat de software naar wens kan aangepast worden, zolang dat recht ook wordt doorgegeven aan anderen en de auteur(s) vermeld worden. Deze masterproef zal namelijk zelf ook open bron zijn.
3.2
XML converteren
Om een bibliotheek beschikbaar te stellen aan de grafische omgeving, moet de XML-output van Doxygen nog geconverteerd worden. Dit is dan ook de volgende stap op Fig. 3.1.
3.2.1
XSLT-conversie
Dit converteren is nodig zodat alle informatie op een gelijkaardig manier opgevraagd kan worden, zonder lang opzoekwerk in alle bestanden of telkens opnieuw dezelfde bewerking
HOOFDSTUK 3. BIBLIOTHEKEN INLADEN
26
uit te voeren op de gegevens. Extensible Stylesheet Language Transformations (XSLT) is speciaal ontwikkeld om XML-bestanden te transformeren naar nieuwe XML-bestanden. Na de conversie worden alle gegevens bewaard als JSON-bestanden (JavaScript Object Notation), hierdoor kunnen gegevens snel ingeladen worden in de GUI. De GUI draait namelijk volledig lokaal in de browser van de gebruiker en is in JavaScript geschreven. Hierdoor wordt het proces om de gegevens in te laden vergemakkelijkt.
Index.xml Bij de GUI zal de gebruiker eerst kunnen kiezen uit welk groter geheel, zoals bestand, klasse hij gegevens nodig heeft. Daarna zal hij uit dit groter geheel een functie of een andere specificatie kunnen kiezen. Zoals vermeld genereert Doxygen een indexbestand die een verwijzing naar alle gegevens bevat, waardoor dit bestand hiervoor gemakkelijk kan instaan. Hierdoor is het dus initieel ook niet nodig om alle gegevens van elke Compound door te sturen. De meeste gegevens zouden toch niet gebruikt worden, maar zouden het laden van de gegevens toch vertragen bij grotere bibliotheken. Omdat de gegevens omgezet zullen worden naar JSON, moeten XML-attributen ook vermeden worden. Een JSON-bestand stelt echter geneste arrays voor, waarbij er geen plaats is voor attributen. Er zijn echter wel alternatieven zoals attributen converteren naar elementen met een speciaal teken (bijvoorbeeld attr wordt @attr), maar dit kan de zaken nodeloos ingewikkeld maken. In het Codevoorbeeld 3.1 is een fragment uit een oorspronkelijke index.xml te vinden en in Codevoorbeeld 3.2 het overeenkomstig geconverteerde fragment. De meeste aanpassingen zijn vlot terug te vinden door de twee codevoorbeelden te bekijken. Enkel parentdirectory heeft wat toelichting nodig. Deze wordt voor de conversie extra toegevoegd om problemen met bestanden die dezelfde naam hebben te vermijden. Dit kan voorkomen indien de bronbestanden zich in meerdere submappen bevinden. De conversie van refid is duidelijk, maar de betekenis misschien niet. Elke functie, bestand, klasse, define of ander unieke specificatie uit een een bibliotheek krijgt een unieke id toegewezen. Hierdoor is het gemakkelijk om zaken bij te houden en te verwijzen naar andere specificaties. Al deze wijzigingen zijn gespecificeerd in convertIndex.xslt. 1 2 3 4 5 6 7 8
dwengoMotor.h <member refid="dwengo_motor_8h_1a6ddfdda7a062d10cff4a72b76b44aeb8" kind="define">FORWARD <member refid="dwengo_motor_8h_1adf445abfe1b77fa63f89e315ccc2f7f2" kind="define"> BACKWARD <member refid="dwengo_motor_8h_1a95a7912f695301a97a3a691a4918fdeb" kind="function"> initMotor <member refid="dwengo_motor_8h_1a770e47a93416c3e81862b7ad60de2f2a" kind="function"> setSpeedMotor1 <member refid="dwengo_motor_8h_1a9056e18a6af908ed39ab3dd12b506f69" kind="function"> setSpeedMotor2 <member refid="dwengo_motor_8h_1acd2c662936b1bc43619f2afa5b637d12" kind="function"> stopMotors
Code 3.1: Voorbeeld compound uit index.xml 1 2 3 4
dwengoMotor.h dwengo_motor_8h <parentdirectory>lib
HOOFDSTUK 3. BIBLIOTHEKEN INLADEN 5
27
Code 3.2: Voorbeeld geconverteerde compound uit index.xml
ID.xml De gedetailleerde gegevens bevinden zich niet in het indexbestand, maar in de vele andere bestanden. Deze bevatten zeer veel informatie, maar hoe meer informatie de GUI ter beschikking heeft, hoe makkelijker uit te breiden naar de toekomst toe. De codevoorbeelden bevinden zich in bijlage B. De volgende gegevens kunnen beschikbaar zijn per bestand na conversie. Dit kan variëren naargelang het XML-bestand gegevens van een klasse, bestand. . . bevat. Dit is ook te zien in bijlage B, Codevoorbeeld B.2. • basecompoundref
• includedby
• innerfile
• briefdescription
• includes
• listofallmembers
• compoundname
• innerclass
• parentdirectory
• detaileddescription
• innerdir
• sectiondef
De sectiondef zal meestal de meeste informatie bevatten. Voor bestanden uit de Dwengobibliotheek zijn onder andere de volgende types mogelijk: functies, defines of typedefs. Hieronder is ook een lijst van alle mogelijke types terug te vinden. Niet alle types komen altijd voor, dit hangt af waarvan het XML-bestand een beschrijving is. Zo kunnen bijvoorbeeld files moeilijk een friend bevatten, dit past meer in de beschrijving van een class. Voor de duidelijkheid: een sectiondef groepeert de verschillende onderdelen per type, zo kan er gemakkelijk een lijst verkregen worden met dezelfde types. • dcop-func • define • enum
• package-staticfunc • package-type
• public-slot
• protected-func
• public-staticattrib
• private-func • private-slot
• protectedstatic-attrib
• private-staticattrib
• protectedstatic-func
• func
• package-staticattrib
• protected-attrib
• protected-sot
• friend
• package-func
• public-func
• private-attrib • event
• package-attrib
• property
• private-taticfunc • private-type
• public-staticfunc • public-type • related
• protected-type
• signal
• prototype
• typedef
• public-attrib
• user-defined
Elk onderdeel van sectiondef bevat verschillende elementen van het type memberdef. Elke memberdef die onder dezelfde sectiondef staan zijn hetzelfde type. Weer hangen de kindelementen af van het type (kind ) memberdef. Hieronder is een lijstje van mogelijke kindelementen te vinden, die behouden of gecreëerd zijn na de conversie.
HOOFDSTUK 3. BIBLIOTHEKEN INLADEN
28
• argsstring
• id
• read
• bitfield
• inbodydescription
• references
• briefdescription
• initializer
• reimplements
• definition
• kind
• templateparamlist
• detaileddescription
• name
• type
• enumvalue
• param
• write
3.2.2
Resultaat
Na het converteren worden de XML-bestanden omgezet in JSON-bestanden, dit is de laatste stap in Fig. 3.1. JSON-gegevens bestaan uit geneste arrays. XML-gegevens bestaan daarentegen uit geneste elementen, deze moeten dus eerst omgezet worden naar een equivalente array. Hiervoor wordt gebruikgemaakt van de PHP-functie van Tamlyn Rhodes [5]. Het JSON-resultaat van de geconverteerde XML uit Codevoorbeeld 3.2 is terug te vinden in Codevoorbeeld 3.3. Daarnaast wordt er ook nog een hulpbestand gecreëerd waardoor een id snel terug te vinden is. Zoals eerder besproken krijgt elke specificatie een unieke id toegewezen. Bij het opvragen van informatie door de GUI zal er gebruik gemaakt worden van deze id. Om zo weinig mogelijk tijd te verliezen bij het bepalen in welk bestand de opgevraagde gegevens zich bevinden, wordt hiervoor een extra mappingssysteem opgesteld. Voor bestanden of klassen bijvoorbeeld is dit simpel, hiervoor kan simpelweg .json achter de id geplaatst worden om de juiste gegevens te vinden. Voor functies in bestanden of klassen moet er een tussenstap gemaakt worden. Hiervoor moet er slechts een deeltje uit een JSON-bestand gehaald worden. Voor elke id wordt er berekend in welk JSON-bestand de informatie terug te vinden is. Deze informatie wordt apart opgeslagen waardoor er snel opgezocht kan worden welke informatie opgevraagd wordt. 1
{ "data": { "@doxygenversion": "1.8.6", "struct": {...}, "file": [..., { "name": "dwengoMotor.h", "refid": "dwengo_motor_8h", "parentdirectory": "lib" },...], ... }
2 3 4 5 6 7 8 9 10 11 12 13
} Code 3.3: Voorbeeld compound uit index.json
HOOFDSTUK 3. BIBLIOTHEKEN INLADEN
3.2.3
29
Conversiescript
Alle voorgaande stappen worden gebundeld in een PHP-script. Dit is het conversiescript uit Fig. 3.1. Dit zijn alle stappen die nodig zijn om een microcontrollerbibliotheek automatisch te verwerken zodat de output eenvoudig begrijpbaar is voor de GUI. Het proces wordt dus gestuurd door het conversiescript. Ook Doxygen wordt vanuit dit script uitgevoerd. Omdat Doxygen apart geïnstalleerd moet worden, wordt er eerst getest of de juiste versie beschikbaar is. Met de PHP-code exec(’doxygen -v’) wordt de huidige versie van Doxygen opgevraagd. Na een simpele vergelijking met de ondersteunde versie is de test al klaar. Zoals eerder vermeld zijn er per bibliotheek nog enkele specifieke wijzigingen die moeten gebeuren aan de Config file van Doxygen. Deze specifieke aanpassingen moeten ingevuld worden in een XML-configuratiebestand. De naam van het bestand moet opgegeven worden als configfile-argument voor het conversiescript. De gegevens uit dit bestand worden dan ingeladen en ingevuld aan de hand van reguliere expressies in een Config file van Doxygen. De sleutel/waarde-combinatie die aangepast moet worden, kan eenvoudig teruggevonden worden aan de hand van reguliere expressies. Na het uitvoeren van Doxygen met de gegenereerde Config file moet er een XSLT-conversie gebeuren. Hiervoor moet de XSL-extensie van PHP nog geactiveerd worden. Dit kan door extension=php_xsl.dll toe te voegen aan het configuratiebestand van PHP, php.ini. PHP hanteert standaard ook een tijdslimiet op het uitvoeren van php. Deze staat standaard ingesteld op 30 seconden. Dit is ruim voldoende om bibliotheken zoals deze van Dwengo te verwerken, maar de bibliotheek van Arduino is een stuk groter. Tijdens het testen van de Arduino-bibliotheek moest deze tijdslimiet dus opgedreven worden, 120 seconden (2 minuten) was ruim voldoende. Dit is de max_execution_time in php.ini. Voor het uitvoeren van deze scriptie is ook minimum PHP 5.2 vereist. Dit is getest met het Minimum PHP Version Calculator Script van Alex Roxon [26]. Tijdens het opstellen van het conversiescript werd ook nog een ander probleem vastgesteld. Standaard ondersteunt PHP enkel XSLT 1.0, hoewel versie 2.0 en zelfs 3.0 ook al uit is. Er zijn wel alternatieve PHP-bibliotheken ontwikkeld, maar de meeste daarvan zijn niet gratis beschikbaar. De XSLT bestanden die gebruikt werden voor het converteren van XMLoutput van Doxygen, gebruikten technieken die pas beschikbaar waren vanaf versie 2.0. Deze XSLT-bestanden moesten dus aangepast worden zodat ze volledig XSLT 1.0 compatibel waren.
3.3
Webservice
Het enige dat nu nog rest is om de gegenereerde data uit de bibliotheek door te sturen naar de GUI. Hiervoor is een apart PHP-script ontwikkeld. Dit script vraagt twee argumenten namelijk lib en id. Hierop wordt alle informatie als antwoord gestuurd die beschikbaar is over de opgevraagde id uit een bepaalde bibliotheek (lib ). Indien het id -argument ontbreekt of indien deze een lege string bevat, wordt alle informatie uit het index.json bestand gestuurd. Met deze informatie alleen is een gebruiker niet veel. De JSON-bestanden worden ook niet opgemaakt, er is dus geen lay-out, om ze zo compact mogelijk te houden. De ontvangen informatie moet dus eerst nog verwerkt worden voor het aan de gebruiker getoond wordt. De informatie zal dus via Asynchronous JavaScript and XML (AJAX) opgevraagd worden vanuit
HOOFDSTUK 3. BIBLIOTHEKEN INLADEN
30
de GUI. De XML uit AJAX is misschien wat misleidend, want in heel veel gevallen (zoals dit project), worden de gegevens in JSON-formaat doorgestuurd. Zoals vermeld worden alle gegenereerde gegevens uit een verwerkte bibliotheek doorgestuurd naar de GUI [19]. Deze GUI staat dus in voor de ondersteuning van de verschillende programmeermogelijkheden. Arduino maakt achter de schermen echter hoofdzakelijk gebruik van C++ in plaats van C, de GUI ondersteunt voorlopig nog veel zaken van C++ niet. Hierdoor kan de bibliotheek van Arduino ook amper getest worden met de GUI, er kan enkel gecontroleerd worden of alle data beschikbaar is door handmatig de webservice op te roepen.
3.4
Platformonafhankelijkheid
In het volledige hoofdstuk zijn ook enkel technologieën gebruikt die platformonafhankelijk zijn. Zowel Doxygen, PHP en XSLT zijn allemaal uitvoerbaar op zowel Linux en Windows zonder aanpassingen.
Hoofdstuk 4
Simulatie Naast het beschikbaar stellen van een microcontrollerbibliotheek aan de GUI, is het simuleren van de code die de gebruiker kan opstellen met de GUI een mooie meerwaarde voor een grafische omgeving. Hierdoor kan de gebruiker virtueel al eens zien hoe de microcontroller zal reageren op geschreven code. In deze masterproef wordt er enkel geconcentreerd op de microcontroller van Dwengo, maar een mogelijkheid voorzien om een andere microcontroller te simuleren is natuurlijk positief. In de oude bètaversie van Dwengo Blocks moesten alle functies gesimuleerd worden om ook te gebruiken. In deze nieuwe versie wordt er echter vertrokken vanaf de bibliotheken zelf, waardoor de simulatie geen verplichting meer is. Hierdoor kan er grafische code opgesteld worden nog voor de simulatie af is en kunnen er ook functies gebruikt worden die niet gesimuleerd kunnen worden. De volledige simulatie zal in dit hoofdstuk besproken worden.
4.1
C porten naar JavaScript
Een eerste idee om de microcontroller zo generiek mogelijk te simuleren was de volledige C-code te porten naar JavaScript. Dit houdt in dat het geschreven programma, samen met de gebruikte bestanden uit de bibliotheek vertaald worden van C naar JavaScript en dus op dezelfde manier uitgevoerd kunnen worden. Hierdoor zou niet elke functie apart gesimuleerd moeten worden, maar wel de effecten van bepaalde waarden in de registers van een Dwengomicrocontroller. De eenvoudigste en meest gebruikte methode was het gebruik van Emscripten [12]. Emscripten vertaalt als het ware de C-code naar JavaScript zodat een C-programma uitgevoerd kan worden in een browseromgeving. In het geval van de microcontroller zal er dan wel nog een visueel effect aan gekoppeld moeten worden. De eerste omzettingen van een eenvoudig Hello-World -programma leken wel vlot te werken. Voor de simulatie moeten er echter visuele effecten aan gekoppeld worden, de omgezette broncode moet dus gemanipuleerd kunnen worden. Hier doken er snel veel problemen op. Variabelen veranderden van naam, de hoeveelheid gegenereerde code voor eenvoudig programma’s was gigantisch. . . Er zou teveel werk inkruipen om de simulatie tot een potentieel goed einde te brengen. Het was ook veel minder praktisch om geconverteerde code te manipuleren dan in eerste instantie werd aangenomen. Dwengo Blocks heeft ook tot doel om
31
HOOFDSTUK 4. SIMULATIE
32
eenvoudige programma’s te maken, zodat beginnende programmeurs de basisconcepten van het programmeren kunnen leren. Door het porten van de C-code naar JavaScript zou er rekening gehouden moeten worden met enorm veel programmeerconcepten. Dit is echter niet de bedoeling van deze simulatie. Hierdoor is er besloten om het porten van C naar JavaScript niet verder te onderzoeken.
4.2
Functies handmatig simuleren
De simulatie uit de oude bètaversie werkte wel goed, maar het grootste probleem was de uitbreidbaarheid. Omdat het porten van de C-code op niets uitdraaide en de oude versie wel goed werkte, was het een goed idee om de ideeën te hergebruiken. Voor het simuleren wordt er in twee stappen te werk gegaan. Eerst wordt alles getekend en bepaald hoe alles moet reageren op het uitvoeren van een bepaalde functie. Daarna wordt de koppeling gemaakt tussen het ontwikkelde programma in de GUI aan de hand van de verwante masterproef die de GUI behandeld en het stap voor stap uitvoeren van de juiste functies. Het GUI-aspect van de simulatie is zeer nauw verwant met het simuleren zelf, daarom dat het tekenen van de simulatie ook in deze masterproef ontwikkeld wordt. De verwante masterproef staat in voor het ontwikkelen van een microcontrollerprogramma. Het is ook geen slecht idee om Fig. 2.7 op pagina 19 nog eens te bekijken. De bestanden simulationObject.js met zijn implementaties en simulation.js komen aan bod in Sectie 4.2.1. Het bestand simulationEngine.js komt aan bod in Sectie 4.2.2.
4.2.1
Simulatiekern en -objecten
Er zijn twee klassen die instaan voor het tekenen van de simulatie en het bijhouden van de verschillende staten. Ze zijn beiden te zien op Fig. 4.1. De eerste, Simulation, beheert alles. Een instantie van Simulation bevat meerdere instanties van het type SimulationObject. Elk SimulationObject moet zich registreren bij de algemene Simulation. De simulatie kan getekend worden door de initDraw-functie op te roepen op de instantie van Simulation. Deze functie zorgt er op zijn beurt voor dat elk SimulationObject op een correcte manier getekend wordt door daar ook de initDraw-functie op aan te roepen. De functie recalculateZoom zorgt ervoor dat bij het vergroten of verkleinen van de simulatie, alles opnieuw geschaald wordt. De updateDraw zorgt ervoor dat elk SimulationObject zijn variabele gedeelten, zoals een led die aan en uit kan staan, opnieuw tekent. Nu de grote lijnen wat geschetst zijn, kan er wat gedetailleerder gekeken worden naar de werking van beide klassen. Eerst is Simulation aan de beurt. Het is duidelijk dat er slechts één instantie is van de Simulation-klasse. Om dit af te dwingen is er gebruikgemaakt van het Singleton-pattern [36]. Hierdoor kan er slechts één instantie aangemaakt worden van de klasse. Indien er geprobeerd wordt om een tweede instantie aan te maken, geeft de constructor het reeds aangemaakte object terug. Dit is te zien in het Codevoorbeeld 4.1.
HOOFDSTUK 4. SIMULATIE
33
Fig. 4.1: JavaScript klassen voor het weergeven en simuleren
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
function Simulation(){ /*Singleton: only 1 instance possible*/ // the cached instance var instance; // rewrite the constructor Simulation = function() { return instance; }; // carry over the prototype Simulation.prototype = this; // the instance instance = new Simulation(); // reset the constructor pointer instance.constructor = Simulation; //normal part of constructor ... }
Code 4.1: JavaScript Singleton [21] De Simulation verwacht dat er een div element beschikbaar is met id=’simulation’ zodat het weet waar hij kan tekenen. De simulationObjects worden ook opgesplitst in drie soorten, die elk op een andere plaats in de tekenruimte weergegeven worden, elk met eigen viewport. De eerste soort krijgt één gemeenschappelijke tekenruimte waar alle objecten op elkaar getekend worden. Dit zijn BOARD -objecten. Voor een Dwengo-microcontroller zijn dit dwengoBoard en dwengoLCD. Daarnaast zijn er de uitbreidingen, die PERIPHERAL -objecten genoemd worden. Dit zijn bijvoorbeeld dwengoMotor of dwengoServo. Deze krijgen elk een aparte tekenruimte onder elkaar. Indien de totale ruimte voor alle PERIPHERAL -objecten groter is dan op het scherm weergegeven kan worden, wordt er automatisch een scrolbalk voorzien, het bord zelf blijft echter altijd zichtbaar. Als laatste soort is er ook nog de overige object, OTHER -objecten. Deze worden niet getekend maar hebben een andere functie, bij-
HOOFDSTUK 4. SIMULATIE
34
voorbeeld dwengoDelay van de Dwengo-bibliotheek. Door de schaling van de tekenruimtes wordt ervoor gezorgd dat alle objecten in percentages getekend kunnen worden. Zo hebben de punten links- en rechtsboven respectievelijk de coördinaten (0,0) en (100,0). De schaling zorgt er dan voor dat alles over de volledige breedte getoond wordt. De hoogte kan voor elk object verschillend zijn. De instantie van Simulation berekent alle hoogtes van de tekeningen en zorgt zo dat alle mooi onder elkaar getoond wordt. Elk SimulationObject staat in voor zijn eigen functionaliteit en correcte virtuele voorstelling. Door het gebruik van de klasse, is deze functionaliteit volledig afgedwongen en moeten enkel nog de specifieke onderdelen aangepast worden. Zo zijn er de functies registerInitDraw en registerUpdateDraw waarmee de tekenfuncties geregistreerd moeten worden. Indien dit niet gebeurd zal er ook niets getekend worden. De ontwikkelaar staat zelf in voor het geven van een gepaste id aan de variabele objecten die aangepast kunnen worden bij het oproepen van de updateDraw-functie. In TEMPLATE.js, een leeg SimulationObject die als handleiding kan dienen om een nieuw object te creëren, wordt aangeraden om alle ids op een generieke manier op te stellen. Dit is namelijk simulation_TEMPLATE_element1, waarbij TEMPLATE de naam van het te simuleren bestand is en element1 een eigen gekozen achtervoegsel. Indien dit consequent verder getrokken wordt, zullen er geen conflicten zijn met ids. Daarnaast heeft elk SimulationObject ook nog één of meerdere staten. Zo kan een led al dan niet branden of een motor al dan niet draaien. Voor elk aspect dat kan variëren moet er een staat geregistreerd worden met de functie registerState(statename,defaultvalue). Staatswijzigingen kunnen dan doorgevoerd worden met setState(statename,newvalue), waarop de simulatieklasse automatisch de functie updateDraw zal oproepen. Het spreekt voor zich dat de ontwikkelaar de functie updateDraw correct zal moeten aangepast hebben voor de dynamische objecten zodat elke staat de juist visuele voorstelling heeft. Staten veranderen bij het uitvoeren van een functie. Zo zal de functie stopMotors() van de Dwengo-bibliotheek er bijvoorbeeld voor zorgen dat de motoren zullen stoppen met draaien, de staat van de motoren wordt dus ingesteld op ’niet draaien’. Deze functies kunnen gesimuleerd worden door ze eerst te koppelen aan een SimulationObject. Dit kan door op een specifiek SimulationObject de functie addFunction(name,func) op te roepen met de juiste parameters. Het SimulationObject zal daarop de functie toevoegen aan de lijst met functies in het algemene Simulation-object. Net zoals de functies in een C-bibliotheek een unieke naam hebben, moeten ze hier ook een unieke naam hebben omdat alle functies van alle SimulationObject -en in dezelfde lijst bewaard worden. Een eerste idee was om de functies niet samen te steken in een lijst, net zoals de gebeurde in de oud bètaversie van Dwengo Blocks (Fig. 2.3 op 15). Hier werden de functies rechtstreeks aangemaakt zoals ze in C zouden aangemaakt worden. Dit heeft echter als nadeel dat er nooit een andere functie die zou zorgen voor de GUI of de algemene werking van de simulatie bijvoorbeeld, dezelfde naam zou kunnen hebben. In het geval van Dwengo is dit voorlopig geen probleem, maar beter toekomstige problemen vermijden dan voorkomen. Een microcontroller kan natuurlijk ook externe input krijgen, bijvoorbeeld door het indrukken van een knop. Dit van door een actie of event te koppelen aan de grafische weergave. Bij het oproepen van zo’n event kan er dan een wijziging doorgevoerd worden aan een van de staten, zo kan een knop ingesteld worden op ’ingedrukt’. Deze event -koppelingen kunnen gebeuren door een functie toe te kennen aan addEvents van een SimulationObject waarin de gepaste koppelingen zijn gespecificeerd. De Simulation zorgt er dan voor dat deze koppelingsinstructies op het gepaste moment worden uitgevoerd, namelijk na het tekenen van alle
HOOFDSTUK 4. SIMULATIE
35
elementen uit de initDraw-functie. Een event wordt in JavaScript aan een functie gekoppeld die uitgevoerd wordt indien het event optreedt, dus de gekoppelde functie moet natuurlijk ook voorzien worden. Net zoals er in TEMPLATE.js aangeraden wordt om alle ids een consequente naam te geven, raadt deze template ook aan om geen globale nieuwe functie aan te maken voor een event. De functies behoren bij een specifiek SimulationObject, dus is logisch om deze als onderdeel van dit object toe te voegen. Omdat alle functies zelf ingevuld kunnen worden is er dus een heel flexibele structuur. Dit heeft als voordeel dat er ook creatief kan omgesprongen worden met sommige visuele voorstellingen. Zo kan een wiel ook dynamisch gemaakt worden. Door het toevoegen van een eigen timer, kan een wiel draaien tijdens de simulatie. Het nadeel van deze flexibele structuur is wel dat er heel consequent te werk gegaan moet worden. Indien er bijvoorbeeld onnauwkeurig wordt omgesprongen met namen van functies of ids, kunnen er problemen ontstaan bij dubbele namen. Ook kan kan het gebeuren dat de functies die opgeroepen worden door timers niet snel genoeg uitgevoerd kunnen worden indien er meerdere zijn. Wielen kunnen dan vertraagd of schokkend draaien in plaats van een vloeiende animatie. Het is ook duidelijk dat alle aanpassingen voor één SimulationObject gebeuren in hetzelfde JavaScript-bestand. Voor een nieuw object moet er dus slechts één bestand aangemaakt worden. Hierbij is TEMPLATE.js de ideale vertrekbasis. De Simulation zal ervoor zorgen dat dit bestand opgenomen wordt in de simulatie en een eigen tekenruimte krijgt.
4.2.2
Simulatiemotor
Nu het voorstellen van de simulatie verduidelijkt is, moet er nu een koppeling komen met de gecreëerde code uit de GUI [19]. Indien de gebruiker de simulatie start, moet het programma uit de GUI stap voor stap overlopen kunnen worden met de correcte visuele reacties. De SimulationEngine of simulatiemotor staat in voor de correcte voortgang van de simulatie. Dit is te vergelijken met Engine.js (Sectie 2.3.1) uit de oude Dwengo Blocks versie. In Fig. 4.2 is een een eenvoudig programmaatje te zien, gecreëerd met een voorlopig versie van de GUI. De leds op het bord stellen een binair getal voor en dit getal (variabele tel ) wordt telkens met één verhoogt. Deze variabele wordt dan ook getest in de functie reset_als_groter of hij niet groter is dan 255, dit is de maximale waarde die binair door de ledjes op een Dwengo-bord kan voorgesteld worden. Indien deze waarde overschreden wordt, dan wordt de variabele terug op één ingesteld. Elk type blok heeft een andere kleur en wordt op een andere manier gesimuleerd. In Fig. 4.2 komen alle blokken eens aan bod, dus kunnen de verschillende simulatiemogelijkheden aan de hand daarvan uitgelegd worden. Deze masterproef handelt niet over de GUI. Er komen hier natuurlijk ook zaken aan bod van de GUI, maar deze zullen niet gedetailleerd besproken worden. Indien er vragen en/of onduidelijkheden zijn met betrekking tot de masterproef over de GUI, kunt u hierbij terecht bij deze scriptie [19]. Indien de simulatie gestart wordt, wordt eerst de startfunctie opgezocht. Deze moet opgegeven worden in het XML-configuratiebestand die ook gebruikt werd voor de preparatie van de bibliotheken (Sectie 3.1.2 en 3.2.3). In het geval van een Dwengo-bibliotheek is de de main-functie. Daarna wordt er periodiek de volgende blok opgehaald en verwerkt, tot er
HOOFDSTUK 4. SIMULATIE
36
Fig. 4.2: Eenvoudig binair tellen programma uit de GUI [19]
geen volgende blok meer is. Bij een correct microcontrollerprogramma moet er echter altijd een oneindige lus zijn zodat er geen einde is, anders zal de microcontroller vreemde effecten hebben. Elke type blok heeft heeft zijn eigen kleur in de GUI. Er zijn vijf soorten blokken, zie ook Fig. 4.2: Call (geel), Operator (rood), Function (blauw), If (groen) en While (paars). De laatste twee bestaan eigenlijk uit meer dan één blok, maar vormen samen wel één functioneel geheel. Net zoals een if en while in een tekstuele programmeertaal meerdere regels insluiten. Omdat er voor de GUI geen programmeerinterface was geschreven waaraan eenvoudig zaken konden opgevraagd worden over het huidige programma, zijn er eerst een aantal functies geschreven om dit proces te vereenvoudigen. Alle communicatie tussen de simulatie en de GUI verloopt dus via functies uit het bestand GUIcommunication.js. Indien er dus wijzigingen zouden gebeuren in de GUI, moeten dus enkel de functies in dat bestand dezelfde output geven en moeten niet alle zaken uit de simulatie aangepast worden. Elke type blok moet op een andere manier gesimuleerd worden. Na zo’n simulatiestap wordt er ook bepaald wat de volgende blok is die gesimuleerd moet worden. Hieronder zullen de specifieke kenmerken van elke blok besproken worden. Zoals eerder vermeld is de eerste blok die aangeroepen moet worden een Function-blok. Elke functie heeft zijn eigen parameters. Daarnaast moeten de variabelen die gebruikt kunnen worden ook in deze blok aangemaakt worden. Met variabelen en parameters moet voorzichtig omgesprongen worden. Indien de variabelen rechtstreeks onder dezelfde naam in JavaScript gebruikt zouden worden, dan kunnen er vreemde effecten indien dezelfde naam in meerdere functies zou voorkomen. Indien een variabele dezelfde naam zou hebben als een variabele die gebruikt zou worden voor de algemene werking van het project, dan zouden de effecten totaal onverklaarbaar lijken voor de gebruiker. Deze problemen werden ook voorzien in de oude versie van Dwengo Blocks (Sectie 2.3.1). Toen werd het simulatieprogramma op
HOOFDSTUK 4. SIMULATIE
37
voorhand volledig berekend en dan pas uitgevoerd. Nu wordt alles stap voor stap berekend en onmiddellijk uitgevoerd. Dit heeft als voordeel dat er nog wijzigingen kunnen gebeuren indien de simulatie al bezig is. De berekening gebeurt ook lokaal in plaats van op de server. Omdat de simulatie blok per blok berekend wordt, kan de nieuwe naam voor een variabele onmiddellijk berekend worden in plaats van de voorlopig !SCOPE! -prefix. Dit houdt in dat er eerst een algemene prefix voor de naam wordt geplaatst, gevolgd door de huidige functie naam en uiteindelijk de oorspronkelijke naam. Zo wordt de variabele tel uit de functie main() achter de schermen bijgehouden als SimulationScope_main_tel. Bij het uitvoeren van een Function-blok, worden alle variabelen achter de schermen aangemaakt met hun eigen simulatienaam. Dit gebeurt niet met de parameters, deze hebben namelijk al een waarde en moeten dus al aangemaakt worden voor een functie aangeroepen wordt. Dit komt later aan bod bij het bespreken van een Call -blok. Naast het aanmaken van de variabelen, plaatst de simulatie bij het uitvoeren van een Function-blok ook de huidige naam van de functie in een lijst. Omdat dit bij elke functie gebeurt, weet de simulatie bij het beëindigen van een functie wat de naam van de vorige functie was. Dit is belangrijk omdat functies elkaar kunnen aanroepen en zonder die lijst weet de simulatie niet naar waar hij terug moet keren bij het beëindigen van een opgeroepen functie. De volgende blok die dan gesimuleerd wordt is de enige blok die aan een Function-blok hangt. De Operator-blok doet op zich niet zoveel, enkel een berekening die opgeslagen wordt in een variabele. Bij het uitvoeren van deze blok moet enkel opgepast worden dat de naam van de variabelen aangepast worden naar hun interne simulatienaam. De naam van de functie die voor de berekening van die naam nodig is, is gemakkelijk op te vragen. Dit is namelijk het het laatste element in de lijst van functies die in de vorige alinea vermeld werd. Net zoals bij een Function-blok, kan er slechts één blok aan een Operator-blok hangen. Dit is dan ook de volgende blok die gesimuleerd wordt. Vervolgens heb je ook nog de Call -blok. Deze roept een functie op en slaat het resultaat ervan eventueel op in een variabele. Er zijn echter twee soorten functies die opgeroepen kunnen worden. De eerste soort zijn functies die zelf aangemaakt zijn door de gebruiker. Zo roept de onderste gele Call -blok uit Fig. 4.2 de functie reset_als_groter op. De variabele tel wordt doorgegeven als parameter, hiervoor wordt er intern een nieuwe variabele aangemaakt met de naam van de functie die opgeroepen wordt. De interne naam voor variabelen wordt aangemaakt met de functienaam die als laatste aan de functielijst is toegevoegd. Bij parameters wordt de functienaam gebruikt die opgeroepen zal worden. De tweede soort zijn functies uit een externe bibliotheek. Deze bibliotheek is eerst verwerkt zoals beschreven in Hoofdstuk 3. Dit type van een Call -blok heeft als enige visueel effect op de simulatie. Deze functies zijn de functies waarvoor extra simulatiecode geschreven is (Sectie 4.2.1) en er dus voor zorgen dat de staat van een object kan veranderen. Bij het oproepen van deze functies moet er opnieuw rekening gehouden worden met de interne simulatienaam van de variabelen. Daarnaast wordt de naam als index gebruikt in de functielijst van Simulation, hieraan kunnen dan de parameters worden toegevoegd en kan de functie worden uitgevoerd. De volgende blok die gesimuleerd wordt kan dus verschillen. Bij het eerste type wordt opnieuw een Function-blok gesimuleerd. Na het beëindigen van alle blokken die tot die functie behoren, wordt de blok die aan de Call -blok hangt gesimuleerd. Bij de tweede soort wordt onmiddellijk de enige blok die aan de Call -blok hangt gesimuleerd.
HOOFDSTUK 4. SIMULATIE
38
Daarnaast is er ook nog een If -blok. Hierbij wordt eerst de conditie berekend. Deze wordt opgebouwd in de GUI als een soort boomstructuur [19] en hieruit kan de conditie dus recursief berekend worden. Hierbij moet opnieuw rekening gehouden worden met de interne naam van de variabelen. Door het evalueren van de conditie kan de volgende stap, de linker of de rechter tak, bepaald worden. Als laatste is er ook nog een While-blok. De werking hiervan lijkt goed op een If -blok, enkel is de volgende blok bepalen iets moeilijker. De conditie evalueren is exact hetzelfde al een If -blok. Indien de evaluatie van deze conditie true teruggeeft moet de code binnenin de whilelus doorlopen worden. Als de code binnenin een while-lus dan afgehandeld is, wordt er altijd teruggekeerd naar het begin van de while-lus om de conditie opnieuw te evalueren. Indien de de evaluatie van deze conditie false teruggeeft, moet er naar de eerste blok na de Whilelus gesprongen worden. Hiervoor zijn er nog twee mogelijkheden om die blok te bepalen. Ofwel is de laatste blok (de donkerpaarse blok op Fig. 4.2) al gekend omdat de while-lus al eens doorlopen is en dan kan de volgende blok onmiddellijk bepaald worden. Ofwel is het einde van de while nog niet gekend is, in de GUI [19] is er namelijk nergens een rechtstreeks verwijzing naar. Hierdoor moeten alle blokken als een gelinkte lijst overlopen worden tot er een einde van een while gevonden wordt, rekening houdend met eventuele tussenliggende While-blokken met hun overeenkomstig einde.
Hoofdstuk 5
Compilatie In de gekoppelde masterproef die handelt over de GUI [19] kan een gebruiker op een eenvoudige methode een microcontrollerprogramma schrijven. Er zijn echter nog twee stappen nodig om deze code te doen werken op een microcontroller. Ten eerste moet deze grafische code vertaald worden naar tekstuele code. Ten tweede moet deze code nog gecompileerd worden om te doen werken op een microcontroller; compilers aanvaarden namelijk enkel tekstuele code. Het vertalen naar tekstuele code heeft nog een extra voordeel. Als de gebruiker de tekstuele versie van zijn grafische code ziet, kan hij gemakkelijker tekstueel leren programmeren. Een grafische programmeertaal is namelijk een opstap naar het tekstueel programmeren.
5.1
GUI naar tekstuele programmeertaal
In deze versie wordt momenteel enkel de programmeertaal C ondersteund. De omzetting heeft veel gelijkenissen met het opstellen van de simulatiecode (Sectie 4.2.2). Opnieuw worden de blokken stap voor stap overlopen en wordt voor elke blok de overeenkomstige lijn(en) code opgesteld. Blok per blok wordt dan het type bepaald en volgens de juiste methode verwerkt. Blokken zoals een Call -blok of Operator-blok, komen overeen met één lijn C-code. Bij een Function-blok moeten opnieuw de variabelen aangemaakt worden en is er dus een extra lijn code per variabele nodig. Voor een If - en While-blok moet er rekening mee gehouden worden dat een geopende accolade (’{’) ook gesloten moet worden (’}’). Daarnaast zijn nog een aantal bijzonderheden die een extra toelichting moeten krijgen. In de Secties 3.1.2, 3.2.3 en 4.2.2 werd er vermeld dat er een XML-configuratiebestand opgesteld moet worden per bibliotheek die verwerkt wordt. Er zijn ook twee configuratieopties voor het opstellen van de tekstuele C-code. Indien gebruik wordt gemaakt van bibliotheekfuncties, moet er natuurlijk ook een #include
regel toegevoegd worden aan de C-code. In het configuratiebestand kunnen ook standaard bibliotheekbestanden opgegeven worden die bij elk programma toegevoegd moeten worden. Voor een Dwengo-microcontroller gaat dit bijvoorbeeld over dwengoConfig.h en dwengoBoard.h. Deze include-regels worden dynamisch aangevuld bij gebruik van functies uit andere bestanden. Indien in een Dwengo-programma een functie voor de LCDfunctionaliteit gebruikt wordt, zal bij het verwerken van die functie uit een Call -blok, de nodige include-regel worden toegevoegd met dwengoLCD.h. 39
HOOFDSTUK 5. COMPILATIE
40
Daarnaast heeft Dwengo Blocks als doel om gebruikers de basisprincipes van het programmeren te leren. Van sommige zaken die specifiek bij een microcontroller horen, is het beter dat een gebruiker zich er niets van moet aantrekken. Zo is er ook nog de mogelijkheid om extra functies toe te voegen aan een programma indien bepaalde bestanden uit de bibliotheek gebruikt worden. Bij Dwengo zal de functie initLCD() automatisch toegevoegd worden indien #include gedetecteerd wordt. In deze masterproef wordt Arduino vaak aangehaald als voorbeeld van een extra microcontroller. Deze C-vertaling werkt nog niet volledig voor een Arduino-programma. Arduino maakt namelijk vooral gebruikt van C++. In het XML-configuratiebestand worden ook de initiële functies gedeclareerd. Voor Arduino is dit setup en loop. Achter de schermen wordt dit echter vertaald naar een main-functie uit Codevoorbeeld 5.1. Er is dus nog extra code nodig om de setup- en loop-functies om te zetten naar zuiver C-code. 1 2 3 4 5 6 7 8 9 10 11 12 13
#include int main(void) { init(); ... setup(); for (;;) { loop(); if (serialEventRun) serialEventRun(); } return 0; }
Code 5.1: Arduino main-functie
5.2
C compilatie
Na het vertalen van de gecreëerde code in de GUI naar C-code, moet het programma nog gecompileerd en overgezet worden op een microcontroller. Hier wordt er enkel een compilatie voorzien voor een Dwengo-programma. De compilatie kan ook uitgevoerd worden op de server, waardoor de gebruiker zelf geen compiler hoeft te installeren. In de oude Dwengo Blocks versie was er al een werkende compilatiemethode. Deze maakte gebruik van de commerciële compiler van MPLAB®X [25]. Deze compiler is echter ook geen open bron software, dit in tegenstelling tot de rest van dit project. Om in het volledige project gebruik te maken van open bron software, werd de opdracht uitgebreid. Deze uitbreiding houdt in dat er bij de compilatie gebruikgemaakt wordt van een open source compiler, namelijk de SDCC-compiler [33]. Naast het installeren van de SDCC-compiler, moet GPUTILS (GNU PIC Utilities) [17] ook geïnstalleerd worden voor de correcte werking ervan. Dit zijn een aantal hulpmiddelen voor de PIC-microcontrollers van Microchip [23]. De Dwengo-microcontroller gebruikt namelijk een PIC18F4550. Voor er een programma gecompileerd kan worden, moet de Dwengo-bibliotheek eerst gecompileerd worden. SDCC kan slechts één bestand per keer simuleren. Voor het compileren van een *.c bestand uit de broncode zijn volgende opties nodig: • -c: de code moet enkel gecompileerd worden, zonder linken.
HOOFDSTUK 5. COMPILATIE
41
• -mpic16: de gegenereerde code dient voor een Microchip PIC 16-bit processor. • -p18f4550: type PIC-processor waarop de gecompileerde code gebruikt zal worden. • --use-non-free: de compilatie mag ook gebruikmaken van alle bibliotheken, ook deze die niet vrij beschikbaar zijn. Dit geeft als gevolg dat de gecompileerde code wel niet beschikbaar is onder de General Public License (GPL) [18], maar het is wel nodig om de nodige functies te ondersteunen. • -I foldername: in deze map zijn de *.h te vinden die de functies en dergelijke declareren. • --optimize-cmp: extra optie om vergelijkingen te optimaliseren indien mogelijk. • --optimize-df: extra optie om de dataflow van de gegenereerde code te optimaliseren indien mogelijk. Daarna is het de beurt aan het geschreven programma om gecompileerd te worden. Hiervoor zijn bijna alle opties gelijk, enkel de -c vervalt nu en de gecompileerde bestanden van de bibliotheek worden toegevoegd. Dit kan door alle gecompileerde *.o toe te voegen of door deze bestanden eerst te bundelen in een *.lib bestand en dit dan toe te voegen. Daarnaast dienen ook nog twee extra bibliotheekbestanden toegevoegd worden, namelijk libio18f4550.lib en libc18f.lib. Deze dienen voor de implementatie van input/output-functionaliteit en specifieke C-functies voor deze specifieke microcontroller. Het eindresultaat is dan een *.hex bestand. Er dient wel opgemerkt te worden dat er nog een aantal wijzigingen moeten gebeuren aan de bibliotheek van Dwengo, meer bepaald aan . Een microcontroller moet eerst nog geconfigureerd worden. Dit gebeurt door de configuratiebits ervan in te stellen. Meer informatie over de waarden van de bits is in de datasheet van de PIC18F4550 [29] terug te vinden. De manier van configureren gebeurde eerst op een verouderde manier, maar hiervoor kon gebruikgemaakt worden van de configuratie voor compilatie met andere microcontrollers. Deze configuratie gebruikte wel de juiste techniek en werkt ook voor SDCC. Na de algemene configuratie werken de knoppen, de vertragingen, het sensorenpaneel en de leds zonder problemen. Er zijn echter twee zaken waar er moeilijkheden opduiken. Bij het LCD-scherm werkt alles met uitzondering van de functies die een string naar het scherm schrijven. Daarnaast vertonen de motoren zeer vreemde effecten en werken niet. Over de servo’s kunnen nog geen uitspraken gedaan worden, aangezien deze nog niet getest zijn. Deze problemen kunnen wel opgelost worden. Het string-probleem was eenvoudig. Die functies verwachten namelijk een variabele van het type const FAR_ROM char* en dit wordt niet ondersteund door SDCC. Indien enkel een const char* — of om alle waarschuwingen te vermijden char * — gebruikt wordt, dan werken deze functies wel. Het probleem met de motoren was iets moeilijker. Hiervoor moet de interne PWM1 -module van de microcontroller geconfigureerd worden. In het bestand compiler/sdcc_pic16_pwm.h van de bibliotheek is hiervoor al de basis gelegd, maar dit werkt nog niet. Voornamelijk de functies openPWM2, SetDCPWM1 en SetDCPWM2 hebben een aantal wijzigingen nodig. Deze functies stellen alle registers voor het configureren van de PWM-module en zijn timer in. Voor de technische details wordt er doorverwezen naar de datasheet van de PIC18F4550 [29]. Met deze wijzigingen werkt de volledige LCD- en motorenfunctionaliteit ook. De Servo’s moeten nog getest worden en hierbij zijn waarschijnlijk nog configuratiewijzigingen voor nodig. 1
Pulse-width modulation of Pulsbreedtemodulatie
HOOFDSTUK 5. COMPILATIE
42
Na deze compilatie krijgt de gebruiker dan het *.hex bestand, maar deze moet nog overgezet worden naar de microcontroller. Hiervoor kan gebruikgemaakt worden van de handige Dwengo Programmer 2 . De installatie ervan zorgt ervoor dat bestanden met een hex-extensie gekoppeld worden aan een scriptje. Dit scriptje voert de volgende code uit: pk2cmd.exe -PPIC18F4550 -F filename -M -T -R. Hierdoor wordt de programmer van de Dwengo-microcontroller die via usb aan de computer gekoppeld is, automatisch gedetecteerd en wordt het gecompileerde programma overgeplaatst.
2
Te downloaden via http://www.dwengo.org/nl/hex
Hoofdstuk 6
Besluit 6.1
Bespreking eindresultaat
In de eerste plaats wordt er gekeken welke zaken volbracht zijn volgens de opdracht (Sectie 1.2). De kwaliteit van het afgeleverde resultaat wordt dan ook ook besproken. In de opdracht waren twee grote delen, namelijk de compatibiliteit met verschillende microcontrollerbibliotheken enerzijds en de simulatie anderzijds.
6.1.1
Inladen bibliotheken
De compatibiliteit met de microcontrollerbibliotheken (Hoofdstuk 3) is zeker geslaagd. Dit is vooral de verdienste van Doxygen. Doxygen is krachtig en heel ervaren met verschillende talen, dit komt natuurlijk heel goed uit voor dit project. De gekoppelde masterproef over de GUI [19], kon ook snel de verwerkte data interpreteren en gebruiken. Er zijn echter ook enkele nadelen. Zo zijn er enorm veel zaken beschikbaar, zoals ook te zien in de lijsten in Sectie 3.2.1. Bij het gebruik van andere talen zullen andere elementen uit deze lijsten gebruikt worden, waardoor het een enorme uitdaging is om met alle mogelijkheden rekening te houden. In het geval van de GUI voor Dwengo Blocks, valt het nog mee. Er worden namelijk nog geen klassen en dergelijke ondersteund, enkel eenvoudige functies. Bij het uitbreiden van Dwengo Blocks, zullen alle elementen wel grondiger bestudeerd moeten worden zodat er met alle talen rekening gehouden wordt. Daarnaast is het conversiescript geschreven in PHP. Dit script moet dus ook afgeschermd worden indien het op een publieke webserver staat, om te vermijden dat iedereen de bibliotheken zomaar opnieuw zou laten verwerken. Deze verwerking neemt wel wat tijd in en houdt ook een risico in. Een oude versie kan namelijk gewist worden, wanneer een gebruiker er eigenschappen van aan het gebruiken is in de GUI.
6.1.2
Simulatie
De onderdelen die op dit moment al klaar zijn voor simulatie (Hoofdstuk 4), werken ook. Dankzij de TEMPLATE.js kunnen nieuwe onderdelen ook gemakkelijk toegevoegd worden, zonder daarbij wijzigingen te moeten doorvoeren op andere plaatsen. De simulatie gaat ook 43
HOOFDSTUK 6. BESLUIT
44
niet uit van Dwengo-eigenschappen. Indien elk SimulationObject dus aangepast wordt, kan een microcontroller van bijvoorbeeld Arduino ook gesimuleerd worden. Voor de GUI zijn er gebruikerstesten uitgevoerd waarbij de simulatie ook al beschikbaar was. Het testpubliek had geen opmerkingen of ergernissen bij het gebruik van de simulatie. Er dient wel opgemerkt te worden dat deze testen gericht waren op het gebruik van de GUI waarbij ze de simulatie vrij mochten gebruiken. Dit was ook niet specifiek opgenomen in de evaluatieformulieren. Maar het testpubliek vond de simulatie heel logisch en had er geen problemen mee. Indien er ook onvolledigheden zijn in de configuratie van een blok in GUI, worden er in de simulatie ook veel fouten opgevangen. Dit zorgt ervoor dat het programma vlot blijft werken ondanks fouten. Ook de simulatie is niet perfect, ook hier zijn enkele nadelen aan verbonden. Er is wel een een communicatie-interface voorzien met de GUI zodat de GUI onafhankelijk aangepast kan worden. Maar de simulatie hergebruikt wel enkele ideeën uit de huidige GUI, namelijk de verschillende types blokken. Indien hieraan grondige wijzigingen gebeuren in de GUI, geeft dit ook invloed op de simulatie. Door de beperking tot deze blokken, is er ook geen mogelijkheid om klassen te simuleren. Dit is nu nog niet aan de orde, maar in latere versie van Dwengo Blocks zou dit wel eens een mogelijke update kunnen zijn. Zoals vermeld in een vorige alinea, kan een andere microcontroller — mits wat werk — ook gesimuleerd worden. Voorlopig kunnen deze ook niet samen gebruikt worden; er moet een keuze gemaakt worden welke simulatie op de server geplaatst wordt. Een verschillende bibliotheek voor de functies per project wordt dan weer wel ondersteund. Daarnaast kruipt er in het aanmaken van een nieuw SimulationObject toch wat werk. Zo moet alles getekend worden, functies moeten correct functioneren, eventuele events moeten kloppen. . . Dit is natuurlijk moeilijk te omzeilen. Het inladen van externe SVG’s kan eventueel ook wel toegevoegd worden. Zo kan een ontwikkelaar een nieuwe SVG met een extern professioneel programma ontwikkelen in plaats van alle coördinaten en dergelijke handmatig in te geven. Als laatste is er ook nog het timerprobleem dat ook al vermeld is in Sectie 4.2.1. Dit treedt op indien er meerder timers tegelijk lopen met een hoge frequentie.
6.1.3
Extra
Naast de verwerking van de bibliotheken en de simulatie is er ook een vertaling ontwikkeld van de GUI naar C-code. Dit is echter geen ’Extra’, maar een noodzakelijkheid voor een grafische programmeertaal. Door de blok-per-blok-aanpak bij de simulatie — de vertaling in het achterhoofd houdende — konden vele zaken hergebruikt worden. In feite is het eenvoudig: de gegenereerde C-code is correct of niet correct. De tests om de vertalingen van de verschillende blokken en structuren te controleren, werkten. Als laatste is er ook nog gekeken naar een nieuwe compilatiemethode met de SDCC-compiler. Dit is een uitbreiding op het project die later is toegevoegd om alle software open bron te kunnen maken. In eerste instantie werd hiervoor enkel de basis gelegd, maar na wat verdere ontwikkeling konden extra functionaliteiten toegevoegd worden. De servo’s zijn echter nog niet getest. De gebruiker staat voorlopig nog volledig zelf in voor de compilatie, omdat er nog geen script ontwikkeld is voor op de server.
HOOFDSTUK 6. BESLUIT
6.2
45
Mogelijke uitbreidingen
Natuurlijk zijn er ook altijd uitbreidingsmogelijkheden: software is nooit volledig af. In de vorige hoofdstukken werden ook al enkele mogelijke uitbreidingen aangehaald. Er worden weinig tot geen gegevens gefilterd uit een ingeladen bibliotheek, de weg naar het gebruik van klassen en andere programmeermogelijkheden in de GUI ligt hierdoor open. Nieuwe bibliotheken toevoegen is dus ook een uitbreidingsmogelijkheid. De uitleg hiervoor kan geraadpleegd worden in Bijlage C. De Arduino-bibliotheek bijvoorbeeld kan ook zonder problemen verwerkt worden, maar er worden voorlopig enkel standaardfuncties ondersteund in de GUI. Hierdoor kan het dus in de GUI lijken dat sommige bestanden uit de bibliotheek niet correct verwerkt zijn. Een simpele simulatie-uitbreiding is het aanmaken van een extra SimulationObject en alle functies van de bestaande objecten toevoegen. Zodanig dat er nog meer zaken uit de bibliotheek van Dwengo gesimuleerd kunnen worden. De uitleg hiervoor staat beschreven in de handleiding in Bijlage D. Er kan eventueel ook gekeken worden om de bibliotheek van bijvoorbeeld Arduino te simuleren. Er moet hiervoor dan een configuratiemogelijkheid zijn, zodat er een keuze is tussen de verschillende simulaties. Om een nieuwe microcontroller te simuleren moet hiervoor elk SimulationObject aangepast worden met nieuwe visualisaties, functionaliteiten, staten enzovoort. Indien de GUI bijvoorbeeld met programmeerklassen uitgebreid zou worden, dient de simulatie dit ook te volgen. Hierbij zal de werking van een algemeen SimulationObject en de SimulationEngine wat uitgebreid moeten worden. Ook het inladen van externe SVG’s voor het tekenen is een interessante uitbreiding. Dit kan door de initDraw-functie te vervangen door een nieuwe functie die externe SVG’s inlaadt en correct schaalt. Bij het vertalen van de GUI naar tekstuele code kunnen de talen ook uitgebreid worden. Op dit moment wordt enkel C ondersteund. Zoals besproken in Sectie 5.1 is dit onvoldoende voor bijvoorbeeld Arduino. In Hoofdstuk 5 werd ook de nieuwe SDCC-compilatie besproken. Dit is echter nog niet volledig af, want de servo’s moeten nog getest worden. Vervolgens is het ook handiger dat een gebruiker zich geen zorgen hoeft te maken over de compilatie. De compilatie zou dus beter naar de server verplaatst worden en hiervoor kan dus nog een compilatiescript geschreven worden.
Lijst van figuren 1.1 Bètaversie van Dwengo Blocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9 1.2 Reacties op het tekstueel programmeren, positieve (grijs) en negatieve (zwart) [13] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 1.3 Reacties op het visueel programmeren, positieve (grijs) en negatieve (zwart) [13] 11 2.1 2.2 2.3 2.4 2.5 2.6 2.7
bibliotheekbestanden vs Dwengo Blocks bestanden Voorbeeldfunctie C . . . . . . . . . . . . . . . . . . . Voorbeeldfunctie JavaScript . . . . . . . . . . . . . . Voorbeeldfunctie Dwengo Blocks . . . . . . . . . . . Dwengo Blocks bèta: Extra opties, if en while . . . . Dwengo Blocks bèta: samenhang bestanden . . . . Nieuwe Dwengo Blocks: samenhang bestanden . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
. . . . . . .
15 15 15 15 16 19 19
3.1 Overzicht converteren van bibliotheek . . . . . . . . . . . . . . . . . . . . . . . . . 21 3.2 Voorbeeld Dwengo-code met annotaties voor Doxygen . . . . . . . . . . . . . . . 22 3.3 Doxygen information flow [7] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 4.1 JavaScript klassen voor het weergeven en simuleren . . . . . . . . . . . . . . . . . 33 4.2 Eenvoudig binair tellen programma uit de GUI [19] . . . . . . . . . . . . . . . . . 36 A.1 Dwengo Blocks bèta: binair tellen A.2 Dwengo Blocks bèta: binair tellen
. . . . . . . . . . . . . . . . . . . . . . . . . . . 52 . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
46
Lijst met codevoorbeelden 3.1 Voorbeeld compound uit index.xml . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 3.2 Voorbeeld geconverteerde compound uit index.xml . . . . . . . . . . . . . . . . . . 26 3.3 Voorbeeld compound uit index.json . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 4.1 JavaScript Singleton [21] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 5.1 Arduino main-functie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 A.1 Oude achterliggende XML-code Binair Tellen . . . . . . . . . . . . . . . . . . . . . 53 A.2 Oude achterliggende simulatie code Binair Tellen . . . . . . . . . . . . . . . . . . 57 B.1 Voorbeeld van gedetailleerde XML informatie voor conversie . . . . . . . . . . . . 58 B.2 Voorbeeld van gedetailleerde XML informatie na conversie . . . . . . . . . . . . . 59
47
Literatuurlijst [1] MIT App Inventor. Geraadpleegd op 11 juni 2014 via http://appinventor.mit.edu/. [2] Arduino. Geraadpleegd op 11 juni 2014 via http://arduino.cc/. [3] Franklin, D., Conrad, P., Boe, B., Nilsen, K., Hill, C., Len, M., . . . & Waite, R. (maart 2013). Assessment of computer science learning in a scratch-based outreach program. In Proceeding of the 44th ACM technical symposium on Computer science education, pp. 371–376. New York: ACM. [4] Blockly. A visual prgramming editor. Geraadpleegd op 11 juni 2014 via https://code.g oogle.com/p/blockly/. [5] Rhodes, T. (augustus 2012). Convert XML to JSON in PHP. Geraadpleegd op 11 juni 2014 via http://outlandish.com/blog/xml-to-json/. [6] Doxygen. Geraadpleegd op 11 juni 2014 via http://www.doxygen.org. [7] Doxygen. Getting started. Geraadpleegd op 11 juni 2014 via http://www.stack.nl/~dim itri/doxygen/manual/starting.html. [8] Doxygen. Perl Module Output. Geraadpleegd op 11 juni 2014 via http://www.stack.nl /~dimitri/doxygen/manual/perlmod.html. [9] Dwengo. Geraadpleegd op 11 juni 2014 via http://www.dwengo.org/. [10] Dwengo Blocks BETA. Geraadpleegd op 11 juni 2014 via http://blocks.dwengo.org/. [11] Dwengo library. Geraadpleegd op 11 juni 2014 via http://www.dwengo.org/library/i ndex.html. [12] Emscripten: An LLVM-to-JavaScript Compiler. Geraadpleegd op 11 juni 2014 via https: //github.com/kripken/emscripten. [13] Booth, T. & Stumpf, S. (2013), End-user experiences of visual and textual programming environments for Arduino. In Dittrich, Y., Burnett, M., Morch, A., Redmiles, D., End-User Development, pp. 25–39. Heidelberg, Dordrecht, London, New York: Springer. [14] Flowcode. Geraadpleegd op 11 juni 2014 via http://www.matrixmultimedia.com/flo wcode.php. [15] Girl Develop It. Don’t be shy. Develop it. Geraadpleegd op 11 juni 2014 via http://www. girldevelopit.com/. [16] Girls who code. Geraadpleegd op 11 juni 2014 via http://girlswhocode.com/.
48
LITERATUURLIJST
49
[17] Gputils. GNU PIC Utilities (juni 2014). Geraadpleegd op 11 juni 2014 via http://gput ils.sourceforge.net/. [18] GNU GENERAL PUBLIC LICENSE (juni 2007). Geraadpleegd op 11 juni 2014 via http: //www.gnu.org/copyleft/gpl.html. [19] Deplorez, J. (2014). Grafisch programmeren voor microcontrollers. Masterproef, Universiteit Gent, Faculteit Ingenieurswetenschappen en Architectuur. [20] Fockedey, S. (maart 2013). Iedereen moet leren programmeren. Geraadpleegd op 11 juni 2014 via http://trends.knack.be/economie/opinie/columns/trends-com/iedereen-m oet-leren-programmeren/opinie-4000270648830.htm. [21] Dodson, R. (augustus 2012). JavaScript Design Patterns: Singleton. Geraadpleegd op 11 juni 2014 via http://robdodson.me/blog/2012/08/08/javascript-design-patterns-s ingleton/. [22] Kodu. Game lab community. Geraadpleegd op 11 juni 2014 via http://www.kodugamela b.com/. [23] Microchip. Geraadpleegd op 11 juni 2014 via http://www.microchip.com/. [24] Modkit. Geraadpleegd op 11 juni 2014 via http://www.modkit.com/. [25] MPLAB®X Integrated Development Environment (IDE). Geraadpleegd op 11 juni 2014 via http://www.microchip.com/pagehandler/en_us/family/mplabx/. [26] Berriman, A. (mei 2010). Minimum PHP Version Calculator Script. Geraadpleegd op 11 juni 2014 via http://phpduck.com/minimum-php-version-script/. [27] Open Blocks Download Page. Geraadpleegd op 11 juni 2014 via http://education.mi t.edu/openblocks. [28] Achour, M., Betz, F., Dovgal, A., Lopes, N., Magnusson, H., Richter, G., . . . & Vrana, J. (juni 2014). PHP Manual. Geraadpleegd op 11 juni 2014 via http://www.php.net/manual /en/. [29] PIC18F2455/2550/4455/4550 Data Sheet (2009). Geraadpleegd op 11 juni 2014 via ht tp://ww1.microchip.com/downloads/en/DeviceDoc/39632e.pdf. [30] Conradi, R. (mei 2013). Programmeren: vast onderdeel lesprogramma?. Geraadpleegd op 11 juni 2014 via http://www.onderwijsvanmorgen.nl/programmeren-vast-onderde el-lesprogramma/. [31] Maloney, J. H., Peppler, K., Kafai, Y., Resnick, M. & Rusk, N. (maart2008). Programming by choice: urban youth learning programming with scratch. In ACM SIGCSE Bulletin, 40, Nr. 1, pp. 367–371. [32] Malan, D. J. & Leitner, H. H. (2007). Scratch for budding computer scientists. ACM SIGCSE Bulletin, 39, nr.1, pp. 223–227. [33] SDCC - Small Device C Compiler (juni 2014). Geraadpleegd op 11 juni 2014 via http: //sdcc.sourceforge.net/. [34] Scanlan, D. A. (1989). Structured flowcharts outperform pseudocode: An experimental comparison. Software, IEEE, 6, nr. 5, pp. 28–36. [35] Scratch. Geraadpleegd op 11 juni 2014 via http://scratch.mit.edu/.
LITERATUURLIJST
50
[36] Hunt, J. (2013). Singleton. In Hunt, J., Scala Design Patterns, pp. 61–69. Cham, Heidelberg, New York, Dordrecht, London: Springer. [37] Stackexchange. Geraadpleegd op 11 juni 2014 via http://stackexchange.com/. [38] Stackoverflow. Geraadpleegd op 11 juni 2014 via http://stackoverflow.com/. [39] James, M. (juli 2013). UK To Teach Programming Starting At Age 5. Geraadpleegd op 11 juni 2014 via http://www.i-programmer.info/news/150-training-a-education /6077-uk-to-teach-programming-starting-at-5.html. [40] Whitley, K. N. (1997). Visual programming languages and the empirical evidence for and against. Journal of Visual Languages & Computing, 8, nr. 1, pp. 109–142.
Bijlage A
Oude Simulatie code - Binair Tellen Deze bijlage hoort bij sectie 2.3.1. Wat volgt is een voorbeeld te vinden van een programma geschreven in de oude versie Dwengo Blocks bèta. Sectie A.1 geeft de grafische code weer, in Sectie A.2 is de achterliggende XML-code terug te vinden en in Sectie A.3 staat de overeenkomstige simulatiecode. Voor de volledigheid worden er per sectie ook al enkele aspecten van de nieuwe versie aangehaald, zodat een vergelijking gemaakt kan worden. Het gaat om een eenvoudig programma die binair telt. Het start bij nul waarbij er geen enkele led brandt. De leds geven een binaire voorstelling van het huidige getal, waarbij het branden van een led een 1 voorstelt en het niet branden een 0. Zo stelt het binaire 10011101, 157 voor in het decimale stelsel. Op het scherm is het overeenkomstig decimale getal te volgen.
51
BIJLAGE A. OUDE SIMULATIE CODE - BINAIR TELLEN
A.1
52
Grafische code
De oude GUI om binair te tellen is weergegeven in Fig. A.1. In Fig. A.2 is een voorlopige versie te zien van de nieuwe GUI [19] met ongeveer hetzelfde programma. Hierin zitten wel nog een paar onvolledigheden en fouten.
Fig. A.1: Dwengo Blocks bèta: binair tellen
BIJLAGE A. OUDE SIMULATIE CODE - BINAIR TELLEN
53
Fig. A.2: Dwengo Blocks bèta: binair tellen
A.2
XML-code
In Codevoorbeeld A.1 is de achterliggende XML-code te zien van Fig. A.1, deze code wordt verwerkt tot simulatiecode. In de nieuw versie die ontwikkeld wordt in de masterproef, zal er geen tussenstap naar XML-code meer gemaakt worden. 1 2 3 4 5 6 7 8 9
<node id="mainSource" type="start" x="144.6842878120411" y="-211.00187909304915" >
<port class="out" id="mainSourceoutPort" connection="c0" /> <node id="mainSink" type="end" x="318.3568746841957" y="94.90105662102575" >
BIJLAGE A. OUDE SIMULATIE CODE - BINAIR TELLEN 10 11 12 13 14 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 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
<port class="in" id="mainSinkinPort" connection="c3" /> <node id="n0" type="basic" x="144.85315712187955" y="-166.00187909304915" > <procedure name="backlightOn" /> <port class="in" id="n0inPort" connection="c0" /> <port class="out" id="n0outPort" connection="c1" /> <node id="n1" type="basic" x="145.54003681202718" y="-116.00187909304915" > <procedure name="appendStringToLCD" /> <param name="message" value="waarde is:"/> <port class="in" id="n1inPort" connection="c1" /> <port class="out" id="n1outPort" connection="c18" /> <node id="n5" type="while" x="146.860239855541" y="49.7460147852701" >
<expressionBuilderContent version="1.0"> <port class="in" id="n5inPort" connection="c19" /> <port class="fb" id="n5fbPort" connection="c2" /> <port class="loop" id="n5loopPort" connection="c5" /> <port class="out" id="n5outPort" connection="c3" /> <node id="n6" type="fb" x="88.46013579726811" y="550.8413292228088" > <port class="in" id="n6inPort" connection="c6" /> <port class="fb" id="n6fbPort" connection="c2" /> <node id="n8" type="basic" x="183.16034386253742" y="180.53064489066801" > <procedure name="delay_ms" /> <param name="ms" value="100"/> <port class="in" id="n8inPort" connection="c16" /> <port class="out" id="n8outPort" connection="c17" /> <node id="n11" type="assign" x="141.63151311956514" y="-42.366991309087176" >
<expressionBuilderContent version="1.0"> <port class="in" id="n11inPort" connection="c18" /> <port class="out" id="n11outPort" connection="c19" /> <node id="n12" type="start" x="-171.5231696407442" y="-215.31399574990232" >
<param name="waarde" type="int"/> <port class="out" id="n12outPort" connection="c4" /> <node id="n13" type="end" x="-172.23516235985312" y="-65.44207475019758" > <port class="in" id="n13inPort" connection="c11" />
54
BIJLAGE A. OUDE SIMULATIE CODE - BINAIR TELLEN 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 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
<node id="n14" type="basic" x="-171.33472528130724" y="-170.31399574990232" > <procedure name="setLedRegister" /> <param name="led" value="waarde"/> <port class="in" id="n14inPort" connection="c4" /> <port class="out" id="n14outPort" connection="c10" /> <node id="n15" type="basic" x="173.93908368360636" y="122.54353762098143" > <procedure name="toon" /> <param name="waarde" value="tel"/> <port class="in" id="n15inPort" connection="c5" /> <port class="out" id="n15outPort" connection="c16" /> <node id="n17" type="if" x="251.22967440948668" y="285.2590175198616" >
<expressionBuilderContent version="1.0"> <port class="in" id="n17inPort" connection="c17" /> <port class="no" id="n17noPort" connection="c8" /> <port class="yes" id="n17yesPort" connection="c7" /> <node id="n18" type="join" x="251.22967440948668" y="518.8270113993223" > <port class="no" id="n18noPort" connection="c9" /> <port class="yes" id="n18yesPort" connection="c15" /> <port class="out" id="n18inPort" connection="c6" /> <node id="n19" type="assign" x="354.5082169313387" y="326.29192807876217" >
<expressionBuilderContent version="1.0"> <port class="in" id="n19inPort" connection="c7" /> <port class="out" id="n19outPort" connection="c12" /> <node id="n2" type="assign" x="171.37366238728666" y="341.0925160533173" >
<expressionBuilderContent version="1.0">
55
BIJLAGE A. OUDE SIMULATIE CODE - BINAIR TELLEN 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
<port class="in" id="n2inPort" connection="c8" /> <port class="out" id="n2outPort" connection="c9" /> <node id="n4" type="basic" x="-171.20519336173257" y="-119.3717739527176" > <procedure name="printIntToLCD" /> <param name="number" value="waarde"/> <param name="line" value="0"/> <param name="position" value="11"/> <port class="in" id="n4inPort" connection="c10" /> <port class="out" id="n4outPort" connection="c11" /> <node id="n7" type="basic" x="354.8162977443364" y="376.29192807876217" > <procedure name="clearLCD" /> <port class="in" id="n7inPort" connection="c12" /> <port class="out" id="n7outPort" connection="c13" /> <node id="n9" type="basic" x="354.8162977443354" y="426.29192807876217" > <procedure name="printStringToLCD" /> <param name="message" value="waarde is:"/> <param name="line" value="0"/> <param name="position" value="0"/> <port class="in" id="n9inPort" connection="c13" /> <port class="out" id="n9outPort" connection="c14" /> <node id="n10" type="basic" x="355.985479963449" y="476.29192807876217" > <procedure name="delay_ms" /> <param name="ms" value="500"/> <port class="in" id="n10inPort" connection="c14" /> <port class="out" id="n10outPort" connection="c15" />
Code A.1: Oude achterliggende XML-code Binair Tellen
56
BIJLAGE A. OUDE SIMULATIE CODE - BINAIR TELLEN
A.3
57
Simulatiecode
In Codevoorbeeld A.2 is de simulatiecode te zien die berekend wordt uit de XML-code uit Codevoorbeeld A.1. Deze simulatie wordt lijn per lijn uitgevoerd, telkens met een korte pauze door de timer. Elke !SCOPE! wordt net voor het uitvoeren vervangen door de functienaam waar het programma zich op dat moment bevindt. In de nieuwe versie die besproken wordt in Hoofdstuk 4, wordt de simulatiecode niet meer op voorhand berekend. Dit gebeurt namelijk on the fly, de uit te voeren JavaScript-code wordt berekend bij de uitvoering van iedere blok. De nieuwe code die berekend wordt, is terug te vinden in simulationEngine.js en wordt besproken in Sectie 4.2.2. 1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
_dwengo_simulator_scope=""; _dwengo_simulator_stack=""; PC++; !SCOPE!tel=0; NOP=true; PC++; initBoard(); PC++; initLCD(); PC++; backlightOn(); PC++; appendStringToLCD("waarde is:"); PC++; !SCOPE!tel= /*NUM*/0 ; PC++; if ( /*NUM*/TRUE ) { PC++; } else { PC+=13; } /* USERFUNCTION toon */ !SCOPE!_toonwaarde = !SCOPE!tel; _dwengo_simulator_scope= _dwengo_simulator_scope+"_toon"; _dwengo_simulator_stack=_dwengo_simulator_stack+"_"+(PC+1); PC=prog_func[’toon’]; delay_ms(100); PC++; if (!SCOPE!tel== /*NUM*/0xFF ) { PC++; } else { PC+=7; } !SCOPE!tel= /*NUM*/0 ; PC++; clearLCD(); PC++; printStringToLCD("waarde is:", 0, 0); PC++; delay_ms(500); PC++; NOP=true; PC+=4; NOP=true; PC++; /* else {, hier komen we nooit*/ !SCOPE!tel=!SCOPE!tel+ /*NUM*/1 ; PC++; NOP=true; PC++ NOP=true; PC-=12; STOP PC++; setLedRegister(!SCOPE!waarde); PC++; printIntToLCD(!SCOPE!waarde, 0, 11); PC++; RETURN
Code A.2: Oude achterliggende simulatie code Binair Tellen
Bijlage B
Conversie Doxygen output Deze bijlage hoort bij het puntje 3.2.1 dat handelt over de conversie van een gedetailleerd outputbestand van Doxygen. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
dwengoMotor.h <sectiondef kind="define"> ... <sectiondef kind="func"> ... <memberdef kind="function" id="dwengo_motor_8h_1a770e47a93416c3e81862b7ad60de2f2a" prot=" public" static="no" const="no" explicit="no" inline="no" virt="non-virtual"> void <definition>void setSpeedMotor1 <argsstring>(short speed) setSpeedMotor1 <param> short <declname>speed <para>Set speed of motor 1. <detaileddescription> <para>Sets speed of motor 1 in range [-1023,1023]. A delay of a few milliseconds is performed when switching speed abruptly from positive to negative or vice versa. <parameterlist kind="param"> <parameteritem> <parameternamelist> <parametername>speed <parameterdescription><para/> ...
58
BIJLAGE B. CONVERSIE DOXYGEN OUTPUT 38 39 40 41 42 43 44 45
<para>Motor functionality. <detaileddescription> <para>Control of motor driver on the Dwengo board <parentdirectory>lib
Code B.1: Voorbeeld van gedetailleerde XML informatie voor conversie 1 2 3 4 5 6 7 8 9 10 11 12 13 14 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 47 48 49
dwengo_motor_8h file <sealed/> <protection/> dwengoMotor.h <define> ... <define> ... ... dwengo_motor_8h_1a770e47a93416c3e81862b7ad60de2f2a function void <definition>void setSpeedMotor1 <argsstring>(short speed) setSpeedMotor1 <param> short <declname>speed <para>Set speed of motor 1. <detaileddescription> <para>Sets speed of motor 1 in range [-1023,1023]. A delay of a few milliseconds is performed when switching speed abruptly from positive to negative or vice versa. < parameterlist kind="param"> <parameteritem> <parameternamelist> <parametername>speed <parameterdescription> <para/> ... <para>Motor functionality.
59
BIJLAGE B. CONVERSIE DOXYGEN OUTPUT 50 51 52 53 54 55
<detaileddescription> <para>Control of motor driver on the Dwengo board <parentdirectory>lib
Code B.2: Voorbeeld van gedetailleerde XML informatie na conversie
60
Bijlage C
Handleiding: Bibliotheken verwerken en gegevens opvragen
61
Handleiding: Bibliotheken verwerken en gegevens opvragen Deze handleiding legt uit hoe een microcontrollerbibliotheek verwerkt moet worden, zodat deze gebruikt kan worden in de grafische programmeeromgeving Dwengo Blocks.
Vereisten en installatie Dwengo Blocks is een webapplicatie. Dit houdt in dat een gebruiker alles in zijn webbrowser kan uitvoeren. Als ontwikkelaar en aanbieder van de dienst is er iets meer werk. Zo moet bijvoorbeeld alles beschikbaar gesteld worden via een webserver. Met uitzondering van enkele noodzakelijkheden, wordt er uitgegaan van de kennis van de ontwikkelaar voor het configureren van de webserver. Ook zijn er enkele externe programma’s nodig voor het verwerken van de bibliotheken. Alle noodzakelijkheden voor de server zijn de volgende: • Webserver1 met minimum PHP 5.2 met volgende instellingen in php.ini : – extension=php_xsl.dll. – max_execution_time verhogen bij grotere bibliotheken. – Voor de andere php.ini -configuratie-instellingen wordt er uitgegaan van de standaardinstallatie van een WampServer1 . De ontwikkelaar kan naar wens hier wel aanpassingen aan doen, maar moet dan zelf de functionaliteit nog testen. – De PHP-scripts hebben ook volledige toegang en rechten nodig in de map libraries. Hier worden veel bestanden en mappen aangemaakt, gewijzigd en soms verwijderd. Voor het aanpassen van deze rechten wordt er gerekend op de kennis van de ontwikkelaar, want het aanpassen van deze rechten is anders op verschillende besturingssystemen. • Doxygen2 1.8.63 . Zorg ervoor dat Doxygen aan te roepen is zonder het installatiepad. Bij Windows kan dit door de PATH-variabele aan te passen indien dit niet automatisch 1
Een eenvoudige en volledige webserver is WampServer http://www.wampserver.com/. De nieuwste versie is beschikbaar via http://www.stack.nl/~dimitri/doxygen/download.html#srcbin 3 Doxygen 1.8.7 is ondertussen ook al beschikbaar, maar nog niet getest. Versie 1.8.6 is beschikbaar via ftp: //ftp.stack.nl/pub/users/dimitri/ 2
gebeurd. • SDCC4 en GPUTILS5 indien de compilatie ook afgewerkt is en ondersteund moet worden. De gebruiker heeft aan een recente browser genoeg. Na de installatie van de hulpprogramma’s, moet de broncode enkel nog gekopieerd worden naar de webserver.
Nieuwe bibliotheken verwerken Bibliotheek toevoegen Een nieuwe bibliotheek toevoegen is eenvoudig. Dit kan door een nieuwe map aan te maken met een eigen gekozen bibliotheeknaam in de map libraries. In deze nieuwe map moet de code van de bibliotheek in een map met de naam source geplaatst worden. Alle andere mappen en bestanden die te vinden zijn in vooraf verwerkte bibliotheken worden allemaal automatisch gecreëerd.
Opties configureren Na het kopiëren van de bibliotheek moet er ook nog een een configuratiebestand aangemaakt worden. Dit moet in de map projectTemplates geplaatst worden. Het bestand TEMPLATE.xml is een ideale vertrekbasis. Maak hier dus eerst een kopie van en geef het een eigen gekozen naam. Hieronder worden enkel de opties besproken die nodig zijn voor het verwerken van de bibliotheken. De juiste XML-structuur voor die opties kan in het bestand TEMPLATE.xml teruggevonden worden. Deze opties hebben invloed op de verwerking van Doxygen. • library: dit is de mapnaam van de bibliotheek waarin de source-map werd gecreëerd. • file_patterns: alle bestanden van de bibliotheek die matchen aan een wildcard uit deze lijst worden verwerkt, de rest niet. Elk patroon wordt in een afzonderlijk file_patternelement geplaatst. Indien er geen patronen worden gespecificeerd, worden de volgende patronen getest: *.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, *.qsf, *.as en *.js. • excludes: hiermee kunnen bestand en/of mappen uitgesloten worden. Dit is enkel voor unieke onderdelen, dus geen wildcards (bij mappen wordt de inhoud ook uitgesloten). Alle specificaties zijn ook relatief aan de source-map. Elke map- of bestandsspecificatie wordt in een afzonderlijk exclude-element geplaatst. • exclude_patterns: dit lijkt op excludes, maar hier kan er ook gebruik gemaakt worden van wildcards. Hiermee kunnen bijvoorbeeld verschillende test-mappen uitgesloten worden door het patroon */test/*. Elk patroon wordt in een afzonderlijk exclude_pattern-element geplaatst. 4 5
http://sdcc.sourceforge.net/ http://gputils.sourceforge.net/
• exclude_symbols: hiermee kunnen bijvoorbeeld functies, namespaces of klassen uitgesloten worden. Elke specificatie wordt in een afzonderlijk exclude_symbol -element geplaatst.
Verwerken Na het configureren van de opties, kan de uiteindelijke verwerking beginnen. Dit kan door het convertLibraries.php-script op te roepen met als configfile-parameter de naam van het XML-configuratiebestand uit de vorige sectie. Zo zal de aanroep convertLibraries.php?c onfigfile=dwengo, de Dwengo-bibliotheek verwerken. Met uitzondering van het configureren van de opties en het kopiëren van de bibliotheek naar de juiste locatie, wordt al het werk dus gedaan door het conversiescript.
Gegevens opvragen uit bibliotheek In de vorige sectie werden alle gegevens uit een bibliotheek verwerkt. Nu volgt de methode om deze gegevens dynamisch te kunnen opvragen. Dit kan door het libInformationService.php-script op te roepen met als verplichte lib -parameter de naam van de bibliotheek waaruit gegevens op te vragen zijn. Deze bibliotheeknaam is de naam van de map waarin de source-map werd gecreëerd in de eerste stap en dit is ook het library-element uit het XMLconfiguratiebestand. Naast de lib -parameter, is er nog een optionele id -parameter. Indien deze niet wordt meegegeven (of als deze blanco is), wordt een overzicht gegeven van alle beschikbare informatie. Elk onderdeel heeft hierin zijn eigen refid of id. Bij een refid staat de gedetailleerde informatie op een andere plaats, dit is dus een referentie naar een id. Als zo’n id wordt meegegeven als parameter, wordt er meer gedetailleerde informatie opgevraagd. Dit kan opgevraagd worden voor elke id, gaande van bestanden of klassen tot het type van een parameters van een bepaalde functie. Een voorbeeld van een aanroep ziet er zo uit: libInformationService.php?lib=Dwengo&i d=dwengo_board_8h_1aef5e2223369f50020bf6f7b5593e6385.
Bijlage D
Handleiding: Uitbreiden simulatie
65
Handleiding: Uitbreiden simulatie Dze handleiding legt uit hoe de simulatie van de grafische programmeeromgeving Dwengo Blocks uitgebreid kan worden met nieuwe functionaliteiten. Eenmaal de ontwikkelaar deze uitbreidingen zelf kan uitvoeren, kan hij vrij eenvoudig ook andere functionaliteiten van andere simulatie-onderdelen aanpassen.
Nieuw SimulationObject aanmaken Om een nieuwe functionaliteit toe te voegen aan de simulatie moet een nieuw SimulationObject aangemaakt worden. Zo’n object bevat de volledige functionaliteit van een onderdeel uit de bibliotheek. Bij Dwengo is zo’n onderdeel een headerbestand met zijn bijhorende implementaties. Een nieuw SimulationObject kan aangemaakt worden door een nieuw JavaScript-bestand aan te maken in de map scripts/simulation/lib. Hierbij wordt het best vertrokken van het bestand TEMPLATE.js. In deze template is de structuur van een nieuw object al ingevuld, waardoor er vlot een nieuw object kan aangemaakt worden. Het eerste dat verandert moet worden is de JavaScript-naam van de variabele die alle nieuwe functionaliteit zal bevatten. Elk functioneel onderdeel van de simulatie wordt namelijk in een variabele opgeslagen. In de template is de naam van die variabele simulation_TEMPLATE. De TEMPLATE moet aangepast worden naar een unieke naam, bij voorkeur de bestandsnaam. Deze naam moet zeker uniek zijn binnen de simulatie om conflicten met variabelen te vermijden. Met een zoek- en vervangfunctie kan simulation_TEMPLATE eenvoudig vervangen worden door zijn nieuwe naam. Bij het oproepen van de constructor moeten ook twee parameters meegegeven worden: het type object en een naam. Er zijn drie type objecten: • simObjectType.BOARD: al deze objecten worden in dezelfde tekenruimte getekend. Dit is het basisbord met bijvoorbeeld een LCD-scherm, ledjes en knoppen. • simObjectType.PERIPHERAL: elk object krijgt een aparte tekenruimte en deze tekenruimtes worden allemaal onder elkaar getekend. • simObjectType.OTHER: deze objecten worden niet getekend en dienen enkel voor
extra niet-visuele functionaliteit. Uit de Dwengo-bibliotheek is dit bijvoorbeeld dwengoDelay. De naam wordt ook weergegeven in de simulatie. In TEMPLATE.js is dit ingevuld met ’filename’, maar hier kan om het even welke naam aan gegeven worden.
Staten Elk SimulationObject heeft zijn eigen staten. Een staat is een eigenschap die kan veranderen. Bijvoorbeeld een led kan aan of uit staan. Elke staat moet geregistreerd worden met de functie registerState van het object die in de vorige sectie is aangemaakt. Hieraan moet de naam en de standaardwaarde van de staat meegegeven worden. De naam van de waarde wordt het best opnieuw consistent opgebouwd. In TEMPLATE.js wordt aangeraden om elke staat als volgt te benoemen simulation_TEMPLATE_statename1, hierbij wordt TEMPLATE aangepast zoals gebeurde in de vorige sectie en statename1 door een eigen gekozen naam die duidelijk kan maken waarvoor de staat dient. Staten kunnen later opgevraagd worden met de functie getState(’simulation_TEMPLATE_statename1’) van het SimulationObject. Aanpassingen kunnen gebeuren met de functie setState(’simulation_TEMPLATE_statename1’, ’newValue’), hierdoor zal dit object zijn staatswijziging automatisch doorvoeren in de visualisatie.
Visualisatie De functie registerInitDraw krijgt een functie mee die moet zorgen voor het tekenen van het SimulationObject. De ontwikkelaar kan dus zelf SVG-elementen tekenen in de viewport die in de functie ter beschikking wordt gesteld. Alles moet in percentages getekend worden, wat het schalen makkelijker maakt. De breedte wordt geschaald naar 100 pixels en de hoogte is variabel, maar in dezelfde verhoudingen als de breedte. Zaken die breder zijn dan 100 pixels, worden niet getekend. Natuurlijk kan de ontwikkelaar zelf transformaties toevoegen waardoor bredere elementen naar die 100 pixels geschaald worden. Het SimulationObject mag om het even welke hoogte hebben; de simulatie zal ervoor zorgen dat alles mooi onder elkaar getekend wordt zonder overschot of tekort aan witruimte. In de template staan enkele voorbeelden hoe objecten getekend kunnen worden. Er zijn ook enkele standaard tekeningen beschikbaar via defaultDrawings van de algemene Simulation, zie TEMPLATE.js voor enkele voorbeelden. Alle variabele elementen moeten een unieke id krijgen, met een gelijkaardige opbouw zoals de namen van een staat. Deze unieke id zorgt ervoor dat ze eenvoudig toegankelijk zijn om te manipuleren. Deze variabele elementen zijn bijvoorbeeld ledlichtjes. De functie die aan registerUpdateDraw wordt meegegeven, moet ervoor zorgen dat alle variabele elementen correct worden aangepast aan de staten. Hier moeten alle staten opgevraagd worden met behulp van de functie getState en afhankelijk van de waarde, moet een element aangepast worden. Deze elementen zijn aanpasbaar via hun id. Deze functie wordt opgeroepen telkens de staat van dit SimulationObject wijzigt.
Functionaliteit De functie addFunction kan gebruikt worden om verschillende functies te declareren. Hieraan kan een functienaam en een JavaScript-functie meegegeven worden. Deze JavaScriptfunctie staat in voor de staatswijzigingen van het SimulationObject. Alle staatswijzigingen moeten gebeuren met de functie setState zodat de visualisatie correct kan aangepast worden.
Events Tot slot kunnen er ook nog verschillende events aan een object worden gekoppeld. Dit is handig bij externe input zoals bij het gebruik van knoppen. Enerzijds moeten de events gekoppeld worden aan een actie van de gebruiker en anderzijds moet het event gekoppeld worden aan een interne reactie zoals een staatswijziging. Het koppelen van een actie aan een reactie gebeurd door de functie addEvents van een SimulationObject te declareren waarin alle koppelingen worden opgeroepen. Een voorbeeld van een koppeling staat in TEMPLATE.js. De functie of de reactie die uitgevoerd moet worden is bij voorkeur een functie die enkel via het specifieke SimulationObject toegankelijk is. Hierdoor zijn er geen problemen met dubbele namen bij functies. Als een functie aan een actie is gekoppeld, moet deze functie natuurlijk ook gedeclareerd worden. Vaak is dit een staatswijziging.