Profielwerkstuk-–-Open-source,-open-data-&-Hoe-laat-komt-mijn-tram?Sven-Boor-&-Arjen-Kremers-–-Gymnasium-Novum-
OPEN%SOURCE,%OPEN%DATA%&HOE%LAAT%KOMT%MIJN%TRAM?Sven-Boor-&-Arjen-KremersGymnasium-Novum12-maart-2013-
1-
Profielwerkstuk-–-Open-source,-open-data-&-Hoe-laat-komt-mijn-tram?Sven-Boor-&-Arjen-Kremers-–-Gymnasium-Novum-
VOORWOORDDit-project-begon-in-het-voorjaar-van-2012,-meneer-Van-Leeuwen,-natuurkunde-docent-op-onzeschool-en-tevens-onze-begeleider,-liet-ons-een-computertje-zien-dat-makkelijk-zelf-teprogrammeren-was,-de-Arduino.-Deze-computer-sloot-prima-aan-bij-onze-wens-om-iets-te-doenmet-programmeren-en-praktisch-bezig-te-zijn.-Meneer-Van-Leeuwen-gaf-ons-een-Arduino-meeom-mee-te-experimenteren.-Vervolgens-hebben-wij-met-de-Arduino-een-verbeterde-versie-vaneen-valproef-gemaakt.--Het-programma-hebben-we-geschreven-in-C.-Vervolgens-hebben-we-eenhardware-versie-van-de-hele-oplossing-laten-maken-waardoor-de-proef-met-behulp-van-deArduino-als-microprocessor-direct-inzetbaar-is-in-de-klas.Een-aantal-displays-aan-tramlijn-15-in-Den-Haag-toont-al-enkele-jaren-geen-reisinformatie-meer.Dit-bleek-te-worden-veroorzaakt-door-gesloten-systemen.-Er-was-geen-documentatie-van-dedisplays-en-van-de-interfaces.-Hierdoor-was-het-noodzakelijk-de-specificaties-via-reverseengineering-boven-tafel-te-krijgen.-Door-de-Arduino,-als-open-source-computer,-zijn-we-gaanonderzoeken-of-het-mogelijk-was-om-met-de-Arduino-een-goedkope-oplossing-te-realiseren-omweer-actuele-reisinformatie-te-tonen.-In-dit-werkstuk-hebben-we-dat-onderzocht-en-eenoplossing-gevonden.-De-Arduino-bleek-niet-genoeg-mogelijkheden-te-geven-om-én-de-data-te-ontvangen-en-teverwerken-én-om-deze-om-te-zetten-naar-het-RS232-signaal-dat-het-LEDXdisplay-verwachtte.Daarom-hebben-we-de-hulp-ingeroepen-van-de-Raspberry-Pi,-een-budgetXmicrocomputer-waarinwe-met-een-Linux-variant-de-taal-Python-konden-draaien.-We-moesten-op-een-server-eenprogramma-maken-dat-de-open-datastroom-met-actueleXreisinformatie-informatievoorbewerkte-voor-de-afzonderlijke-haltes,-zodat-de-datastroom-naar-de-halteplaats-zeerbeperkt-kan-blijven.-We-hebben-ons-de-taal-Python-eigen-gemaakt-en-waren-zo-in-staat-voor-ca.€100-aan-consumenteninkoopsprijs-de-haltes-reizigersinformatie-te-laten-weergeven.-HetStadgewest-Haaglanden-en-HTM-zijn-geïnteresseerd-in-het-implementeren-van-de-oplossing,voor-het-aanpassen-van-200-andere-displays-in-de-regio-loopt-een-ander-project.-Het-budgetvoor-dit-project-is--€300.000-–-€400.000.-Realisatie-met-behulp-van-ons-openconcept--is-voor-Haaglanden-veel-voordeliger.-Een-demonstratie-van-het-probleem-en-onze-oplossing-is-te-bekijken-viahttp://vimeo.com/60644074-of-door-onderstaande-QR-code-te-scannen.-Graag-bedanken-wij-meneer-Van-Leeuwen-en-meneer-Van-Soest-voor-de-ondersteuning-enbegeleiding-van-ons-werkstuk.-Meneer-Van-Soest-in-het-bijzonder-voor-al-het-solderen-en-eenpermanente-opstelling-maken-van-de-valproef.-Daarnaast-willen-we-het-hostingbedrijf-CJ2bedanken-voor-het-sponsoren-van-een-server-en-JC-Decaux,-de-exploitant-van-de-abri’s,-voor-demedewerking-bij-het-ter-beschikking-stellen-van-het-display.-
-
-
2-
Profielwerkstuk-–-Open-source,-open-data-&-Hoe-laat-komt-mijn-tram?Sven-Boor-&-Arjen-Kremers-–-Gymnasium-Novum-
INHOUDVoorwoord-...............................................................................................................................................................................-2! Inhoud-........................................................................................................................................................................................-3! Inleiding-....................................................................................................................................................................................-4! Valproef-..........................................................................................................................................................................................-5! Algemeen-..................................................................................................................................................................................-6! Hardware-..................................................................................................................................................................................-7! Onderdelen-..........................................................................................................................................................................-7! Schakelschema-...............................................................................................................................................................-11! Problemen-........................................................................................................................................................................-12! Software-.................................................................................................................................................................................-13! Programma-......................................................................................................................................................................-13! Verbeteringen-.................................................................................................................................................................-17! Handleiding-...........................................................................................................................................................................-18! Tramdisplay-...............................................................................................................................................................................-20! Probleemstelling-.................................................................................................................................................................-21! Realisatie-................................................................................................................................................................................-25! Programmatuur-..................................................................................................................................................................-34! Conclusie-.....................................................................................................................................................................................-48! Bronvermelding-.......................................................................................................................................................................-49! -
-
3-
Profielwerkstuk-–-Open-source,-open-data-&-Hoe-laat-komt-mijn-tram?Sven-Boor-&-Arjen-Kremers-–-Gymnasium-Novum-
INLEIDINGOpen-source-en-open-data-zijn-twee-begrippen-die-de-afgelopen-jaren-overal-in-de-IT-wereldopduiken.-Maar-wat-houden-beiden-begrippen-in-en-wat-kan-men-ermee?Dit-profielwerkstuk-is-het-verslag-van-ons-onderzoek-naar-open-data-en-open-source.-Ditonderzoek-is-gedaan-door-het-houden-van-praktijkproeven-maken-in-twee-losse-projecten.Het-eerste-project-diende-vooral-als-reserve-voor-als-het-tweede,-grote-project-niet-van-de-grondzou-komen-wegens-onvoorziene-problemen.-Het-project-hield-een-natuurkundige-proef-inwaarbij-de-gravitatieversnelling-van-de-aarde-bepaald-kan-worden-met-behulp-van-de-tijd-dateen-kogeltje-erover-doet-om-over-een-bepaalde-afstand-te-vallen.-Het-doel-van-het-project-wasom-deze-tijd-nauwkeurig-te-meten-met-behulp-van-een-zelf-geprogrammeerde-open-sourcemicrocontroller.-Deze-opstelling-kan-dan-door-de-natuurkundesectie-op-het-Gymnasium-Novumworden-gebruikt-bij-het-onderwijs.Het-tweede-project-is-het-hoofdproject.-Het-doel-is-om-een-oud-LEDXscherm-dat-op-tramhaltes-tegebruikt-werd-om-vertrektijden-van-trams-weer-te-geven-en-niet-langer-functioneerde-nieuwleven-in-te-blazen-door-gebruik-te-maken-van-open-data-en-open-source.OPEN-DATA-EN-OPEN-SOURCE-SOFTWAREOpen-Data-zijn-gegevens-die-vrij-van-rechter-voor-hergebruik-ter-beschikking-wordt-gesteld.Meestal-door-de-overheid,-maar-ook-andere-organisaties-kunnen-open-data-beschikbaar-stellen.-Open-Data-kan-de-basis-vormen-voor-nieuwe-diensten-met-toegevoegde-waarde.-Als-burgers-enbedrijven-vrij-kunnen-beschikken-over-deze-open-data,-kunnen-ze-nuttige-nieuwe-toepassingenontwikkelen.-Een-voorbeeld-is-Buienradar,-dat-gebruik-maakt-van-gegevens-van-het-KNMI.Kortom-met-het-vrijgeven-ven-Open-Data,-kunnen-economische-activiteiten-worden-ontplooid.Open-source-software-betekent-dat-de-broncode-waarin-de-software-is-geschreven-vrijbeschikbaar-is.-Iedereen-kan-de-broncode-lezen,-aanpassen-en-verspreiden.-Bij-andere-‘geslotensource’-software-is-de-gebruiker-afhankelijk-van-de-oorspronkelijke-leverancier-en-heeft-zelfgeen-toegang-tot-de-broncode.-Net-als-open-standaarden-is-open-source-software-belangrijk-ommeer-openheid-in-ICT-systemen-te-realiseren.De-combinatie-van-Open-Data-en-open-source-software-kunnen-en-innovatie-en-educatie-eenenorme-impuls-geven.-
-
4-
Profielwerkstuk-–-Open-source,-open-data-&-Hoe-laat-komt-mijn-tram?Sven-Boor-&-Arjen-Kremers-–-Gymnasium-Novum-
VALPROEFVAN-ANALOOG-NAAR-DIGITAAL-
-
5-
Profielwerkstuk-–-Open-source,-open-data-&-Hoe-laat-komt-mijn-tram?Sven-Boor-&-Arjen-Kremers-–-Gymnasium-Novum-
ALGEMEENMet-de-valproef-die-beschreven-wordt-kan-de-valversnelling-uitgerekend-worden.-Devalversnelling-wordt-bepaald-door-de-afstand-dat-het-kogeltje-valt-en-de-tijd-die-het-kogeltjedaarover-doet-nauwkeurig-te-meten.-De-beschrijving-is-opgedeeld-in-een-stuk-over-hardware,software-en-een-handleiding-over-hoe-de-opstelling-gebouwd-kan-worden.De-valproef-werd-in-het-verleden-al-gebruikt,-alleen-was-er-altijd-een-groot-probleem-met-detijdwaarneming.-De-externe-timer-waarmee-wordt-gewerkt-is-namelijk-erg-gevoelig.-Vroegerwerd-de-timer-op-een-‘analoge’-manier-geactiveerd.-Er-treedt-dan-een-bounce-effect-op-bij-hetindrukken-van-een-schakelaar.-Dit-is-een-stuitering-of-schommeling-van-de-spanning-bij-hetafschakelen-van-de-stroom.-De-timer-werkt-alleen-op-digitale-signalen,-dus-kan-alleen-een-laagen-een-hoog-signaal-waarnemen.-De-schommeling-van-de-spanning-is-voor-de-timer-eenwisselend-aanX-en-uitsignaal,-dit-is-niet-nauwkeurig-genoeg.-Door-nu-een-stukje-elektronica-toete-voegen-kunnen-we-softwarematig-dat-bounce-effect-ondervangen-zodat-het-geen-storendewerking-heeft.-Hierbij-wordt-voor-het-aansturen-van-de-timer-gebruik-gemaakt-van-een-digitaalsignaal.-
-
-
6-
Profielwerkstuk-–-Open-source,-open-data-&-Hoe-laat-komt-mijn-tram?Sven-Boor-&-Arjen-Kremers-–-Gymnasium-Novum-
HARDWAREDe-hardware-wordt-in-drie-onderdelen-behandeld.-In-het-eerste-onderdeel-wordt-uitgelegdwelke-onderdelen-in-het-circuit-zijn-opgenomen-en-welke-functie-ze-hebben.-In-het-tweede-deelwordt-uitgelegd-hoe-de-verschillende-onderdelen-met-elkaar-samenhangen-en-in-het-laatste-deelworden-problemen-met-de-hardware-behandeld.-
ONDERDELENHieronder-volgt-een-lijst-met-alle-onderdelen-die-in-het-circuit-opgenomen-zijn.X X X X X X X X X X X
Arduino-microcontroller1-rode-LED1-gele-LEDdrukknopspoelluikexterne-spanningsbronFETdiodeexterne-timerweerstanden-
ARDUINODe-Arduino1-is-een-programmeerbare-microcontroller-die-softwarematig-reageert-op-signalenvan-sensoren-die-erop-aan-te-sluiten-zijn-en-zelf-signalen-afgeeft-om-andere-hardware-aan-testuren.LED’SDe-LED’s-in-het-circuit-fungeren-als-controlelampjes.-Wat-de-lampjes-precies-aangeven,-is-tevinden-in-het-softwaregedeelte-en-in-de-handleiding.DRUKKNOP---De-drukknop-is-in-het-circuit-opgenomen-om-de-meting-te-kunnen-activeren-en-te-resetten.SPOELDe-spoel-is-bedoeld-om-het-balletje-“vast-te-houden”-tot-het-moment-waarop-de-drukknop-wordtingedrukt-en-de-stroom-wordt-onderbroken.-De-spoel-werkt-met-behulp-van-het-principe-vanmagnetische-inductie.-Door-er-een-elektrische-stroom-doorheen-te-laten-stromen-ontstaat-eenmagnetisch-veld-dat-het-stalen-kogeltje-vasthoudt.-De-spoel-heeft-een-koperdraad-met-eendoornede-van-0,18-mm-en-een-weerstand-van-120,7Ω.Van-de-spoel-waren-de-volgende-gegevens-bekend:X X X
Diameter-inwendig:-12-mmDiameter-uitwendig:-30-mmHoogte:-15-mm-
------------------------------------------------------------1-http://www.arduino.cc/2-nl.wikipedia.org/wiki/Koperdraad-
7-
Profielwerkstuk-–-Open-source,-open-data-&-Hoe-laat-komt-mijn-tram?Sven-Boor-&-Arjen-Kremers-–-Gymnasium-NovumX Doorsnede-koperdraad:-0,18-mmX NietXmetallische-kernX Geen-redundant-magnetismeDe-totale-diameter-is-te-berekenen-door-de-uitwendige-diameter-minus-de-inwendige-diameterte-nemen.!"#$%&%'! = !!"#$%&'"(! − !!"#$"%!&! = !30!!!! − !12!!!! = !18!!!! Het-oppervlakte-van-de-doorsnede-van-de-spoel-is-als-volgt-te-berekenen.!""#$%&'&!!"#$%! = !!"#$%&%'!×!ℎ!!!"#! = !18!!!!×!15!!!! = !270!!! ! ! = !2,7!!" ! ! Op-Wikipedia2-is-op-de-pagina-over-koperdraad-het-aantal-windingen-te-vinden-bij-een-gegevendoorsnede-van-de-koperdraad.-Een-koperdraad-met-een-diameter-van-0,18-mm-geeft-2270windingen-per-vierkante-centimeter.-Vermenigvuldig-dat-met-het-aantal-vierkante-centimeterdoorsnede-die-wij-hadden-om-het-aantal-windingen-te-krijgen.-Dit-getal-moet-nog-gedeeldworden-door-twee-omdat-een-winding-zowel-heen-als-terug-gaat,-hij-loopt-immers-rond-om-despoel.!! = !2,7! ÷ !2!×!2270! = !3064,5!!"#$"#%Hieronder-is-in-beeld-gebracht-hoe-deze-berekening-tot-stand-is-gekomen.-
------------------------------------------------------------2-nl.wikipedia.org/wiki/Koperdraad-
8-
Profielwerkstuk-–-Open-source,-open-data-&-Hoe-laat-komt-mijn-tram?Sven-Boor-&-Arjen-Kremers-–-Gymnasium-NovumDe-lengte-van-één-winding-is-ongeveer-de-omtrek-van-de-spoel.-De-lengte-van-de-helekoperdraad-moet-dan-het-aantal-windingen-maal-de-lengte-van-één-winding-zijn.-Als-straalwordt-het-gemiddelde-genomen-van-de-binnenste-straal,-6mm,-en-de-buitenste-straal,-15mm.(15!!!! + !6!!!) ! ÷ !2! = !10,5!!!! !!"#$"#% = !!!×!2!×!!! = !!!×!2!×!10,5!!!! = !65,973!!!! = !0,065973!!! !!"##! = ! !!"#$"#% !×!!! = !0,065973!!!×!3064,5! = !202,18!!! = !2,0218!ℎ!! In-de-tabel-op-Wikipedia-is-ook-af-te-lezen-hoe-groot-de-weerstand-is-in-een-koperdraad-bij-eengegeven-draaddikte-per-hectometer.-Bij-een-draaddikte-van-0,18-mm-is-dit-69-Ω/hm.Vermenigvuldig-dit-met-de-afstand-in-hectometer-om-de-weerstand-in-Ohm-te-krijgen.!! = !2,0218!ℎ!!×!69!!/ℎ!! = !!139,5042!!! Afgerond-op-significante-cijfers-geeft-dit-een-weerstand-van-140-Ω.-
-
9-
Profielwerkstuk-–-Open-source,-open-data-&-Hoe-laat-komt-mijn-tram?Sven-Boor-&-Arjen-Kremers-–-Gymnasium-NovumSCHAKELAARDe-schakelaar-is-in-het-circuit-opgenomen-om-het-stalen-kogeltje-te-detecteren.-De-schakelaaronderbreekt-de-stroom-als-hij-open-staat,-wat-waargenomen-kan-worden-door-de-Arduino.EXTERNE-SPANNINGSBRONIn-het-circuit-is-een-externe-spanningsbron-opgenomen-om-de-spoel-van-een-spanning-van-30volt-te-kunnen-voorzien-die-nodig-is-om-de-spoel-goed-te-laten-functioneren.FETDe-Arduino-kan-de-hoge-spanning-die-nodig-is-voor-de-spoel-niet-leveren,-dus-moet-er-eenexterne-spanningsbron-worden-aangesloten.-Deze-moet-op-een-apart-circuit-wordenaangesloten,-zodat-de-hoge-spanning-ook-niet-over-de-Arduino-komt-te-staan,-dus-om-dezespanning-te-laten-lopen-of-te-onderbreken-met-de-Arduino-is-een-FET-nodig.DIODENa-afschakeling-van-de-stroom-door-de-spoel-blijft-er-een-stroom-lopen-door-de-spoel-totdat-hetmagnetisch-veld-van-de-spoel-wordt-afgebroken.-Dit-komt-doordat-de-magneet-eeninductiespanning-opwekt.-Deze-spanning-kan-oplopen-tot-duizenden-Volt.-De-energie-kan-danalleen-weg-door-middel-van-een-vonkontlading,-die-waarschijnlijk-in-de-FET-plaatsvinden.-Dezekan-daardoor-kapot-gaan.-Dit-is-te-voorkomen-door-een-diode-tegengesteld-parallel-aan-de-spoelin-te-bouwen.-Op-het-moment-dat-de-stroom-vanuit-de-spanningsbron-door-de-spoel-loopt-gaater-geen-stroom-door-de-diode,-maar-op-het-moment-dat-de-stroom-wordt-onderbroken-en-despoel-een-spanning-gaat-genereren,-kan-deze-spanning-teruggevoerd-worden-via-de-diode.EXTERNE-TIMERDe-timer-is-in-het-circuit-opgenomen-voor-de-tijdwaarneming.-De-Arduino-bleek-ook-prima-instaat-om-tijdwaarneming-te-doen.-Vooral-van-korte-duur,-zoals-in-dit-geval,-want-toen-getestwerd-over-een-tijd-van-tientallen-seconden-bleek-er-een-redeljik-grote-afwijking-te-zijn.-Voordemonstraties-in-de-klas-is-de-grote-externe-timer-geschikter,-omdat-deze-direct-dewaargenomen-tijd-laat-zien-en-er-geen-computer-voor-nodig-is-die-de-seriële-output-van-deArduino-ontvangt.-
-
10-
Profielwerkstuk-–-Open-source,-open-data-&-Hoe-laat-komt-mijn-tram?Sven-Boor-&-Arjen-Kremers-–-Gymnasium-Novum-
SCHAKELSCHEMAOnderstaande-afbeelding-geeft-het-schakelcircuit-weer.-
-
11-
Profielwerkstuk-–-Open-source,-open-data-&-Hoe-laat-komt-mijn-tram?Sven-Boor-&-Arjen-Kremers-–-Gymnasium-Novum-
-
PROBLEMENTijdens-het-ontwikkelen-zijn-we-ook-tegen-een-aantal-problemen-aangelopen.-Bijvoorbeeld-datwe-de-externe-timer-eerst-op-pin-1-hadden-aangesloten,-maar-door-de-seriële-interface-teinitialiseren,-die-ook-zijn-signaal-naar-pin-1-stuurt,-is-deze-poort-niet-meer-te-gebruiken.-Hij-geeftdan-namelijk-elke-1/9600e-van-een-seconde-een-puls-bij-een-baudrate-van-9600.-Als-de-seriëleinterface-niet-geïnitialiseerd-wordt-is-pin-1-wel-gewoon-te-gebruiken-voor-een-puls-“aan”-en“uit”.Een-ander-probleem-waar-we-tegen-aan-liepen-waren-de-draadjes-om-de-verschillendeonderdelen-van-ons-circuit-met-elkaar-te-verbinden.-Deze-draadjes-zijn-erg-kwetsbaar-en-dooreen-defect-draadje-in-het-circuit-wordt-de-hele-opstelling-onbruikbaar.-Een-probleem-als-dit-ismoeilijk-te-vinden,-omdat-je-niet-snel-bedenkt-dat-dit-het-probleem-kan-zijn-en-er-een-grotehoeveelheid-aan-draadjes-is-gebruikt.-
12-
Profielwerkstuk-–-Open-source,-open-data-&-Hoe-laat-komt-mijn-tram?Sven-Boor-&-Arjen-Kremers-–-Gymnasium-Novum-
SOFTWAREPROGRAMMAOm-de-Arduino-naar-eigen-inzicht-te-laten-reageren-op-signalen-moet-de-controllergeprogrammeerd-worden.-Een-ArduinoXprogramma-bestaat-uit-twee-basisonderdelen,-tweefuncties.-Eén-wordt-aangeroepen-bij-het-opstarten-van-het-programma.-Dit-is-de-setup-functie.De-andere-functie-is-de-loop-functie.-Deze-functie-wordt-na-de-initialisatie-van-het-programmacontinu-aangeroepen.Aan-het-begin-van-het-programma-worden-de-benodigde-constanten-en-variabelen-gedeclareerddie-nodig-zijn-in-de-rest-van-het-programma.-De-poorten-die-gebruikt-gaan-worden-zijn-allemaalgedeclareerd-in-de-preprocessor.-Dit-zorgt-ervoor-dat-voordat-de-code-wordt-gecompileerd,klaargemaakt-om-te-worden-gebruikt-door-de-Arduino,-alle-overeenkomsten-in-de-code-wordenvervangen-door-de-toegewezen-waarde.-Op-deze-manier-wordt-er-geen-geheugen-verbruikt-voordeze-waardes-op-de-Arduino,-maar-er-moet-goed-gelet-worden-op-mogelijke-fouten-die-gemaaktkunnen-worden.-Deze-worden-namelijk-niet-opgevangen-door-de-compiler.#define LED 13 //De LED die aangeeft of de opstelling klaar is voor een meting. #define FET 5 //De FET. Door deze aan of uit te zetten kan de spoel wel of niet onder spanning worden gezet. #define SWITCH 4 //De schakelaar waar het kogeltje op valt. #define BUTTON 2 //De drukknop die gebruikt wordt voor het resetten en het starten van de meting. #define ALERT 12 //Deze LED is het waarschuwingslampje dat aan gaat als de schakelaar open is. #define TIMER 8 //De externe timer die gebruikt wordt om de valtijd op te meten. unsigned long starttime; //De tijd in millisecondes op het moment dat de meting begint en het kogeltje wordt losgelaten. unsigned long lastResetTime; //De tijd in millisecondes dat de opstelling voor het laatst is gereset. boolean ballDropped = false; //De vlag die aangeeft of het kogeltje aan het vallen is. boolean isSet = false; //De vlag die aangeeft of de opstelling klaar is voor een meting. !
Onze-gehele-setup&functie-is-als-volgt-ingericht:-Eerst-wordt-hier-aangegeven-dat-de-seriële-poort-moet-worden-geactiveerd.-Met-deze-poortkunnen-gegevens-worden-verstuurd-via-de-USBXpoort-op-de-Arduino-naar-de-computer,-omweergegeven-te-worden-op-het-scherm.-Bij-de-initialisatie-van-de-seriële-poort-moet-ook-wordenaangegeven-op-hoeveel-baud-deze-draait.-Een-baud-is-de-eenheid-voor-het-aantal-bits-dat-perseconde-wordt-verstuurd.-Hier-is-gekozen-voor-een-baudrate-van-9600-baud.-Dit-is-namelijk-eenveelgebruikte-snelheid,-en-goed-voor-ons-gebruik.Daarna-worden-de-gebruikte-pins-geïnitialiseerd.-De-drukknop-en-de-schakelaar-waar-hetkogeltje-op-valt-worden-als-ingangen-voor-gegevens-gebruikt.-Zo-kunnen-de-waardes-afgelezenworden.-De-overige-attributen,-de-twee-LED’s,-de-FET-en-de-externe-tijdmeter,-hebben-eensignaal-nodig.-Om-te-schrijven-naar-deze-pinnen-worden-ze-als-uitgangen-geactiveerd.-
13-
Profielwerkstuk-–-Open-source,-open-data-&-Hoe-laat-komt-mijn-tram?Sven-Boor-&-Arjen-Kremers-–-Gymnasium-Novumvoid setup() { // Initialiseer de Serial met een snelheid van 9600 baud. Serial.begin(9600); Serial.flush(); // Initialiseer de output en input pins. pinMode(LED, OUTPUT); pinMode(FET, OUTPUT); pinMode(TIMER, OUTPUT); pinMode(BUTTON, INPUT); pinMode(SWITCH, INPUT); pinMode(ALERT, OUTPUT); digitalWrite(FET, LOW); //Stuur een laag signaal naar de FET zodat de spoel niet aan staat. } !
De-loop-functie-is-een-stuk-complexer-en-zal-in-delen-worden-uitgelegd.-Voor-het-eigen-gemak-ende-eigen-duidelijkheid-is-de-code-zelf-ook-al-ingedeeld-in-meerdere-methodes.De-eerste-selectie-die-in-de-loop-methode-wordt-uitgevoerd-bepaald-hoe-lang-de-opstelling-alklaar-is-voor-gebruikt.-Vanwege-veiligheidsredenen-en-het-gebruik-van-een-magnetische-spoelwordt-de-opstelling-na-tien-secondes-weer-uitgeschakeld,-zodat-hij-opnieuw-gereset-moetworden.-Na-deze-check-wordt-gekeken-of-er-op-de-drukknop-wordt-gedrukt,-en-of-de-schakelaarnaar-beneden-is.void loop() { if (millis() - lastResetTime > 10000) { unset(); } // Als de bal al losgelaten is hoeft de knop niet meer gecheckt te worden, maar dan moet de schakelaar gecheckt worden. checkButton(); checkSwitch(); }
-
-
-
14-
Profielwerkstuk-–-Open-source,-open-data-&-Hoe-laat-komt-mijn-tram?Sven-Boor-&-Arjen-Kremers-–-Gymnasium-NovumDe-checkButton&functie-ziet-er-als-volgt-uit:Als-blijkt-dat-het-kogeltje-al-aan-het-vallen-is,-wordt-de-functie-afgebroken.-Er-gebeurt-verderniets.-Anders-wordt-de-pin-die-aan-de-knop-bevestigd-is-gelezen,-met-de-methode-digitalRead,-enbepaald-of-het-signaal-hoog-is-en-de-knop-dus-is-ingedrukt.-Aangezien-de-knop-gebruikt-moetworden-voor-twee-doeleinden,-het-resetten-en-het-laten-vallen-van-de-kogel,-volgt-er-nog-eenselectie.-Als-de-opstelling-gereset-is,-en-dus-klaar-is-om-te-meten,-wordt-het-balletje-losgelaten-ende-meting-gestart.-Dit-gebeurt-in-de-dropBall-functie.-Is-de-opstelling-niet-klaar-voor-gebruik,-danbegint-de-procedure-om-het-systeem-klaar-te-maken-in-de-reset-functie.void checkButton() { /* Als de bal aan het vallen is wordt de functie vroegtijdig afgebroken. Als de knop niet is ingedrukt gebeurt er eveneens niets. */ if (ballDropped) { return; } if (digitalRead(BUTTON) == HIGH) { if (isSet) { dropBall(); } else { reset(); } } } !
dropBall&werkt-als-volgt:-Allereerst-wordt-naar-de-seriële-uitgang-een-string-verzonden-dat-demeting-is-gestart.-De-ballDropped-waarde-wordt-naar-true-gezet,-zodat-het-programma-weet-datde-meting-loopt.-De-starttijd-van-de-interne-timer-wordt-naar-de-huidige-tijd-gezet.-Naar-deTIMER-poort-wordt-een-hoog-signaal-geschreven-hetgeen-inhoudt-dat-de-externe-timer-start-mettellen.-Er-volgt-een-aanroep-naar-de-unsetXfunctie,-waardoor-de-spanning-op-de-magneetspoelwordt-weggenomen-en-het-kogeltje-valt.void dropBall() { Serial.println("Meting gestart"); ballDropped = true; starttime = millis(); //Start interne timer. digitalWrite(TIMER, HIGH); //Start externe timer. unset(); } !
-
-
15-
Profielwerkstuk-–-Open-source,-open-data-&-Hoe-laat-komt-mijn-tram?Sven-Boor-&-Arjen-Kremers-–-Gymnasium-NovumDe-checkSwitch-functie-is-als-volgt-ingedeeld:Het-eerste-dat-wordt-gecontroleerd-is-of-de-schakelaar-open-is-of-gesloten-door-het-signaal-waarte-nemen.-De-schakelaar-is-geopend-als-het-signaal-laag-is,-want-dan-is-de-stroomkringonderbroken,-en-hij-is-gesloten-als-het-signaal-hoog-is-en-de-stroomkring-gesloten.-Als-deschakelaar-gesloten-is-hoeft-alleen-de-waarschuwingsXLED-uitgeschakeld-te-worden.Is-hij-geopend,-dan-is-het-de-vraag-of-de-meting-bezig-is.-Als-de-meting-namelijk-gestart-is,-danbetekent-het-dat-het-kogeltje-door-de-schakelaar-heen-is-gevallen-en-dus-de-afstand-heeftafgelegd.-Nu-moet-de-tijd-gestopt-worden.-Dat-gebeurt-allereerst-door-de-externe-timer-testoppen-met-een-schrijfoperatie-naar-laag.-Daarna-wordt-de-verlopen-tijd-uitgerekend-door-destarttijd-van-de-meting-van-de-huidige-tijd-af-te-trekken.-Deze-berekende-waarde-wordt-naar-deseriële-uitgang-gestuurd.-De-gravitatieversnelling-wordt-vervolgens-ook-uitgerekend-met-deformule-g! = 2s!/!t ! en-geprint-naar-de-seriële-poort.-
-
Hierna-wordt-zowel-in-het-geval-van-een-meting-als-wanneer-er-geen-meting-heeftplaatsgevonden-de-opstelling-gereset-en-de-rode-waarschuwingsXLED-aangezet.-Deze-LED-geeftaan-dat-de-schakelaar-open-staat.void checkSwitch() { if (digitalRead(SWITCH) == LOW) { if (ballDropped) { digitalWrite(TIMER, LOW); // Stop de externe timer. unsigned int delta = millis() - starttime; // Meet de interne verlopen tijd. ballDropped = false; Serial.print("Millisecondes: "); // Zend de waarde van de interne timer naar de Serial. Serial.println(delta); float seconds = float(delta)/1000.0; //De millisecondes worden omgerekend naar hele secondes. Serial.print("Gravitatieversnelling: "); Serial.print(((2*0.335)/(seconds*seconds))); //Hier wordt de gravitatieversnelling uitgerekend met de formule. 0.335 is de afstand die het kogeltje heeft afgelegd. Serial.println(" m/s^2"); } digitalWrite(ALERT, HIGH); //De rode LED wordt aangezet. unset(); //De opstelling wordt gereset. } else { digitalWrite(ALERT, LOW); } } !
Nu-volgt-de-documentatie-van-de-laatste-twee-functies,-reset()-en-unset():De-opstelling-kan-nooit-gereset-worden-als-de-schakelaar-open-staat.-Dit-wordt-dus-allereerstgecontroleerd-en-er-wordt-een-bericht-verzonden-naar-de-serial-als-dit-het-geval-is.-Bij-dewerkelijke-reset-wordt-de-gele-LED-aangeschakeld,-om-aan-te-geven-dat-de-opstelling-klaar-isvoor-een-meting.-De-FET-wordt-ook-aangezet-zodat-de-er-een-spanning-door-de-magneetspoelloopt-om-het-balletje-vast-te-houden.-De-laatste-resettijd-wordt-naar-de-huidige-tijd-gezet-en-heter-wordt-aangegeven-dat-de-opstelling-gereset-is-met-de-isSet&waarde.-Er-volgt-een-delay-van-eenseconde,-wat-ervoor-zorgt-dat-de-meting-niet-onmiddelijk-begint.-De-drukknop-is-namelijkwaarschijnlijk-nog-steeds-ingedrukt.-
16-
Profielwerkstuk-–-Open-source,-open-data-&-Hoe-laat-komt-mijn-tram?Sven-Boor-&-Arjen-Kremers-–-Gymnasium-Novumvoid reset() { if (digitalRead(SWITCH) == LOW) { Serial.println("Sluit de schakelaar"); } else { Serial.println("Reset"); digitalWrite(LED, HIGH); digitalWrite(FET, HIGH); lastResetTime = millis(); isSet = true; } delay(1000); } !
In-unset-wordt-de-LED-die-aangeeft-dat-de-opstelling-klaar-is-voor-een-meting-uitgezet,-samenmet-de-FET.-Hierdoor-wordt-de-spanning-van-de-spoel-afgehaald.-Naar-de-isSet-waarde-wordtfalse-geschreven.void unset() { digitalWrite(LED, LOW); digitalWrite(FET, LOW); isSet = false; }
-
VERBETERINGENHet-ontwerpen-van-de-programmatuur-verliep-niet-volgens-de-beste-methode.-Een-aanpassingvan-de-schakeling-ging-steeds-vooraf-aan-een-kleine-toevoeging-aan-de-code.-Op-deze-manierwas-zowel-de-opstelling-als-het-programma-eenvoudig-te-testen.-Een-nadeel-van-deze-methodeis-dat-met-name-het-programma-niet-overzichtelijk-wordt-opgebouwd,-waardoor-enkeleslordigheden-over-het-hoofd-zijn-gezien.Hieronder-valt-de-manier-waarop-de-drukknop-en-schakelaar-worden-gecontroleerd.-Een-beterimplementatie-was-geweest-als-er-zowel-voor-de-knop-als-voor-de-schakelaar-een-boolean-wasgedeclareerd-die-bijhield-of-de-knop-ingedrukt-is,-en-dat-elke-iteratie-van-het-programma-wordtgecontroleerd-of-de-staat-van-de-knop-of-schakelaar-is-veranderd.-Als-dat-het-geval-is,-wordt-ereen-functie-aangeroepen.-In-deze-functie-wordt-dan-vervolgens-het-nodige-gedaan.-Dezemethode-is-iets-omslachtiger,-maar-veel-overzichtelijker,-en-een-belangrijk-probleem-wordtermee-vermeden,-namelijk-dat-sommige-functies-elke-iteratie-worden-aangeroepen-als-dat-nietnodig-is.Dit-is-ook-het-geval-bij-de-controle-hoe-lang-er-een-stroom-door-de-magneetspoel-loopt.-Nadat-detien-seconden-dat-de-opstelling-gereed-is-verstreken-zijn,-wordt-continu-de-unset-functieaangeroepen,-ook-al-is-dit-slechts-éénmaal-nodig.-
17-
Profielwerkstuk-–-Open-source,-open-data-&-Hoe-laat-komt-mijn-tram?Sven-Boor-&-Arjen-Kremers-–-Gymnasium-Novum-
HANDLEIDING1. Zorg-ervoor-dat-de-elektronica-en-de-draden-als-volgt-zijn-aangesloten:De-ground-van-de-timer,-de-Arduino-en-de-externe-spanningsbron-moeten-met-elkaarverbonden-zijn.-De-externe-spanningsbron-moet-aangesloten-worden-op-de-contactenwaar-“25-V=”-boven-staat-en-ingesteld-worden-op-25-volt-gelijkspanning.-Het-metalenklepje,-het-luik,-moet-worden-aangesloten-bij-“luik”-en-de-spoel-bij-“spoel”.De-bundel-kabeltjes-uit-het-kastje-gaat-richting-de-Arduino-en-moet-als-volgt-op-deArduino-worden-aangesloten:• WitXgeel:5-V• Zwart:- Pin-12• Blauw:-Pin-13• Oranje:-Pin-2• Rood:- Pin-4• Wit:- Pin-5De-rode-aansluiting-van-de-timermoet-via-een-apart-kabeltje-oppoort-8-van-de-Arduino-wordenaangesloten.2. Controleer-of-schakelaargesloten-is-en-of-de-timer-op-dit(⎍)-symbool-staat-en-druk-opde-startknop-van-de-timer-omdeze-gereed-te-maken-voor-eenmeting.3. Druk-eenmaal-op-de-knop-om-despoel-te-activeren.-Het-gelelampje-gaat-branden-als-tekendat-je-de-meting-kunt-starten.Let%op:%de-stroom-door-spoelwordt-na-10-seconden-automatisch-onderbroken-en-je-moet-hem-opnieuw-activeren.-Ditis-ter-veiligheid-zodat-de-spoel-niet-te-heet-wordt.Als-het-luik-open-staat-gaat-het-rode-lampje-branden-ter-teken-dat-de-meting-niet-gestartkan-worden.4. Plaats-het-kogeltje-in-de-onderkant-van-de-spoel.-Verhoog-de-spanning-als-deze-niet-blijfthangen-totdat-het-kogeltje-net-blijft-hangen.5. Druk-nogmaals-op-de-knop-om-de-proef-uit-tevoeren.-Het-kogeltje-valt-op-het-klepje-en-op-detimer-verschijnt-de-valtijd.-
18-
Profielwerkstuk-–-Open-source,-open-data-&-Hoe-laat-komt-mijn-tram?Sven-Boor-&-Arjen-Kremers-–-Gymnasium-Novum-
-
-
19-
Profielwerkstuk-–-Open-source,-open-data-&-Hoe-laat-komt-mijn-tram?Sven-Boor-&-Arjen-Kremers-–-Gymnasium-Novum-
TRAMDISPLAYHOE-LAAT-KOMT-MIJN-TRAM?-
-
-
20-
Profielwerkstuk-–-Open-source,-open-data-&-Hoe-laat-komt-mijn-tram?Sven-Boor-&-Arjen-Kremers-–-Gymnasium-Novum-
-
PROBLEEMSTELLINGNa-kennis-gemaakt-te-hebben-van-met-de-Arduino-de-open-source-computer,-zijn-we-op-zoekgegaan-naar-nieuwe-toepassingsmogelijkheden-van-open-source.-Op-YouTube3-kwamen-we-eeninteressant-filmpje-tegen-over-het-gebruik-van-Open-Data-in-het-Openbaar-vervoer.In-dit-filmpje-uit-Boston-komt-naar-voren-dat-door-het-vrijgeven-van-openbaar-vervoersdata,ontwikkelaars-in-korte-tijd-een-groot-aantal-nieuwe-toepassingen-gaat-maken.-Ook-in-Nederlandwordt-vanaf-2012-actuele-reisinformatie-van-het-openbaar-vervoer-open-vrijgegeven.Een-term-die-wordt-gebruikt-voor-data-die-vrij-beschikbaar-wordt-gemaakt-is-Open-Data.-Hetidee-van-Open-Data-is-dat-het-vrij-beschikbaar-is-voor-iedere-ontwikkelaar.-Ontwikkelaarskunnen-met-behulp-van-deze-data-zelf-applicaties-en-oplossingen-ontwikkelen.Op-tramlijn-15-toonden-de-tramdisplays-al-enkele-jaren-geen-actuele-informatie-op-een-aantalhaltes-in-Ypenburg-en-Rijswijk.-Ons-leek-het-leuk-om-te-onderzoeken-of-het-mogelijk-was-ommet-behulp-van-deze-vrijgegeven-openXdata-een-nieuwe-oplossing-te-bedenken-om-de-displaysaan-te-sturen.-
-
------------------------------------------------------------3-http://www.youtube.com/watch?v=URmKRTUXhxQ
21-
Profielwerkstuk-–-Open-source,-open-data-&-Hoe-laat-komt-mijn-tram?Sven-Boor-&-Arjen-Kremers-–-Gymnasium-NovumWAAROM-IS-ER-GEEN-REISINFORMATIE?Bij-HTM-hebben-we-nagevraagd-waarom-er-geen-actuele-reisinformatie-op-de-displays-van-lijn15-werd-getoond.-HTM-gafå-aan-dat-sinds-2010-gebruik-wordt-gemaakt-van-andereboordcomputers-in-de-trams.-Deze-boordcomputer-bepaalt-op-basis-van-o.a.-GPS-waar-hetvoertuig-is-op-de-route-en-hoeveel-de-tram-te-vroeg-of-te-laat-is.De-displays-langs-lijn-15-waren-een-integraal-onderdeel-van-het-oude-voertuigvolgsysteem.-Dezekonden-niet-meer-worden-aangestuurd-met-de-nieuwe-boordcomputers,-er-zijn--geen-openstandaarden-beschikbaar-om-de-displays-aan-te-sturen.-
-
-
22-
Profielwerkstuk-–-Open-source,-open-data-&-Hoe-laat-komt-mijn-tram?Sven-Boor-&-Arjen-Kremers-–-Gymnasium-NovumKNELPUNTEN-BIJ-REISINFORMATIEBij-nader-onderzoek-bleek-dat-het-probleem-van-HTM-in-meer-regio’s-voor-komt.-Iederevervoerder-maakt-gebruik-van-haar-eigen-reizigersinformatiesystemen.-Daar-waarverschillende-vervoerbedrijven-samen-komen,-is-het-nodig-de-gegevens-uit-meerdere-systemente-combineren-op-een-display.-Door-het-ontbreken-van-standaards-betekende-dit-dat-er-eengroot-aantal-(n-x-m)-interfaces-zouden-moeten-worden-gerealiseerd.Sinds-2002-wordt-het-openbaar-vervoer-in-de-meeste-regio’s-in-Nederland-aanbesteed,waardoor-er-regelmatig-andere-vervoerders-in-een-regio-komen-te-rijden.-In-Haaglanden-redenvroeger-allen-bussen-en-trams-van-HTM-en-Connexxion,-tegenwoordig-rijden-HTMBuzz,-Veoliaen-Arriva-in-Den-Haag.-De-reiziger-wil-onafhankelijk-van-het-vervoerbedrijf,-goedereisinformatie.-
-
-
23-
Profielwerkstuk-–-Open-source,-open-data-&-Hoe-laat-komt-mijn-tram?Sven-Boor-&-Arjen-Kremers-–-Gymnasium-NovumOPLOSSINGDe-oplossing-om-het-aantal-interfaces-te-beperken-is-het-standaardiseren-van-deinformatiestromen.-Door-vanuit-alle-vervoerders-de-gegevens-aan-te-leveren-aan-een-centraalpunt,-wordt-het-aantal-interfaces-teruggebracht-tot-1-x-n-interfaces-(n-=-het-aantal-vervoerdersdat-data-aanlevert).-
-
-
24-
Profielwerkstuk-–-Open-source,-open-data-&-Hoe-laat-komt-mijn-tram?Sven-Boor-&-Arjen-Kremers-–-Gymnasium-Novum-
REALISATIEDATAGOVI-(Grenzeloze-Openbaar-Vervoer-Informatie)-is-een-overheidsinitiatief-met-als-doel-eenlandelijke-database-te-creëren-voor-actuele-reisinformatie-afkomstig-van-verschillendevervoerders.-Het-GOVI-project-is-gestart-in-2007,-en-had-in-eerste-instantie-tot-doelgeïntegreerde-reisinformatie-te-leveren-voor-de-weergave-op-displays-bij-haltes-enknooppunten.Om-ook-op-haltes-waar-onvoldoende-reizigers-instappen-om-de-investering-in-displays-rendabelte-maken,-is-gezocht-naar-mogelijkheden-om-de-reisinformatie-ook-via-mobiel-internet-teontsluiten.-Vanaf-2010-is-geëxperimenteerd-met-een-eerste-BusXmobiel-project-in-NoordBrabant.-Vanaf-maart-2012-wordt-er-een-continue-datastroom-actuele-reisinformatie-geleverdvoor-alle-hates-in-het-GOVI-gebied-aan-OpenOV,-een-stichting-die-zich-tot-doel-stelt-om-openbaarvervoerdata-beschikbaar-te-stellen.GOVI-GEGEVENSSTROMENVERVOERDER-→-GOVI-
De-berichten-van-de-vervoerder-richting-GOVI-bestaan-uit-geplande-vertrektijden-(KV1),-deposities-van-bussen-en-trams-(KV6),-vrije-teksten-voor-op-displays-(KV15)-en-uitval-of-omleidingvan-bepaalde-ritten-(KV17).-KV-staat-voor-“koppelvlak”,-een-gegevensuitwisseling-oververschillende-organisaties.GOVI-→-DRIS-
Vanuit-GOVI-worden-de-geplande-vertrektijden-op-een-bepaalde-halte-in-de-vorm-van-KV7verstuurd-naar-het-DRIS-systeem.-Een-KV8-wordt-elke-keer-als-de-verwachte-vertrektijdverandert,-als-een-tram-aankomt-op-een-halte-en-als-een-tram-vertrekt-van-een-halte-verstuurd.In-KV8-worden-ook-vrije-teksten-en-uitgevallen-bussen-&-trams-doorgegeven.-
-
25-
Profielwerkstuk-–-Open-source,-open-data-&-Hoe-laat-komt-mijn-tram?Sven-Boor-&-Arjen-Kremers-–-Gymnasium-NovumKV78TURBOGOVI-was-oorspronkelijk-alleen-bestemd-voor-het-aansturen-van-DRIS’sen.--Met-de-opkomst-vanmobiel-internet-en-apps-kwam-er-ook-vraag-naar-informatie-op-alle-haltes-in-Nederland.-KV7/8was-oorspronkelijk-bedoeld-om-gebruikt-te-worden-voor-5000-haltes-en-niet-voldoende-ominformatie-te-verstrekken-over-alle-50.000-haltes-in-Nederland.-Daarom-is-er-een-efficiëntere-ensnellere-versie-van-KV7/8-ontwikkelt,-namelijk-KV78Turbo.-De-grootte-van-de-berichten-is-opdeze-nieuwe-manier-veel-kleiner-omdat-er-in-plaats-van-XML-gebruik-wordt-gemaakt-van-CTX,een-bestandsformaat-waarin-de-gegevens-gescheiden-zijn-door-een-sluisteken-(|).De-KV78Turbo-berichtenstroom-wordt-doorgestuurd-naar-OpenOV,-een-organisatie-die-zichinzet-om-alle-data-van-het-openbaar-vervoer-in-Nederland-beschikbaar-te-stellen-als-open-data.OpenOV-distribueert-deze-gegevensstroom-vervolgens-weer-naar-alle-ontwikkelaars-die-eenapplicatie-met-deze-data-willen-ontwikkelen.-Voorbeelden-van-applicaties-die-met-behulp-vandeze-data-zijn-ontwikkeld-zijn-OVInfo-voor-Android-en-Tranzzit-en-Openbaar-Vervoer-voor-iOS.-
26-
Profielwerkstuk-–-Open-source,-open-data-&-Hoe-laat-komt-mijn-tram?Sven-Boor-&-Arjen-Kremers-–-Gymnasium-NovumSTAPPENPLANWat-betekent-dit-voor-ons-project?-De-beschikbaarheid-van-de-KV78turbo-stroom-in-combinatiemet-opensource-hardware-en-software-vormden-de-basis-om-te-onderzoeken-hoe-we-actuelereisinformatie-op-de-displays-van-tramlijn-15-kunnen-krijgen.-Tijdens-de-uitvoering-hebben-wede-volgende-stappen-doorlopen:1. 2. 3. 4. 5. 6.
Hoe-komen-we-aan-het-display-t.b.v.-nader-onderzoek?Hoe-krijgen-we-een-tekst-op-het-display?Hoe-krijgen-we-reisinformatie-op-display?Hoe-laten-we-alles-samenwerken?BeheerUitrol-
-
-
27-
Profielwerkstuk-–-Open-source,-open-data-&-Hoe-laat-komt-mijn-tram?Sven-Boor-&-Arjen-Kremers-–-Gymnasium-NovumHOE-KOMEN-WE-AAN-HET-DISPLAY?De-eerste-uitdaging-was-om-de-beschikking-over-een-display-te-krijgen-zodat-we-ermee-kondengaan-testen.-We-zochten-begin-augustus-2012-contact-met-het-Stadsgewest-Haaglanden-dieverantwoordelijk-is-voor-alle-busX-en-tramhaltes-in-de-regio-Haaglanden.-Haaglanden-gaf-aan-dater-geen-reserve-display-was-om-mee-te-testen.-Stadsgewest-Haaglanden-verwees-ons-door-naarJC-Decaux,-de-exploitant-van-de-abri’s.--JC-Decaux-verwees-ons-weer-door-naar-de-HTM.-Ditkastje-naar-de-muur-gestuur,-leerde-ons-dat-het-beheer-van-de-displays-in-ieder-geval-nieteenduidig-was-geregeld.-Na-flink-heen-en-weer-mailen-bleek-JC-Decaux-bereid-om-ons-te-helpen.Een-monteur-heeft-ons-geholpen-met-het-demonteren-van-een-display-uit-de-abri-op-26september-2012.--Dit-proces-heeft-uiteindelijk-bijna-twee-maanden-geduurd.-
Op-deze-manier-zat-het-display-bevestigd-in-de-kast.-
-
-
28-
Profielwerkstuk-–-Open-source,-open-data-&-Hoe-laat-komt-mijn-tram?Sven-Boor-&-Arjen-Kremers-–-Gymnasium-NovumLEDXDISPLAYDe-volgende-onderzoeksvraag-was-hoe-we-zelf-teksten-op-het-display-konden-weergeven.-Heteerste-doel-was-om-dit-te-bereiken-via-de-computer.-De-gegevens-van-de-oude-microcontrollerwerden-via-een-RSX232-verbinding-naar-het-display-gestuurd.-Moderne-computers-hebbenalleen-een-USB-uitgang,-daarom-zijn-we-op-zoek-gegaan-naar-een-converter-van-USB-naar-RSX 232.-Om-het-LEDXdisplay-aan-te-sturen-hadden-wij-de-documentatie-van-de-LEDXcontroller-die-wekonden-gebruiken.-Hierin-stond-bijvoorbeeld-de-baudrate,-maar-ook-de-specifieke-commando’sdie-naar-de-LED’s-worden-opgestuurd-om-tekst-te-laten-verschijnen.-Deze-documentatie-bleekechter-niet-de-juiste-te-zijn,-in-ieder-geval-kregen-wij-het-display-er-niet-mee-aan-de-praat.-Ookde-aangegeven-baudrate-bleek-incorrect.Omdat-we-hadden-waargenomen-dat-het-LEDXdisplay-na-één-minuut-uitgaat-als-er-geen-signaalnaartoe-wordt-verzonden-en-dat-de-weergegeven-tijd-elke-minuut-werd-ververst,-concludeerdenwij-dat-de-oude-controller-ten-minste-1x-per-minuut-een-signaal-moet-sturen.-Door-hetcommando-dat-de-controller-verstuurt-op-te-vangen-op-de-computer,-konden-we-dit-bevestigen.We-ontvingen-een-onleesbaar-signaal,-maar-door-de-baudrate-aan-te-passen-lukte-het-onsuiteindelijk-het-signaal-te-onderscheppen-en-deze-te-gebruiken-om-onze-eigen-teksten-op-hetdisplay-te-laten-verschijnen.-Hierdoor-konden-wij-bepalen-welke-instructies-nodig-waren-om-hetdisplay-bepaalde-opdrachten-te-laten-uitvoeren.-Bovendien-hadden-we-zo-ook-de-baudratewaarop-het-LEDXdisplay-de-signalen-verwerkt-uitgevonden.-Deze-manier-van-onderzoekenwordt-ook-wel-reverse&engineering-genoemd.PYTHONPython-is-een-open-source-programmeeromgeving-die-bedoeld-is-om-programmereneenvoudiger-te-maken-voor-zowel-mensen-met-ervaring-als-mensen-die-net-beginnen-metprogrammeren.-Python-wordt-geleverd-met-een-zeer-grote-hoeveelheid-aan-zogenaamdelibraries,-bibliotheken-met-voorgebouwde-programma’s-die-te-gebruiken-zijn-in-eigenprogramma’s,-zodat-niet-steeds-het-wiel-opnieuw-hoeft-te-worden-uitgevonden.-Opdrachten-diein-andere-programmeertalen-meerdere-regels-aan-code-nodig-hebben,-zijn-in-Python-met-éénfunctie-te-bereiken.-Dit-is-het-geval-bij-bijvoorbeeld-het-lezen-van-bestanden,-wat-ingeavanceerdere-talen-geen-eenvoudige-taak-is,-wordt-in-Python-zeer-eenvoudig-gemaakt.-Omdatwij-de-code-op-de-server-en-de-microcontroller-eenvoudig-wilden-houden-en-beiden-bereidwaren-een-nieuwe-programmeertaal-te-leren,-leek-het-ons-een-goed-idee-om-van-Python-gebruikte-maken.SERVERVoor-ons-systeem-gebruiken-we-ook-een-KV78turbo-gegevensstroom,-die-vanuit-de-servers-vanOpenOV-naar-onze-eigen-server-wordt-gestuurd.-Op-dit-moment-gebruiken-we-alleen-nogKV8passtimes,-de-gegevensstroom-met-de-actuele-vertrektijden-van-de-tram.-Op-de-serverwordt-de-gegevensstroom-gefilterd-op-timingpointcode-(een-uniek-nummer-per-halte)-endoorgestuurd-naar-de-bijbehorende-haltecontroller.-De-halte-die-de-gegevens-ontvangt-slaat-zeop-en-verwerkt-ze-in-de-juiste-volgorde-tot-een-tekst-voor-het-LEDXdisplay.-Het-display-maakt-detekst-vervolgens-leesbaar.-Zie-ook-onderstaande-schets.-
29-
Profielwerkstuk-–-Open-source,-open-data-&-Hoe-laat-komt-mijn-tram?Sven-Boor-&-Arjen-Kremers-–-Gymnasium-Novum-
Voor-de-verbinding-tussen-onze-server-en-die-van-OpenOV-gebruiken-wij-het-MQTT-protocol.-Ditis-een-PublishXSubscribe-protocol-(kortweg-PubSub).-Dat-houdt-in-dat-de-cliënt-zich-bij-de-serverregistreert-(subscribe)-op-één-of-meerdere-onderwerpen-en-de-server-per-onderwerp-berichtenpubliceert-(publish)-die-automatisch-naar-de-geregistreerde-cliënts-worden-toegezonden.-Ditprotocol-is-uitstekend-geschikt-voor-ons-project.-Het-beperkt-de-gegevensoverdracht,-de-cliënthoeft-immers-niet-continu-aan-de-server-te-vragen-of-er-nieuwe-berichten-zijn,-en-zorgt-ervoordat-wanneer-er-een-nieuw-bericht-is-deze-vrijwel-onmiddellijk-door-de-cliënt-ontvangen-enverwerkt-wordt-en-deze-dus-zo-actueel-mogelijke-gegevens-heeft.-Softwarematig-konden-we-hetPubSub-protocol-eenvoudig-implementeren-door-gebruik-te-maken-van-de-openXsource-libraryMosquitto,-die-ook-een-PythonXbinding-heeft.KEUZE-VOOR-MICROCONTROLLERVoor-de-microcontroller-die-de-data-moet-aansturen-naar-het-systeem-hadden-we-twee-eisen.-Demicrocontroller-moet-tegen-extreme-weersomstandigheden-kunnen-en-hij-moet-verbinding-methet-internet-kunnen-maken-via-3G.-Iets-anders-dat-meewoog-was-de-prijs.-We-hebben-lang-opinternet-gezocht-en-zijn-veel-oplossingen-tegengekomen,-zoals-volledig-geïntegreerdeoplossingen-maar-ook-modulaire-systemen.-Andere-opties-die-we-overwogen-hebben-is-eengoedkope-android-telefoon-en-een-industriële-computer-de-iModX9400-met-ingebouwde-gprsondersteuning.-Deze-opties-vielen-af-vanwege-de-hoge-prijs-en-het-gebrek-aan-flexibiliteit.Uiteindelijk-hebben-we-gekozen-voor-de-Raspberry-Pi,-een-microcomputer-die-voor-eenminimale-prijs-(€35)-wordt-geproduceerd,-maar-wel-zeer-geavanceerde-specificaties-heeft.Hierdoor-is-het-mogelijk-om-een-standaard-linuxXdistro-te-gebruiken.-Dit-heeft-als-voordeel-datheel-veel-hardware-zonder-het-installeren-van-drivers-functioneert.-De-Raspberry-Pi-zelf-heeftgeen-3G-modem-en-RSX232-aansluiting,-maar-heeft-wel-twee-USB-aansluitingen.-Op-één-van-dieaansluitingen-is-een-HUAWEI-160G-3g-stick-aangesloten-voor-de-verbinding-met-internet.-Op-deandere-is-een-USB-naar-RSX232Xconverter-aangesloten-zodat-de-controller-gegevens-kan-
30-
Profielwerkstuk-–-Open-source,-open-data-&-Hoe-laat-komt-mijn-tram?Sven-Boor-&-Arjen-Kremers-–-Gymnasium-Novumverzenden-naar-het-LEDXdisplay.-Uiteindelijk-kost-deze-oplossing-qua-hardware-ongeveer-100euro.PI-ALS-MICROCONTROLLERDe-nieuwe-taak-was-nu-om-de-Raspberry-Pi-de-taak-van-de-oude-microcontroller-over-te-latennemen.-Hiertoe-diende-deze-geprogrammeerd-te-worden.De-software-op-de-microcontroller-bestaat-uit-twee-los-functionerende-onderdelen,-die-via-eenlokale-database-met-elkaar-communiceren.-Het-ene-gedeelte-registreert-zich-bij-de-server-om-deberichten-met-vertrektijden-te-ontvangen-en-slaat-deze-op-in-de-database.-Het-andere-gedeelteleest-deze-database-en-verwerkt-de-gegevens-vervolgens-tot-een-tekst-op-het-display-met-detrams-in-de-juiste-volgorde-op-vertrektijd.-Ook-op-de-Raspberry-Pi-konden-wij-gebruik-makenvan-Python-als-programmeertaal,-wat-wij-uiteraard-hebben-gedaan,-zodat-de-server-en-decontroller-softwarematig-hetzelfde-werken-en-wij-dezelfde-libraries-en-stukjes-code-kondengebruiken.De-verbinding-tussen-de-server-en-de-haltecontroller-verloopt-op-dezelfde-manier-als-tussenonze-server-en-die-van-OpenOV.-De-cliënt-registreert-zich-op-een-bepaald-onderwerp-bij-deserver,-wanneer-de-server-een-bericht-ontvangt-van-OpenOV-publiceert-hij-deze-op-hetonderwerp-met-als-naam-de-timingpointcode-van-de-halte.-De-halte-met-die-timingpointcode,-diedus-op-dat-onderwerp-is-geregistreerd,-ontvangt-dan-dit-bericht.-
-
31-
Profielwerkstuk-–-Open-source,-open-data-&-Hoe-laat-komt-mijn-tram?Sven-Boor-&-Arjen-Kremers-–-Gymnasium-NovumMIJKSENAARXSTANDAARDOm-het-display-gebruiksvriendelijk-en-duidelijk-te-maken-voor-reizigers,-hebben-we-gebruikgemaakt-van-de-Mijksenaar4Xstandaard-voor-displays-voor-openbaar-vervoer.-Deze-standaard-isontwikkeld-door-het-(information-design)-consultancybureau-Mijksenaar.-Dit-bedrijf-richt-zichop-het-ontwerpen-van-gebruiksvriendelijke-en-efficiënte-bewegwijzering-en-informatie-en-isover-de-hele-wereld-bekend,-vooral-van-de-bewegwijzeringssystemen-op-Luchthavens.-Het-leekons-verstandig-ons-aan-de-voorschriften-te-houden-die-zijn-ontwikkeld-door-Mijksenaar-watbetreft-displays-voor-het-openbaar-vervoer.Regels-waar-wij-dan-op-hebben-moeten-letten-zijn-bijvoorbeeld-de-volgorde-en-breedte-van-dekolommen-waarin-de-gegevens,-lijnnummer,-eindhalte-en-aantal-minuten-tot-vertrek,-zijningedeeld-en-dat-het-aantal-minuten-tot-vertrek-wordt-gevolgd-door-“-min“.-Aan-een-aantalvoorschriften,-zoals-het-laten-alterneren-van-speciale-berichten-en-de-variabele-letterbreedte,hebben-wij-ons-niet-gehouden-omdat-het-display-niet-beschikte-over-de-benodigde-functieshiervoor.-
BEHEEROm-het-mogelijk-te-maken-dat-ons-ontwerp-van-de-haltedisplay-in-productie-kan-wordengenomen,-is-er-een-manier-nodig-om-ervoor-te-zorgen-dat-de-displays-functioneel-blijven-werkenen-eventueel-softwarematig-verbeterd-kunnen-worden.-Om-het-project-af-te-sluiten-bogen-wijons-nog-over-dit-probleem.Aangezien-het-systeem-gebruik-maakt-van-een-draadloze-verbinding-en-in-het-openbaar-wordtgebruikt,-is-een-veilige-verbinding-nodig.-Het-enige-dat-nodig-is-om-de-haltecontroller-tebesturen,-is-toegang-tot-de-console.-Deze-toegang-is-te-verkrijgen-via-een-SSH-verbinding,-diestandaard-beschikbaar-is-op-onze-microcontroller,-de-Raspberry-Pi.-Dit-is-een-zeer-veiligeverbinding-die-gebruik-maakt-van-RSA-encryptie.Deze-verbinding-kan-niet-permanent-bestaan-en-moet-daarom-op-aanvraag-tot-stand-komen.Extra-veiligheid-is-nodig,-zodat-personen-van-buitenaf-geen-verbinding-kunnen-aanvragen-metde-controller.-Daarom-is-Het-IPXadres-van-onze-server-ingeprogrammeerd-in-de-haltecontrollerzodat-de-haltecontroller-alleen-met-onze-server-verbinding-kan-maken.-Aangezien-er-al-eenpublishXsubscribe-verbinding-tussen-de-controller-en-server-aanwezig-is,-leek-het-ons-handig-deaanvraag-voor-een-SSHXverbinding-ook-via-deze-weg-te-versturen.-De-server-verzendt-een-apartbericht-waarop-de-controller-met-het-ingeprogrammeerde-IPXadres-van-de-server-verbindingmaakt.-Op-deze-manier-zullen-personen-van-buitenaf-nooit-verbinding-kunnen-maken-met-decontroller,-omdat-deze-met-maar-één-server-de-verbinding-aangaat.Voor-een-zo-goed-mogelijk-beheer-van-de-haltecontrollers-moet-het-bekend-zijn-wanneer-eenbepaalde-controller-defect-is-en-controle-vereist,-zodat-dit-kan-worden-verholpen.-Een-voor-dehand-liggende,-maar-wel-zeer-bruikbare-methode-is-om-de-controller-om-het-half-uur-een-kleinbericht-naar-de-server-te-laten-sturen.-De-server-houdt-dan-van-elke-controller-bij-hoe-langgeleden-deze-een-bericht-heeft-gestuurd.-Als-dat-langer-is-dan-een-half-uur-is-er-waarschijnlijk------------------------------------------------------------4-http://nl.wikipedia.org/wiki/Paul_Mijksenaar-
32-
Profielwerkstuk-–-Open-source,-open-data-&-Hoe-laat-komt-mijn-tram?Sven-Boor-&-Arjen-Kremers-–-Gymnasium-Novumiets-mis-met-de-controller-en-moet-er-actie-worden-ondernomen.-De-server-zou-dan-een-berichtnaar-de-beheerder-kunnen-sturen.-Deze-methode-kan-worden-geïmplementeerd-als-toekomstigeoplossing-voordat-het-systeem-in-productie-wordt-genomen.KOSTENDit-project-is-begonnen-met-het-aan-de-praat-krijgen-van-1-van-de-7-displays-die-niet-werkten,één-display-hebben-we-nu-aan-de-praat.-Deze-oplossing-valt-te-kopiëren-naar-de-andere-haltes.Voor-elk-display-moet-de-onderstaande-hardware-aangeschaft-worden,-het-oude-LEDXdisplaykan-hergebruikt-worden:Onderdeel-
Geschatte%prijs-
Raspberry-Pi-
€40-
3G-Dongle-
€30-
USBXrs232-converter-
€15-
5V-USB-voeding-
€10-
SD-card-
€5-
Totaal:%-
€100-
Voor-het-ombouwen-van-alle-7-displays-is-dat-in-ongeveer-€700.-Voor-gotere-aantallen-geldenuiteraard-lagere-stuksprijzen.-Naast-de-eenmalige-kosten-van-het-ombouwen-van-het-displayzijn-er-ook-nog-maandelijkse-kosten.-Deze-kosten-bestaan-uit-de-server-waarop-het-programmadraait-om-de-berichten-te-distribueren-en-kosten-voor-de-mobiele-data.-De-kosten-voor-de-serverbedragen-ongeveer-€25-per-maand-(onafhankelijk-van-hoeveel-displays-er-op-wordenaangesloten).-De-kosten-voor-het-gebruik-van-mobiele-data-bedragen-per-display-ongeveer-€10per-maand.-De-beheerkosten-per-maand-zijn-dus-ongeveer-€100.-Wat-bij-dit-plaatje-nog-niet-ismeegerekend-zijn-de-arbeidskosten-(alle-uren-die-wij-er-al-in-gestopt-hebben).-
-
33-
Profielwerkstuk-–-Open-source,-open-data-&-Hoe-laat-komt-mijn-tram?Sven-Boor-&-Arjen-Kremers-–-Gymnasium-Novum-
PROGRAMMATUURDit-gedeelte-hebben-we-opgenomen-voor-de-technisch-geïnteresseerde-lezer-om-enig-inzicht-tekrijgen-hoe-de-programma’s-werken.SERVERIn-deze-paragraaf-worden-de-twee-programma’s-beschreven-die-op-onze-distributieserverdraaien.KV8.PYOnderstaande-programma-is-het-programma-dat-de-data-die-ontvangen-wordt-via-ZMQ-(600berichten-per-seconde-op-het-drukste-moment)-filtert-en-doorstuurt-via-het-MQTT-protocol-naarde-juiste-halte.import sys # Toegang tot systeem functies import os import zmq # De ZeroMQ library om gegevens van de OpenOV-server te ontvangen. import datetime # De time functie uit de time library om de huidige tijd in secondes op te vragen. from gzip import GzipFile # Nodig om bestanden met Gzip compressie te lezen. from cStringIO import StringIO # Hulpmiddel voor Strings tpcs = ['32005935', '32005937', '32005939', '32005215', '32005216', '32005108', '32005107'] # De TimePointCodes van de haltes waar wij van willen ontvangen in een lijst (array). context = zmq.Context() # Een ZeroMQ "context" wordt aangevraagd. kv8 = context.socket(zmq.SUB) # Maakt een socket aan voor de verbinding met OpenOV. # Een verbinding met de OpenOV-server wordt tot stand gebracht. kv8.connect("tcp://83.98.158.170:7817") kv8.setsockopt(zmq.SUBSCRIBE, "/GOVI/KV8") poller = zmq.Poller() poller.register(kv8, zmq.POLLIN) print("Collect data from server") counter = 0
-
-
34-
Profielwerkstuk-–-Open-source,-open-data-&-Hoe-laat-komt-mijn-tram?Sven-Boor-&-Arjen-Kremers-–-Gymnasium-Novum# Deze functie verwerkt het ontvangen bestand, dat de vorm heeft van een String. def processPackage(content): global tpcs # De verwijzing naar variabele tpcs is een globale verwijzing. for line in content.split('\r\n')[:-1]: if line[0] == '\\': if line[1] == 'G': label, name, subscription, path, endian, enc, res1, timestamp, _ = line[2:].split('|') if label != 'KV8turbo_passtimes': print content elif line[1] == 'T': types = line[2:].split('|')[1] elif line[1] == 'L': keys = line[2:].split('|') else: # De gegevens worden ingedeeld in een map, in de volgorde die de \L-lijn heeft aangegeven. row = {} values = line.split('|') for k,v in map(None, keys, values): if v == '\\0': row[k] = None else: row[k] = v if row['TimingPointCode'] in tpcs: # Alleen als de TimingPointCode van de halte in de tpcs array zit, zijn de gegevens voor ons interessant en worden ze verwerkt in de database. now = datetime.datetime.now() print str(now) try: f = open("tmp.gz", "w+") gz = GzipFile(fileobj=f, mode="w") gz.write(line) gz.close() f.close() #os.system("mosquitto_pub -m '" + sio.getvalue() + "' -t '" + row['TimingPointCode'] + "/KV8passtimes'") os.system("mosquitto_pub -f 'tmp.gz' -t '" + row['TimingPointCode'] + "/KV8passtimes'") print "Send!" except Exception as e: print e raise
# Zolang het programma draait wordt opgevraagd of er een bericht is ontvangen. Is dit het geval, dan wordt het bericht geunzipt en wordt de 'processPackage' functie aangeroepen. while True: socks = dict(poller.poll()) if socks.get(kv8) == zmq.POLLIN: multipart = kv8.recv_multipart() content = GzipFile('','r',0,StringIO(''.join(multipart[1:]))).read() processPackage(content)
subscriber.close() context.term()
CONNECTSSH.PY-
35-
Profielwerkstuk-–-Open-source,-open-data-&-Hoe-laat-komt-mijn-tram?Sven-Boor-&-Arjen-Kremers-–-Gymnasium-NovumDit-programma-zorgt-ervoor-dat-de-haltecontroller-(de-Raspberry-Pi)-op-afstand-met-een-veiligeverbinding-beheerd-kan-worden.-Het-is-slechts-een-klein-script-dat-om-user-input-vraagt-en-datomzet-in-LinuxXcommando-dat-de-SSHXverbinding-tot-stand-brengt.import os import time #timinpointcode van te beheren halte tpc = raw_input("Enter Tpc: ") #poort haltecontroller-->server port = raw_input("Enter port: ") #stuur bericht om verbinding te maken met server os.system('mosquitto_pub -t "' + tpc + '/con" -m "' + port + '"') #wacht totdat connectie tot stand komt print('Wait on SSH') time.sleep(10) #verbind met halte controller os.system('ssh pi@localhost -p ' + port)
-
-
36-
Profielwerkstuk-–-Open-source,-open-data-&-Hoe-laat-komt-mijn-tram?Sven-Boor-&-Arjen-Kremers-–-Gymnasium-NovumHALTECONTROLLER-(RASPBERRY-PI)In-deze-paragraaf-beschrijven-we-gedetailleerd-de-software-die-op-de-haltecontroller-draait.-
In-de-bovenstaande-systeemschets-van-de-haltecontroller,-de-Raspberry-Pi,-is-het-programmawat-er-voor-zorgt-dat-de-KV8passtimes,&de&verwachte-vertrektijden,-in-de-database-komengetkv8.py.-Het-programma-disp_cmd.py-ververst-elke-seconde-de-data-op-het-display-en-maaktdaarvoor-gebruik-van-display.py.-Beide-programma’s-maken-gebruik-van-disp_config.py-om-deTimePointCode-van-de-halte-waar-de-software-op-draait-te-weten-en-enige-andere-configuratie.Koppelvlak-7-is-nog-niet-geïmplementeerd-in-onze-software,-net-zoals-KV8generalmessage,-dealgemene-berichten.-
-
37-
Profielwerkstuk-–-Open-source,-open-data-&-Hoe-laat-komt-mijn-tram?Sven-Boor-&-Arjen-Kremers-–-Gymnasium-NovumGETKV8.PYDit-programma-zorgt-voor-een-internetverbinding-en-verwerkt-gepushte-berichten-vanaf-serverin-een-lokale-database.#importeer softwarebibliotheken import mosquitto import sqlite3 import os from gzip import GzipFile from cStringIO import StringIO import disp_config as confg #laad configuratie bestand print "Loading configuration file" confg.read() tpc = str(confg.tpc) #configureer database en mqtt pconnected = False connection = sqlite3.connect("/home/pi/data.db", timeout=3) client = mosquitto.Mosquitto(tpc) #toon “Connected” indien verbinding met server succesvol is def on_connect(rc): print "Connected" #wordt uitgevoerd als er een nieuw bericht binnen komt def on_message(msg): global tpc print "\nget" print "Topic: " + msg.topic print "Raw: " + msg.payload try: #maak string van bericht sio = StringIO(msg.payload) #ungzip bericht gz = GzipFile(fileobj=sio, mode="r") payload = gz.read() print "Uncompressed: " + payload except Exception as e: print "Not gzipped" payload = msg.payload #als server bericht stuurt om te beheren if msg.topic == tpc + "/con": os.system('ssh -nNT -R ' + str(payload) + ':localhost:22
[email protected] &') print "ok" #anders (dus in het geval kv8passtimes bericht) else: kv8 = payload keys = kv8.split('|')
-
38-
Profielwerkstuk-–-Open-source,-open-data-&-Hoe-laat-komt-mijn-tram?Sven-Boor-&-Arjen-Kremers-–-Gymnasium-Novumcursor = connection.cursor() #cursor.execute("SELECT * FROM departure WHERE journeynumber=(%s) and timingpointcode=(%s)", (row["JourneyNumber"], row["TimingPointCode"],)) cursor.execute('SELECT * from realization WHERE(journeynumber=(?))', (keys[3],)) valueInDB = cursor.fetchone() #als ritnummer nog niet in database zit if valueInDB == None: #voeg rit toe aan DB cursor.execute('INSERT INTO realization VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', (keys[0], keys[1], keys[2], keys[3], keys[4], keys[5], keys[6], keys[7], keys[8], keys[9], keys[10], keys[11], keys[12], keys[13], keys[14], keys[15], keys[16], keys[17], keys[18], keys[19], keys[20], keys[21], keys[22], keys[23], keys[24], keys[25], keys[26], keys[27], keys[28], keys[29], keys[30], keys[31], keys[32],)) #anders (als rit er dus al wel in zit) else: #update bestaande rit in DB cursor.execute("UPDATE realization SET expectedarrivaltime=(?), expecteddeparturetime=(?), lastupdatetimestamp=(?), tripstopstatus=(?) WHERE journeynumber=(?);", (keys[13], keys[14], keys[10], keys[15], keys[3],)) #als status van een bus in het systeem "PASSED" of "CANCELED is gooi bus van display cursor.execute("DELETE FROM realization WHERE tripstopstatus=(?) or tripstopstatus=(?);", ("PASSED", "CANCELED",)) expectedarray = cursor.fetchone() connection.commit() #voer uit zolang programma draait while True: #als er geen verbinding (meer) met server is if client.loop() != 0: #als er niet eerder een verbinding is geweest if not pconnected: #initialiseer 3G modem os.system("sudo /./sakis3g start SIM_PIN='0000' APN='internet'") pconnected = True print "Connected to internet" #anders else: #herinitialiseer 3G modem os.system("sudo /./sakis3g reconnect SIM_PIN='0000' APN='internet'") print "Reconnected to internet" #maak verbinding met server client.connect("94.124.88.194") #abonneer op topic van tpc van desbetreffende halte client.subscribe(tpc + "/+", 0) client.on_message = on_message client.on_connect = on_connect
-
-
39-
Profielwerkstuk-–-Open-source,-open-data-&-Hoe-laat-komt-mijn-tram?Sven-Boor-&-Arjen-Kremers-–-Gymnasium-NovumDISPLAY.PYNu-volgt-de-zelf-geschreven-PythonXklasse-als-hulpmiddel-voor-het-aansturen-van-het-LEDX display.-De-breedte-van-het-scherm,-het-aantal-karakters-dat-kan-worden-weergegeven,-is-in-eenconstante-opgeslagen.-De-createXfunctie-maakt-een-seriële-verbinding-met-een-baudrate-van9600-aan-met-het-LEDXdisplay-op-de-aangegeven-poort,-device.-De-destroyXfunctie-verbreektdeze-verbinding-weer.import sys import serial global ser DISPLAY_WIDTH = 32 def create(device): global ser ser = serial.Serial(device, 9600) def destroy(): global ser if ser: ser.close()
clear-maakt-het-scherm-leeg,-de-txt_*Xfuncties-laten-een-aangegeven-tekst-op-de-aangegevenregel-zien-op-de-manier-die-hoort-bij-de-functie.-Dat-kan-zijn-horizontaal-en-verticaal-scrollend,of-gewoon-stilstaand.-De-tekst,-het-lijnnnummer-en-eventueel-welk-effect-moet-worden-gebruiktworden-verwerkt-in-een-commando-dat-naar-het-via-de-seriële-verbinding-naar-de-LED’s-wordtgestuurd.-In-elke-functie-wordt-gecontroleerd-of-de-seriële-verbinding-ser-bestaat,-als-dat-niet-zois-gebeurt-er-niets.def clear(): txt_show("",0) txt_show("",1) txt_show("",2) def txt_show(text, line): global ser if ser == None: return cmd = "#0A>FF#00#00#0%s#%s#00#cc<" % (str(line), text) ser.write(cmd) def txt_scroll_hor(text, line): global ser if ser == None: return cmd = "#0A>FF#00#01#0%s#%s#00#cc<" % (str(line), text) ser.write(cmd) def txt_scroll_vert(text, line): global ser if ser == None: return cmd = "#0A>FF#00#02#0%s#%s#00#cc<" % (str(line), text) ser.write(cmd)
-
40-
Profielwerkstuk-–-Open-source,-open-data-&-Hoe-laat-komt-mijn-tram?Sven-Boor-&-Arjen-Kremers-–-Gymnasium-NovumDISP_CONFIG.PYDe-volgende-Python-klasse-hebben-we-ook-geschreven-als-hulpmiddel,-deze-dient-voor-het-lezenvan-de-halteXconfiguratie.-In-dit-bestand-staat-de-TimePointCode-van-de-halte-en-een-tabelwaarin-de-codes-van-eindhaltes-tegenover-de-namen-van-deze-eindhaltes-staan.-Ditconfiguratiebestand-moet-door-beide-Python-programma’s-op-de-controller-gelezen-worden-endaarom-is-een-aparte-klasse-nodig,-zodat-niet-in-beide-programma’s-dezelfde-code-opgenomenhoeft-te-worden.tpc = 0 nameMap = {} def read(): global tpc global nameMap try: f = open("/home/pi/disp.confg", "r") line = f.readline().strip() tpc = int(line) print("Line: " + line) line = f.readline() while line != None and len(line) > 0: s = line.split(" ", 2) i = int(s[0].strip()) j = int(s[1].strip()) name = s[2].strip() nameMap[MapKey(i,j)] = name line = f.readline() except IOError: print("Cannot read config file") raise except: print("Invalid config file") raise
In-deze-hulpklasse-zit-ook-een-functie-getName-opgenomen-die-door-de-andere-programma’saangeroepen-kan-worden-om-via-het-lijnnummer-en-de-lijnrichting-de-naam-van-de-eindhalte-teverkrijgen.def getName(num, dir): global nameMap key = MapKey(num, dir) try: return nameMap[key] except KeyError: pass return ""
De-aparte-klasse-MapKey-dient-als-sleutel-voor-de-tabel-die-aan-de-hand-van-de-het-lijnnummeren-de-lijnrichting-de-string-met-de-naam-van-de-eindhalte-opzoekt.-Deze-sleutel-bevat-hetlijnnummer-en-de-lijnrichting-en-creëert-in-de-__hash__Xfunctie-de-zogenaamde-hashcode-die-inde-tabel-gebruikt-wordt-voor-het-opzoeken-van-de-bijbehorende-naam-van-de-eindhalte.Hiervoor-is-ook-de-__eq__Xfunctie-nodig,-die-nagaat-of-twee-instanties-van-MapKey-aan-elkaargelijk-zijn.-
41-
Profielwerkstuk-–-Open-source,-open-data-&-Hoe-laat-komt-mijn-tram?Sven-Boor-&-Arjen-Kremers-–-Gymnasium-Novumclass MapKey: def __init__(self, num, dir): self.lineNum = num self.lineDir = dir def __eq__(self, obj): return self.lineNum == obj.lineNum and self.lineDir == obj.lineDir def __hash__(self): return self.lineDir + self.lineNum * 4
DISP_CMD.PYHet-laatste-programma-is-het-programma-dat-de-gegevens-van-de-vertrektijden-uit-de-databaseleest-en-ze-in-de-juiste-volgorde-laat-zien-op-het-LEDXscherm.-De-NAME_WIDTH_LIMIT&constantebewaart-de-maximale-lengte-van-de-naam-van-de-eindhalte-die-kan-worden-weergegeven.-Dezeis-gelijk-aan-het-maximale-aantal-karakters-dat-horizontaal-op-het-scherm-past-verminderd-met11.-Deze-11-bestaat-uit-drie-karakters-voor-het-lijnnummer,-spaties-voor-en-achter-de-naam-vande-eindhalte-en-6-karakters-voor-het-aangeven-van-het-aantal-minuten-tot-vertrek.De-EMPTY_NAME-constante-bevat-een-tekenreeks-van-spaties,-met-een-lengte-zo-groot-alsNAME_WIDTH_LIMIT.-Deze-tekenreeks-wordt-gebruikt-om-de-tekenreeks-van-de-naam-van-deeindhalte-op-te-vullen-met-spaties,-zodat-de-tijden-tot-vertrek-mooi-uitgelijnd-worden.import sys import display import disp_config as confg import sqlite3 import time from cStringIO import StringIO NAME_WIDTH_LIMIT = display.DISPLAY_WIDTH - 11 EMPTY_NAME = " " journeys = {} message = None msgAlternationTimer = 0 msgIndex = 0 journeyPassedTimer = 0
Eerst-worden-het-configuratiebestand-gelezen,-zoals-beschreven-onder-disp_config.py,-envervolgens-wordt-de-verbinding-met-het-display-tot-stand-gebracht,-zie-ook-display.py.-BeideUSBXuitgangen-worden-uitgeprobeerd.-Daarna-wordt-de-verbinding-met-de-database-gemaaktmet-behulp-van-de-sqlite3-library.-
42-
Profielwerkstuk-–-Open-source,-open-data-&-Hoe-laat-komt-mijn-tram?Sven-Boor-&-Arjen-Kremers-–-Gymnasium-Novum#Load config print "Loading configuration file" confg.read() #Init display print "Starting up display" try: display.create("/dev/ttyUSB0") except: display.create("/dev/ttyUSB1") #Init print con = cur =
database "Establishing connection with database" None None
try: con = sqlite3.connect("/home/pi/data.db", timeout=3) cur = con.cursor() print "Connected with database" except sqlite3.Error, e: print e sys.exit(1) #Done init
De-volgende-functie,-displayNormalMessage,-bouwt-van-het-lijnnummer,-de-naam-van-deeindhalte-en-het-aantal-minuten-een-tekenreeks,-die-naar-display.py-wordt-gestuurd-omvervolgens-op-het-LEDXdisplay-te-worden-laten-zien.-Er-wordt-gebruik-gemaakt-van-een-StringIOobject.-Een-virtueel-bestand-waar-naartoe-geschreven-kan-worden-en-vervolgens-in-een-normaletekenreeks-omgezet-kan-worden.-Dit-is-een-veel-efficiëntere-oplossing-dan-concatenatie-vantekenreeksen.def displayNormalMessage(ptline, stopname, min, line): strio = StringIO() if ptline < 10: strio.write(" ") elif ptline < 100: strio.write(" ") strio.write(str(ptline)) strio.write(" ") if len(stopname) > NAME_WIDTH_LIMIT: stopname = stopname[0:NAME_WIDTH_LIMIT] strio.write(stopname) strio.write(EMPTY_NAME[0:NAME_WIDTH_LIMIT - len(stopname)]) strio.write(" ") min = int(min) if min < 10: strio.write(" ") strio.write(str(min)) strio.write(" min") display.txt_show(strio.getvalue(), line) del strio
De-JourneyXklasse-is-de-klasse-die-alle-nodige-gegevens-die-bij-een-bepaald-reisnummer-horenbewaart.-Er-is-een-calcDeltaTimeXfunctie-opgenomen-om-met-de-huidige-tijd-het-aantal-minuten43-
Profielwerkstuk-–-Open-source,-open-data-&-Hoe-laat-komt-mijn-tram?Sven-Boor-&-Arjen-Kremers-–-Gymnasium-Novumtot-vertrek-te-berekenen.-De-displayXfunctie-roept-de-globale-displayNormalMessageXfunctie-aanmet-zijn-gegevens-als-argumenten.class Journey: def __init__(self, jour, line, dir, deptime, depdate): self.delta = 99 self.deltaFloat = 99 self.journeyNum = jour self.lineNum = line self.lineDir = dir self.depTime = deptime self.depDate = depdate def calcDeltaTime(self, currenttime): if int(self.depTime[:2]) >= 24: self.depTime = "0" + str(int(self.depTime[:2]) - 24) + self.depTime[2:] timeobj = time.strptime(self.depDate + " " + self.depTime, "%Y-%m-%d %H:%M:%S") dep = time.mktime(timeobj) + 86400 else: timeobj = time.strptime(self.depDate + " " + self.depTime, "%Y-%m-%d %H:%M:%S") dep = time.mktime(timeobj) prevdelta = self.deltaFloat self.deltaFloat = dep - currenttime if self.deltaFloat < -60: cur.execute("DELETE FROM realization WHERE JourneyNumber=(?);", (self.journeyNum,)) con.commit() del journeys[self.journeyNum] else: self.deltaFloat /= 60 if self.deltaFloat > prevdelta and self.deltaFloat < prevdelta + 1.0: self.deltaFloat = prevdelta self.delta = max(int(round(self.deltaFloat, 0)), 0) def display(self, index): displayNormalMessage(self.lineNum, confg.getName(self.lineNum, self.lineDir), self.delta, index)
De-readDatabaseXfunctie-leest-de-gegevens-uit-de-database.-Met-SQL-worden-de-benodigdegegevens-opgevraagd.-Dat-zijn-de-datum,-de-verwachte-vertrektijd,-het-lijnnummer,-delijnrichting-en-het-reisnummer.-Deze-gegevens-worden-in-volgorde-van-de-verwachte-vertrektijdin-een-lijst-gezet.-Er-wordt-een-map-bijgehouden-waarin-de-reisnummers-verwijzen-naar-deJourneyXobjecten.-De-reisnummers-zijn-elke-dag-uniek-per-tram-die-langs-rijdt.-Als-de-map-eenbepaald-reisnummer-nog-niet-bevat,-wordt-een-nieuw-JourneyXobject-gemaakt,-de-gegevens-uitde-database-worden-in-het-object-geschreven-en-het-object-wordt-toegevoegd.-Als-het-JourneyX object-al-wel-bestaat,-wordt-de-verwachte-vertrektijd-bijgewerkt.-Als-de-tram-van-datreisnummer-voorbij-is-wordt-het-object-weer-verwijderd-uit-de-map.-
44-
Profielwerkstuk-–-Open-source,-open-data-&-Hoe-laat-komt-mijn-tram?Sven-Boor-&-Arjen-Kremers-–-Gymnasium-Novumdef readDatabase(): global journeys global journeyPassedTimer #NEW activejourneys = [] cur.execute("select OperationDate, ExpectedDepartureTime, LinePlanningNumber, LineDirection, JourneyNumber from realization order by ExpectedDepartureTime") row = cur.fetchone() while row != None: jn = int(row[4]) activejourneys.append(jn) if jn in journeys: j = journeys[jn] j.depTime = row[1] else: linenum = int(row[2]) amount = 0 j = Journey(jn, int(row[2]), int(row[3]), row[1], row[0]) journeys[jn] = j row = cur.fetchone() for jn, j in journeys.items(): if not j.journeyNum in activejourneys: if j == journeys.values()[0]: journeyPassedTimer = 3 del journeys[j.journeyNum] display.txt_show("", 0) time.sleep(3) print "deleterow" else: j.calcDeltaTime(time.time()) del activejourneys
Om-de-gelezen-gegevens-te-laten-zien-op-het-display-is-de-displayJourneysXfunctie.-Dit-is-eenaparte-functie,-omdat-de-code-duidelijker-wordt-als-het-lezen-van-de-database-en-het-schrijvennaar-het-display-gescheiden-worden.-De-reizen,-Journeys,-worden-op-aantal-minuten-tot-vertrekgesorteerd-en-vervolgens-wordt-van-de-eerste-drie-instanties-de-displayXfunctie-aangeroepen,dat-ervoor-zorgt-dat-de-reisinformatie-op-het-display-komt-te-staan.De-setMessageXfunctie-en-de-msgAlternationTimerXvariabele-zijn-bedoeld-om-vrije-teksten-op-hetdisplay-te-laten-zien,-maar-dit-is-nog-niet-geïmplementeerd-in-koppelvlak-8-en-worden-daaromnog-niet-gebruikt.-
45-
Profielwerkstuk-–-Open-source,-open-data-&-Hoe-laat-komt-mijn-tram?Sven-Boor-&-Arjen-Kremers-–-Gymnasium-Novumdef displayJourneys(): global journeys global message global journeyPassedTimer counter = {} index = 0 if journeyPassedTimer != 0: display.txt_show("", 0) index += 1 max = 3 if message != None: max -= 1 for j in sorted(journeys.values(), key=lambda jo : jo.deltaFloat): amount = 0 if j.lineNum in counter: amount = counter[j.lineNum] if amount < 2: counter[j.lineNum] = amount + 1 j.display(index) index += 1 if index == max: break while index < 3: if index != 2 or message == None: display.txt_show("", index) index += 1 del counter def setMessage(msg): global message if msg == None: message = None return message = [] while len(msg) > 0: message.append(msg[0:display.DISPLAY_WIDTH]) msg = msg[display.DISPLAY_WIDTH:]
De-mainPloop-van-het-programma-wordt-gestart-zodra-alle-verbindingen-tot-stand-zijn-gebrachten-de-initialisatie-is-voltooid.-De-loop-wordt-gesynchroniseerd-zodat-precies-elke-seconde-dedatabase-wordt-gelezen-en-het-scherm-wordt-bijgewerkt.-Dit-gebeurt-met-de-sleepXfunctie-diehet-programma-een-bepaalde-tijd-pauzeert.-Als-er-een-fout-ontstaat-of-het-programma-wordtonderbroken-stopt-de-loop-en-worden-de-verbindingen-gesloten.-
46-
Profielwerkstuk-–-Open-source,-open-data-&-Hoe-laat-komt-mijn-tram?Sven-Boor-&-Arjen-Kremers-–-Gymnasium-Novumtry: while True: starttime = time.time() if journeyPassedTimer > 0: journeyPassedTimer -= 1 if msgAlternationTimer > 0: msgAlternationTimer -= 1 elif message != None: msgAlternationTimer = 3 msgIndex = (msgIndex + 1) % len(message) if message != None: display.txt_show(message[msgIndex], 2) readDatabase() displayJourneys() #timestr = time.asctime(time.localtime(starttime)) #display.txt_show(timestr, 2) starttime += 1 time.sleep(max(starttime - time.time(), 0)) except: print "\nStopping" finally: del journeys display.clear() display.destroy() if con: con.close()
-
-
47-
Profielwerkstuk-–-Open-source,-open-data-&-Hoe-laat-komt-mijn-tram?Sven-Boor-&-Arjen-Kremers-–-Gymnasium-Novum-
CONCLUSIEHet-was-voor-ons-een-bijzondere-ervaring-om-kennis-te-nemen-van-de-praktijk-van-open-sourceen-open-data.-De-samenwerking-met-een-community,-waarin-mensen-belangeloos-met-elkaarmeedenken-en-meehelpen,-maar-waar-ook-de-problemen-en-oplossingen-van-anderen-te-vindenzijn,-is-een-erg-bijzonder-fenomeen.-Door-de-herbruikbaarheid-van-software,-is-men-snel-in-staatom-complexe-vraagstukken-op-te-lossen.In-de-praktijk-hebben-wij-kunnen-ervaren-dat-open-source-en-open-data-innovatie-ensamenwerking-tussen-verschillende-partijen-stimuleren.-Doordat-er-geen-drempels-meer-zijn-inde-vorm-intellectuele-eigendomsrechten-worden-oplossingen-goedkoper-en-komen-ze-snellertot-stand.Een-volgende-vraag-die-wij-ons-stellen-is-of-het-mogelijk-is-om-geld-te-verdienen-met-onzeoplossing?-Hoe-verkoop-je-een-product-op-basis-van-open-source-en-open-data?Hier-over-hebben-we-diverse-ideeën,-zoals●
Haaglanden/HTM-hebben-belang-bij-actuele-reisinformatie.-Het-beeld-van-het-openbaarvervoer-wordt-beter-met-actuele-reisinformatie.-De-investering-en-beheerkosten-zijngering.-Bij-5-extra-reizigers-per-dag-ontstaat-al-een-break-even-situatie-(compensatie-vanextra-kosten-met-extra-reizigersopbrengsten).-
●
Voor-JC-Decaux,-exploitant-van-de-abri’s,-kan-het-heel-interessant-zijn-digitale-displays-tegebruiken-voor-reclame,-afgewisseld-met-reisinformatie,-waardoor-de-attentie-van-dereizigers-bij-het-display-blijft.-
●
Samenwerken-met-leveranciers-van-displays.-Zij-kunnen-goedkoper-displays-levereninclusief-beheer-en-onderhoud-door-gebruik-te-maken-van-open-sourceX-en-opendataoplossingen.-
De-business-cases-willen-we-nader-verkennen-na-ons-examen.-Het-Belgische-vervoersbedrijf-DeLijn-heeft-al-contact-met-ons-opgenomen-naar-aanleiding-van-het-filmpje-dat-we-hebbengemaakt.-Het-bedrijf-toonde-interesse-in-ons-project-omdat-zij-te-maken-hebben-metvergelijkbare-problematiek-als-wij-in-dit-werkstuk-onderzocht-heb----ben.-
-
48-
Profielwerkstuk-–-Open-source,-open-data-&-Hoe-laat-komt-mijn-tram?Sven-Boor-&-Arjen-Kremers-–-Gymnasium-Novum-
BRONVERMELDINGRasberry-PI:http://www.raspberrypi.org/http://www.savagehomeautomation.com/projects/raspberryXpiXinstallingXaXrs232XserialX port.html/180910053409?pt=US_Internal_Network_Cards&hash=item2a1f145821http://www.savagehomeautomation.com/projects/raspberryXpiXrs232XserialXinterfaceX optionsXrevisit.htmlhttp://www.raspberrypi.org/phpBB3/viewtopic.php?p=90223
-
Arduino:-http://www.arduino.cc/Modem:-http://www.ebay.com/itm/7X2MbpsXHUAWEIXE220XHSDPAXUMTSX3GXUSBXDongleX WirelessXModemXforXAndroidXXPXWin7Xpl2303x:-http://www.noah.org/wiki/RSX232#5Xwire_RSX232SSH-Tunneling:-http://www.linuxhorizon.ro/sshXtunnel.htmlGOVI:-http://govi.nu/Paul-Mijksenaar:-http://nl.wikipedia.org/wiki/Paul_MijksenaarKoppelvlak-informatie:-http://nl.wikipedia.org/wiki/KoppelvlakOpen-data-informatie:-http://nl.wikipedia.org/wiki/Open_dataOpen-source-informatie:-http://nl.wikipedia.org/wiki/Open_sourceGegevens-van-een-koperdraad:-http://nl.wikipedia.org/wiki/KoperdraadPython:-http://www.python.org/Informatie-over-inductiestoring-in-magneetspoel:-http://www.idd.nl/key/inductiestoring.htmlFilmpje-toepassing-open-data-in-OV-in-Boston:-http://www.youtube.com/watch?v=URmKRTUX hxQ-Filmpje-over-het-werkstuk:-http://vimeo.com/60644074Apps:https://play.google.com/store/apps/details?id=nl.skywave.ovinfo&hl=nlhttps://itunes.apple.com/nl/app/tranzzit/id591675055?-mt=8&ignXmpt=uo%3D4http://openbaarvervoerapp.nl/Syntax-colouring:-http://pygments.org-
49-