Inhoudsopgave 1 Van de installatie van het besturingssysteem tot en met het eerste Python-programma 1.1 Wat heeft men nodig? 1.1.1 Micro-USB-oplader voor mobiele telefoon 1.1.2 Geheugenkaart 1.1.3 Toetsenbord 1.1.4 Muis 1.1.5 Netwerkkabel 1.1.6 HDMI-kabel 1.1.7 Audiokabel 1.1.8 Gele FBAS-videokabel 1.2 Raspbian-besturingssysteem installeren 1.2.1 Geheugenkaart in de PC voorbereiden 1.2.2 De software-installer NOOBS 1.2.3 De LED's op de Raspberry Pi. 1.2.4 De eerste start op de Raspberry Pi. 1.
6 LED via pulsduurmodulatie dimmen 6.1.1 Zo werkt het 6.1.2 Twee LED's onafhankelijk van elkaar dimmen 6.1.3 Zo werkt het 53 56 57 59 7 Ruimteweergave van geheugenkaart met LED's 7.1.1 Zo werkt het 60 63 8 Grafische dobbelsteen 8.1.1 Zo werkt het 65 67 9 Analoge klok op het beeldscherm 9.1.1 Zo werkt het 72 73 10 Grafische dialoogvelden voor de programmabesturing 10.1.1 Zo werkt het 10.2 Looplicht met grafisch oppervlak besturen 10.2.1 Zo werkt het 10.3 Knippersnelheid instellen 10.3.
1 Van de installatie van het besturingssysteem tot en met het eerste Python-programma Er is amper een elektronisch apparaat in zijn prijsklasse waar de afgelopen maanden zoveel over is gepraat als de Raspberry Pi. Ook wanneer u het op het eerste gezicht niet zou zeggen, is de Raspberry Pi een volwaardige computer ter grootte van ongeveer een kredietkaart - en dat voor een lage prijs.
1.1.1 Micro-USB-oplader voor mobiele telefoon Voor de Raspberry Pi voldoet elke moderne netadapter voor mobiele telefoon. Oudere opladers uit de begintijd van de USB-oplaadtechniek zijn nog te zwak. Als men vermogensverbruikende USB-apparatuur aansluit zoals een harde schijven zonder eigen voeding, is een zwaardere netadapter noodzakelijk. De netadapter moet 5 V en minimaal 700 mA leveren, maar beter nog 1.000 mA. De ingebouwde vermogensregelaar voorkomt het »doorbranden« bij te zware netadapters.
1.1.7 Audiokabel Via een audiokabel met 3,5 mm jackpluggen kunnen koptelefoons of PC-luidsprekers worden gebruikt op de Raspberry Pi. Het audiosignaal is tevens via de HDMI-kabel beschikbaar. Bij HDMI-televisies of monitoren is een audiokabel niet nodig. Wanneer een PC-monitor via een HDMI-kabel met DVI-adapter wordt aangesloten, gaat meestal op deze plaats het audiosignaal verloren, zodat de analoge audiouitgang opnieuw nodig is. 1.1.
Geheugenkaart wordt gewist Gebruik bij voorkeur een lege geheugenkaart voor de installatie van het besturingssysteem. Als er zich op de geheugenkaart gegevens bevinden, worden deze door de nieuwe formattering tijdens de besturingssysteeminstallatie onherroepelijk gewist. 1.2.2 De software-installer NOOBS »New Out Of Box Software« (NOOBS) is een uiterst eenvoudige installer voor Raspberry Pibesturingssystemen.
Afb. 1.2: De status-LED's op de Raspberry Pi. 1.2.4 De eerste start op de Raspberry Pi. Na afsluiting van de installatie boot de Raspberry Pi opnieuw en start automatisch de configuratie-tool raspi-config. Hier hoeft u enkel nog onder Enable Boot to Desktop de optie Desktop Log in as user 'pi' te kiezen. De Nederlandse taal en Nederlandse toetsenbordindeling zijn overeenkomstig overige belangrijke basisinstellingen al automatisch gekozen. Na opnieuw opstarten is de grafische LXDE-desktop beschikbaar. 1.
Afb. 1.3: De LXDE-desktop op de Raspberry Pi komt in grote mate overeen met Windows XP. Raspbian-Linux voor de Raspberry Pi gebruikt de interface LXDE (Lightweight X11 Desktop Environment), die enerzijds zeer weinig systeemressourcen nodig heeft en anderzijds met zijn startmenu en de verkenner in grote mate overeenkomt met de bekende Windows-interface. Linux-aanmelding Ook de bij Linux kenmerkende gebruikersaanmelding wordt op de achtergrond uitgevoerd.
1.3.1 Eigen gegevens opslaan op de Raspberry Pi. Het bestandsbeheer loopt onder Linux echter anders dan onder Windows, maar is echter niet moeilijker. Raspbian komt met een verkenner, die sprekend op Windows-Explorer lijkt. Een belangrijk onderscheid ten opzichte van Windows: Linux scheidt niet strikt volgens loopwerken, alle bestanden bevinden zich in een gezamenlijk bestandssysteem. Onder Linux plaatst men alle eigen bestanden principieel alleen onder de eigen home-map.
Afb. 1.5: ... of op deze manier. Hoeveel vrije ruimte heeft de geheugenkaart? Niet alleen harde schijven van PC's zijn voortdurend vol – bij de geheugenkaart van de Raspberry Pi kan dit nog veel sneller gebeuren. Des te belangrijker is het, de vrije en bezette ruimte op de geheugenkaart altijd in de gaten te houden. De statusregel van de verkenner onderin de beeldschermrand, geeft rechts de vrije en bezette opslagruimte weer op de geheugenkaart. 1.
Python 2.7.3 wordt met het pictogram IDLE op de desktop gestart. Hier verschijnt een op het eerste gezicht eenvoudig invoerscherm met een opdrachtprompt. Afb. 1.6: Het invoerscherm van de Python-shell. In dit scherm opent u aanwezige Python-programma's, schrijft u nieuwe of kunt u ook direct Pythoncommando's interactief verwerken, zonder een eigenlijk programma te moeten schrijven. Voer bijv. bij de prompt het onderstaande in: >>> 1+2 Dan verschijnt onmiddellijk het juiste antwoord.
Python-flashcards Python is de ideale programmeertaal, om de instap in de programmering te leren. Men moet alleen wennen aan de syntax en de layout-regels. Ter assistentie in de dagelijkse programmering worden de belangrijkste syntaxelementen van de Python-taal in de vorm van »spiekbriefjes« kort beschreven. Deze zijn gebaseerd op de Python-flashcards van David Whale. Wat dit precies betekent, vindt u onder bit.ly/pythonflashcards.
Afb. 1.8: De juiste instelling voor de weergave van dubbele punten in Python. 4. Start nu het spel met de toets [F5] , of het menupunt Run/Run Module. 5. Het spel ziet omwille van de eenvoud af van elke grafische interface, alsmede op verklarende teksten of plausibiliteitsvragen voor de invoer. De computer genereert op de achtergrond een willekeurig getal tussen 0 en 1.000. Vermeld eenvoudig een tip en u verneemt, of het gezochte getal groter is of kleiner.
Afb. 1.9: Getallen raden in Python 1.4.2 Zo werkt het Dat het spel werkt, kan eenvoudig worden uitgeprobeerd. Nu ontstaan er natuurlijk enkele vragen: Wat gebeurt er op de achtergrond? Wat betekenen de losse programmaregels? import random Om random het willekeurige getal te genereren, wordt een externe Python-module met de naam geïmporteerd, dat verschillende functies voor willekeursgeneratoren bevat. getal = random.
Hoe ontstaan willekeurige getallen? Over het algemeen wordt gedacht dat in een programma niets toevallig kan gebeuren. Hoe kan het dan, dat een programma willekeurige getallen kan genereren? Wanneer een groot priemgetal door een willekeurige waarde wordt gedeeld, ontstaan vanaf de x-te plaats na de komma getallen, die nauwelijks nog voorspelbaar zijn. Deze veranderen ook zonder enige regelmatigheid, wanneer men de divisor regelmatig verhoogt.
.... verschijnt een andere tekst. i += 1 In elk geval – daarom niet meer ingesprongen – wordt de teller i, die de pogingen telt, met 1 verhoogd. Deze regel met de operator += betekent hetzelfde als i = i + 1. print "Je hebt het getal bij de ",i,". tip geraden" Deze regel is meer ingesprongen en dit betekent dat ook de while-lus is beëindigd..
Voorzichtig Verbind in geen geval enigerlei GPIO-pinnen met elkaar om daarna te wachten, wat er gebeurt, maar volg absoluut de onderstaande aanwijzingen op: enkele GPIO-pinnen zijn direct met aansluitingen van de processor verbonden, kortsluiting kan de Raspberry Pi volledig kapot maken. Verbindt men twee pinnen met elkaar via een schakelaar of een LED, moet hiertussen altijd een voorweerstand worden geschakeld. Gebruik voor logicasignalen altijd pin 1 die +3,3 V levert en tot 50 mA kan worden belast.
• 4x weerstand 220 kilo-ohm (rood-rood-bruin) • 12x Verbindingskabel (insteekprintplaat – Raspberry Pi) • ca. 1 m schakeldraad 2.1.1 Insteekprintplaten Voor het snel opbouwen van elektronische schakelingen, zijn twee insteekprintplaten in het pakket opgenomen. Hier kunnen elektronische onderdelen direct op standaardafstanden in het gaatjesrooster worden gestoken, zonder te moeten solderen.
Er is bovendien staaldraad meegeleverd in het leerpakket. Hiermee maakt u korte verbindingsbruggen, waarmee contactrijen op de insteekprintplaat worden verbonden. Knip het draad met een kleine zijkniptang op de passende lengtes af, zoals bij de individuele experimenten is beschreven. Om de draden beter in de insteekprintplaat te kunnen steken, wordt aanbevolen, de draden een beetje schuins af te snijden, zodat een soort wig ontstaat.
In het leerpakket zijn weerstanden in drie verschillende waarden opgenomen: Waarde 1. Ring (tien) 2. Ring (één) 3. Ring (multipl.) 4. Ring (tolerantie ) Toepassing 220 Ohm Rood Rood Bruin Goud Voorweerstand voor LED's 1 kilo-ohm Bruin zwart Rood Goud Beveiligingsweerstand voor GPIO-ingangen 10 kilo-ohm Bruin zwart Oranje Goud Pull-down-weerstand voor GPIO-ingangen Tab. 2.2: Kleurcodes van de weerstanden in het leerpakket.
Afb. 2.3: Opbouw insteekbord, om een LED aan te sluiten.
Afb. 2.4: De eerste LED op de Raspberry Pi In dit eerste experiment wordt de Raspberry Pi alleen gebruikt als voeding voor de LED. De LED brandt altijd, hiervoor is generlei software nodig. In het volgende experiment plaatst u een toets in de aanvoerleiding van de LED. De LED brandt nu alleen, wanneer deze toets is ingedrukt. Ook hiervoor heeft men generlei software nodig.
Afb. 2.5: Opbouw insteekbord voor een LED, die met een toets wordt geschakeld.
Afb. 2.6: LED met toets op de Raspberry Pi. 2.3 GPIO met Python De Python-GPIO-bibliotheek moet zijn geïnstalleerd, om GPIO-poorten via Python-programma's te kunnen gebruiken. Twijfelt u, of alle noodzakelijke modules zijn geïnstalleerd, installeer een keer de actuele versies via de onderstaande console-opdrachten: sudo apt-get update sudo apt-get install python-dev sudo apt-get install python-rpi.
2.4 LED aan- en uitschakelen Sluit een LED via een 220-ohm-voorweerstand (rood-rood-bruin) aan op een GPIO-poort 25 (pin 22) en niet meer direct op een +3,3-V-aansluiting en verbind de minpool van de LED via de aardrail van de insteekprintplaat met de aardleiding van de Raspberry Pi (pin 6), zoals weergegeven in de onderstaande afbeelding. Benodigde onderdelen: 1x insteekprintplaat 1x LED rood 1x 220-ohm-weerstand 2x verbindingskabel Het volgende programma led.
Afb. 2.7: Een LED aan de GPIO-poort 25. 2.4.1 Zo werkt het Het voorbeeld toont de belangrijkste basisfuncties van de RPi.GPIO-bibliotheek. import RPi.GPIO as GPIO De bibliotheek RPi.GPIO moet in elk Python-programma worden geïmporteerd, waarin ze zou moeten worden gebruikt. Door deze schrijfwijze kunnen alle functies van de bibliotheek via de prefix GPIO worden aangesproken. import time De regelmatig gebruikte Python-bibliotheek time heeft niets te maken met de GPIOprogrammering.
Nummering van de GPIO-poorten De bibliotheek RPi.GPIO ondersteunt twee verschillende methoden voor het kenmerken van de poorten. In de modus BCM worden de bekende GPIO-poortnummers gebruikt, die ook op commandoregelniveau of in shell-scripts worden gebruikt. In de alternatieve modus BOARD komen de kenmerken van de pinnummers 1 tot en met 26 overeen met de Raspberry Pi-printplaat. GPIO.setup(25, GPIO.OUT) De functie GPIO.setup initialiseert een GPIO-poort als uit- of als ingang.
2.5 Python met GPIO-ondersteuning starten, zonder terminal Wie veel met Python en GPIO bouwt, wil niet elke keer een LXTerminal opvragen, om IDLE te starten. Het kan ook eenvoudiger. Plaats hiervoor een pictogram op de desktop, die Python-IDE met superuser-rechten opvraagt: • Maak een kopie van het vooraf geïnstalleerde desktoppictogram IDLE. Ga hiervoor als volgt te werk: • Klik met de rechter muistoets op het pictogram IDLE op de desktop en kies in het contextmenu kopiëren. Afb. 2.
Afb. 2.9: Melding bij het dupliceren van een desktopkoppeling. Klik nu met de rechter muistoets op de kopie van het desktoppictogram en kies in het contextmenu Leafpad . Desktopkoppelingen zijn in Linux zuivere tekstbestanden, die met een tekstbewerkers kunnen worden bewerkt. Afb. 2:10: De desktopkoppeling in de Leafpad-Editor. Voer hier de beide afgebeelde wijzigingen uit. • Wijzig de veld naam naar IDLE GPIO. Dit is de op het beeldscherm weergegeven naam.
3 Verkeerslicht Eén LED aan- en weer uitschakelen, kan in het eerste geval heel spannend zijn, maar hiervoor heeft men eigenlijk geen computer nodig. Een verkeerslicht met kenmerkende lichtcyclus van groen via geel naar rood en daarna via een lichtcombinatie rood-geel weer naar groen, is met drie LED's eenvoudig op te bouwen en toon overige programmatechnieken in Python. Bouw de afgebeelde schakeling op de insteekprintplaat.
Afb. 3.2: Een eenvoudig verkeerslicht. Het programma ampel01.py sbestuur het stoplicht: import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BCM) rot = 0; gelb = 1; gruen = 2 Ampel=[4,18,23] GPIO.setup(Ampel[rot], GPIO.OUT, initial=False) GPIO.setup(Ampel[gelb], GPIO.OUT, initial=False) GPIO.setup(Ampel[gruen], GPIO.OUT, initial=True) print ("Strg+C beëindigt het programma") try: while True: time.sleep(2) GPIO.output(Ampel[gruen],False); GPIO.output(Ampel[gelb],True) time.sleep(0.
GPIO.output(Ampel[gelb],False); GPIO.output(Ampel[rot],True) time.sleep(2) GPIO.output(Ampel[gelb],True) time.sleep(0.6) GPIO.output(Ampel[rot],False); GPIO.output(Ampel[gelb],False) GPIO.output(Ampel[gruen],True) except KeyboardInterrupt: GPIO.cleanup() 3.1.1 Zo werkt het De eerste regels zijn al bekend, zij importeren de bibliotheken RPi.GPIO voor de aansturing van de GPIOpoorten e ntime voor tijdsvertragingen. Hierna wordt de nummering van de GPIO-poorten zoals in het eerdere voorbeeld op BCM geplaatst.
[Strg]+[C] –, wordt het programma afgebroken en de except-aanwijzing aan het einde van het programma wordt uitgevoerd.. except KeyboardInterrupt: GPIO.cleanup() Door deze toetscombinatie wordt een KeyboardInterrupt geactiveerd en de lus wordt automatisch verlaten. De laatste regel sluit de gebruikte GPIO-poorten en schakelt hiermee alle LED's uit. Hierna wordt het programma beëindigd.
4 Voetgangerslicht In het volgende experiment breiden we de verkeerslichtschakeling nog met een extra voetgangerslicht uit, die tijdens de roodfase van het verkeerslicht een knipperlicht voor voetgangers weergeeft, zoals het in sommige landen wordt gebruikt. Men kan natuurlijk ook het in Midden-Europa gebruikelijke voetgangerslicht met rood en groen licht in het programma inbouwen, alleen bevat dit leerpakket naast de voor het verkeerslicht gebruikte LED's, nog slechts één andere.
Afb. 4.2: Verkeerslicht met voetgangerlicht. Het programma ampel01.py bestuurt het nieuwe verkeerslicht: Ten opzicht van de eerdere versie is het programma maar gering uitgebreid. import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BCM) rot = 0; gelb = 1; gruen = 2; blau = 3 Ampel=[4,18,23,24] GPIO.setup(Ampel[rot], GPIO.OUT, initial=False) GPIO.setup(Ampel[gelb], GPIO.OUT, initial=False) GPIO.setup(Ampel[gruen], GPIO.OUT, initial=True) GPIO.setup(Ampel[blau], GPIO.
time.sleep(2) GPIO.output(Ampel[gruen],False); GPIO.output(Ampel[gelb],True) time.sleep(0.6) GPIO.output(Ampel[gelb],False); GPIO.output(Ampel[rot],True) time.sleep(0.6) for i in range(10): GPIO.output(Ampel[blau],True); time.sleep(0.05) GPIO.output(Ampel[blau],False); time.sleep(0.05) time.sleep(0.6) GPIO.output(Ampel[gelb],True); time.sleep(0.6) GPIO.output(Ampel[rot],False) GPIO.output(Ampel[gelb],False) GPIO.output(Ampel[gruen],True) except KeyboardInterrupt: GPIO.cleanup() 4.1.
time.sleep(0.6) Met een vertraging van 0,6 seconden na de laatste lusdoorloop wordt de normale schakelcyclus van het verkeerslicht voortgezet, doordat de gele LED aanvullend op de al brandende rode wordt ingeschakeld. Tot nu toe niet veel nieuws. Het voetgangerslicht wordt pas echt interessant , wanneer ze niet automatisch loopt, maar pas door een toetsindruk wordt gestart, zoals die bij veel voetgangerslichten het geval is.
Afb. 4.4: Toets met beveiligingsweerstand en pull-down-weerstand aan een GPIO-ingang. Bouw volgens de onderstaande afbeelding een toets met de beide weerstanden in. Afb. 4.5: Opbouw insteekbord voor de voetganger-»bedieningslicht«.
Benodigde onderdelen: 1x insteekprintplaat 1x LED rood 1x LED geel 1x LED groen 1x LED blauw 4x 220-ohm-weerstand 1x toets 1x 1-kilo-ohm-weerstand 1x 10-kilo-ohm-weerstand 7x verbindingskabel 1x korte draadbrug De in de afbeelding weergegeven onderste contactstrip van de toets is via de plus-rail van de insteekprintplaat met de +3,3-V-leiding van de Raspberry Pi (pin 1) verbonden. Voor de verbinding van de toets met de plus-rail gebruiken wij, om de tekening overzichtelijk te houden, een korte draadbrug.
Afb. 4.6: Voetgangersknipperlicht met toets Het programma ampel03.py bestuurt de nieuwe verkeerslichtinstallatie met de toets voor het voetgangersknipperlicht. # -*- coding: utf-8 -*import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BCM) rood = 0; geel = 1; groen = 2; blauw = 3; toets = 4 Ampel=[4,18,23,24,25] GPIO.setup(Ampel[rot], GPIO.OUT, initial=False) GPIO.setup(Ampel[gelb], GPIO.OUT, initial=False) GPIO.setup(Ampel[gruen], GPIO.OUT, initial=True) GPIO.setup(Ampel[blau], GPIO.
GPIO.setup(Ampel[taster], GPIO.IN) print ("Druk de toets in, om het voetgangerlicht in te schakelen, Strg+C beëindigt het programma") try: while True: if GPIO.input(Ampel[taster])==True: GPIO.output(Ampel[gruen],False) GPIO.output(Ampel[gelb],True) time.sleep(0.6) GPIO.output(Ampel[gelb],False) GPIO.output(Ampel[rot],True) time.sleep(0.6) for i in range(10): GPIO.output(Ampel[blau],True); time.sleep(0.05) GPIO.output(Ampel[blau],False); time.sleep(0.05) time.sleep(0.6) GPIO.output(Ampel[gelb],True) time.
Toen later parallel aan de ASCII-leestekens de ANSI-leestekens werden ingevoerd, die door oudere Windows-versies wordt gebruikt, maakte men dezelfde fout nog een keer. Om de taalverwarring perfect te maken, werden de Duitse dubbel punten en andere letters met accenten op andere plaatsen in de leestekens geplaatst dan in de ASCII-standaard.
while True: if GPIO.input(Ampel[taster])==True: Binnen de gesloten lus is nu een vraag ingebouwd. De onderstaande aanwijzingen worden pas uitgevoerd, als de GPIO-poort 25 de waarde True aanneemt, de gebruiker dus een toets indrukt. Tot aan dit moment blijft het verkeerslicht in haar groenfase staan. Het verdere verloop van de lus komt in wezen overeen met die van het laatste programma. Het verkeerslicht schakelt via geel naar rood, het knipperlicht knippert tien keer.
Benodigde onderdelen: 1x insteekprintplaat 1x LED rood 1x LED geel 1x LED groen 1x LED blauw 4x 220-ohm-weerstand 5x verbindingskabel Afb. 5.2: Vier LED's met voorweerstanden.
Aan de hand van verschillende LED-knipperpatronen, leggen wij andere lussen en programmeermethoden uit in Python. Het volgende programma biedt verschillende LED-patronen, die door de gebruiker via toetsenbordinvoer kan worden gekozen. Het programma ledmuster.py laat de LED's in verschillende patronen knipperen. # -*- coding: utf-8 -*import RPi.GPIO as GPIO import time import random GPIO.setmode(GPIO.BCM) LED = [4,18,23,24] for i in LED: GPIO.setup(i, GPIO.OUT, initial=0) z = len(LED); w = 5; t = 0.
for j in range(z): GPIO.output(LED[j], False) time.sleep(t) elif e == "5": for i in range(w*z): j = random.randint(0,z-1) GPIO.output(LED[j], True); time.sleep(t) GPIO.output(LED[j], False) else: print ("Ongeldige invoer") except KeyboardInterrupt: GPIO.cleanup() 5.1.1 Zo werkt het De eerste regels van het programma met de definitie van de UTF-8-codering en de import van de noodzakelijke bibliotheken zijn al vanuit eerdere experimenten bekend.
Om het programma algemeen geldend en gemakkelijk wijzigbaar te houden, worden nu nog slechts drie variabelen gedefinieerd: z Aantal LED's Het aantal LED's wordt met behulp van de functie len() automatisch uit de lijst LED overgenomen w Herhalingen Elk patroon wordt, opdat men het beter herkent, standaard vijf keer herhaald. Dit aantal kan willekeurig worden gewijzigd en geldt dan voor alle patronen. t Tijd Deze variabele geeft weer, hoe lang een LED tijdens het knipperen is ingeschakeld.
gevallen is dus raw_input() de betere keuze, omdat men zich niet bezig hoeft te houden met veel eventualiteiten van mogelijke invoeren. Het programma wacht, tot de gebruiker een letter invoert en op de [Enter]-toets drukt. Afhankelijk hiervan, welk getal de gebruiker heeft ingevoerd, moet nu een bepaald patroon met de LED's worden aangegeven. Om dit op te vragen, gebruiken wij een if...elif...else-constructie. Patroon 1 Was de invoer een 1, wordt het achter deze regel ingesprongen programmadeel uitgevoerd.
for i in range(w): for j in range(z): GPIO.output(LED[j], GPIO.output(LED[j], for j in range(z-1, -1, GPIO.output(LED[j], GPIO.output(LED[j], True); time.sleep(t) False) -1): True); time.sleep(t) False) Ook hier worden in elkaar geschakelde lussen gebruikt. Na de eerste binnenste lus, die overeenkomt met het eerder beschreven programmadeel, dus nadat de LED met nummer 3 brandt, start nog een lus voor het looplicht in tegengestelde richting. Lijstelementen zijn altijd met 0 beginnend genummerd.
De eerste binnenste lus schakelt de LED's opeenvolgend met een vertraging in. Aan het einde van de lus, die kan worden herkend aan het uitspringen van de regel time.sleep(2*t), wordt de dubbele vertragingstijd onderhouden. Gedurende die tijd branden alle LED's. Hierna begint een andere lus, die achterwaarts telt en de één na de andere LED weer uitschakelt.
Ongeldige invoer Bij alle programma's, die invoer van gebruikers vereisen, moet foute invoer worden ondervangen. Wanneer de gebruiker iets invoert dat niet wordt verwacht, moet het programma hierop reageren. else: print ("Ongeldige invoer") Als de gebruiker iets anders ingevoerd, wordt de onder else aangegeven aanwijzing uitgevoerd. Deze sectie van een vraag komt alleen dan overeen, wanneer geen van de andere vragen een waar resultaat heeft opgeleverd.
Afb. 6.
Afb. 6.3: Een LED aan de GPIO-poort 18. Het programma leddimmen01.py dimt de LED cyclisch lichter en donkerder en gebruikt hiervoor een eigen PWM-functionaliteit van de GPIO-bibliotheek. Het PWM-signaal wordt als eigen thread gegenereerd. Op deze manier kan een gedimde LED (bijna) als een normaal brandende LED in een programma worden toegepast. import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BCM); LED = 18 GPIO.setup(LED, GPIO.OUT) print ("Strg+C beëindigt het programma") p = GPIO.PWM(LED, 50); p.
6.1.1 Zo werkt het Een deel van dit programma zal u bekend voorkomen, enkele elementen echter helemaal niet, omdat wij op deze plaats een intermezzo in het objectgeoriënteerde programma maken. Aan het begin worden, zoals bekend, de bibliotheken geïmporteerd. Dit keer wordt slechts een enkele variabele, LED, voor de GPIOport 18 vastgelegd, deze wordt als uitgang geïnitialiseerd. print ("Strg+C beëindigt het programma") Omdat ook dit programma met een try...
Nadat de LED de volledige lichtsterkte heeft bereikt, regelt een tweede lus haar volgens hetzelfde schema weer omlaag. Deze lus telt van 100 in stappen van -2 omlaag. Deze cyclus herhaalt zich tot een gebruiker de toetscombinatie [Strg]+[C] indrukt. except KeyboardInterrupt: p.stop(); GPIO.cleanup() De KeyboardInterrupt activeert nu aanvullende de methode stop() van het PWM-object. Deze methode beëindigt de aanmaak van een PWM-signaal.
Benodigde onderdelen: 1x insteekprintplaat 1x LED geel 1x LED rood 2x 220-ohm-weerstand 3x verbindingskabel Afb. 6.5: Een tweede LED aan de GPIO-poort 25. Het programma leddimmen02.py dimt een LED cyclus lichter en donkerder, terwijl de andere LED weliswaar samen met de eerste LED lichter, maar in de andere cyclus niet donkerder wordt, maar weer vanaf 0 lichter wordt en hierbij snel flikkert. import RPi.
GPIO.setmode(GPIO.BCM); LED = [18,25] GPIO.setup(LED[0], GPIO.OUT); GPIO.setup(LED[1], GPIO.OUT) print ("Strg+C beëindigt het programma") p = GPIO.PWM(LED[0], 50); q = GPIO.PWM(LED[1], 50) p.start(0) q.start(0) try: while True: for c in range(0, 101, 2): p.ChangeDutyCycle(c); q.ChangeDutyCycle(c) time.sleep(0.1) q.ChangeFrequency(10) for c in range(0, 101, 2): p.ChangeDutyCycle(100-c); q.ChangeDutyCycle(c) time.sleep(0.1) q.ChangeFrequency(50) except KeyboardInterrupt: p.stop(); GPIO.cleanup() 6.1.
Nu start de tweede lus, omwille van het overzicht dit keer ook met oplopende telling. Voor de eerste LED uit het PWM-object p, die in deze cyclus stap-voor-stap moet worden gedimd, worden de betreffende waarden voor de pulsverhouding in elke doorloop berekend. Bij de tweede LED uit het PWM-object q wordt de pulsverhouding eenvoudig weer bijgeteld. Het knippereffect ontstaat door de gewijzigde frequentie. q.
Afb. 7.2: Opbouw insteekbord voor de ruimteweergave van de geheugenkaart.
Afb. 7.3: De drie LED's geven de vrije geheugenruimte op de geheugenkaart weer. Het programma speicheranzeige.py levert afhankelijk van de vrije geheugenruimte op de geheugenkaart verschillende LED-indicaties: Vrije geheugenruimte LED-indicator < 1 MB Rood 1 MB tot 10 MB rood–geel 10 MB tot 100 MB geel 100 MB tot 500 MB geel–groen > 500 MB groen Tab. 7.1: Zo wordt de vrije ruimte van de geheugenkaart weergegeven.
import RPi.GPIO as GPIO import time import os g1 = 1; g2 = 10; g3 = 100; g4 = 500 GPIO.setmode(GPIO.BCM) LED = [4,18,23] for i in range(3): GPIO.setup(LED[i], GPIO.OUT, initial=False) print ("Strg+C beëindigt het programma") try: while True : s = os.statvfs('/') f = s.f_bsize * s.f_bavail / 1000000 if f < g1: x = "100" elif f < g2: x = "110" elif f < g3: x = "010" elif f < g4: x = "011" else: x = "001" for i in range(3): GPIO.output(LED[i], int(x[i])) time.sleep(1.0) except KeyboardInterrupt: GPIO.
GPIO.setmode(GPIO.BCM) LED = [4,18,23] for i in range(3): GPIO.setup(LED[i], GPIO.OUT, initial=False) Een lijst definieert de GPIO-nummer van de drie LED's. Vervolgens initialiseert een lus de drie GPIO-poorten als uitgangen en zet alle LED's op uitgeschakeld. Ook in dit experiment gebruiken wij een try...except-constructie en een gesloten lus, om het programma steeds weer automatisch te laten lopen, tot de gebruiker het met [Strg]+[C] afbreekt.
Een lus legt de GPIO-uitvoerwaarden voor de drie LED's vast. Opeenvolgend krijgen alle LED's de getalwaarde van het betreffende cijfer uit de tekenvolgorde 0 of 1 toegekend. De waarden 0 en 1 kunnen evenals False en True worden gebruikt, om GPIO-uitgangen aut- of in te schakelen. De functie int() berekent uit een teken de getalwaarde hiervan. Het teken wordt via de lusteller i uit een bepaalde positie van de patroontekenketting gelezen. time.sleep(1.
# -*- coding: utf-8 -*import pygame, sys, random from pygame.locals import * pygame.init() VELD = pygame.display.set_mode((320, 320)) pygame.display.set_caption("dobbelsteen") BLAU = (0, 0, 255); WEISS = (255, 255, 255) P1 = ((160, 160)); P2 = ((60, 60)); P3 = ((160, 60)); P4 = ((260, 60)) P5 = ((60, 260)); P6 = ((160, 260)); P7 = ((260, 260)) mainloop = True print "Druk een willekeurige toets in, om de dobbelsteen te gooien, [Esc] beëindigt het spel" while mainloop: for event in pygame.event.
Loopt zonder sudo Omdat dit programma geen GPIO-poorten nodig heeft, loopt het ook zonder superuser-rechten. U kunt de Python-IDLE eenvoudig via het desktop-pictogram IDLE starten. 8.1.1 Zo werkt het Dit programma toont een veelvoud aan nieuwe functies, in het bijzonder voor de grafische weergave met de PyGame-bibliotheek, die natuurlijk niet alleen voor spellen, maar ook voor alle andere grafische weergaves op het beeldscherm kan worden gebruikt. import pygame, sys, random from pygame.
Het coördinatensysteem voor computergrafiek Ieder punt in een scherm resp. op een surface-object wordt door een x- en een y-coördinaat gekenmerkt. Het nulpunt van het coördinatensysteem is niet, zoals men het op school heeft geleerd, linksonder, maar linksboven. Net als dat men een tekst van linksboven naar rechtsonder leest, loopt de x-as van links naar rechts, de y-as van boven naar onderen. De zeven punten P1 tot en met P7 kenmerken de in de grafiek aangegeven middelpunten van de dobbelsteenogen.
mainloop = True Hiermee is de basis gemaakt, en het eigenlijke spel kan beginnen. print "Druk op een willekeurige toets, om te dobbelen, [Esc] beëindigt het spel" Deze regel legt in het kort uit aan de gebruiker, wat er moet worden gedaan. Bij elke keer indrukken van een willekeurige toets op het toetsenbord, wordt opnieuw gedobbeld. print schrijft altijd in het Python-shellscherm, niet in het nieuwe grafische scherm. while mainloop: Nu begint de hoofdlus van het spel.
Nu genereert de willekeursfunctie random een willekeurig getal tussen 1 en 6 en slaat deze op in de variabele ZAHL. Deze regel schrijft alleen ter controle het dobbelresultaat in het Python-shell-scherm. Deze regel kan ook worden weggelaten, wanneer u op de op tekstgebaseerde uitvoer wilt afzien. print ZAHL if ZAHL == 1: pygame.draw.circle(FELD, WEISS, P1, 40) Nu volgen er zes vragen, allen volgens hetzelfde schema.
Afb. 8.3: De zes mogelijke dobbelresultaten.
De lus start direct vanaf het begin en wacht weer op het indrukken van een toets door de gebruiker. Wanneer tijdens de lus mainloop op False is gezet, omdat de gebruiker het spel wil beëindigen, wordt de lus niet nog een keer doorlopen, maar in plaats daarvan wordt de volgende regel uitgevoerd. pygame.quit() Deze regel beëindigt de PyGame-module, waardoor tevens het grafische scherm sluit en daarna het volledige programma.
Het programma uhr01.py geeft de afgebeelde analoge klok weer op het beeldscherm: import pygame, time from pygame.locals import * from math import sin, cos, radians pygame.init() ROT = (255, 0, 0); WEISS = (255, 255, 255); SCHWARZ = (0, 0, 0) FELD = pygame.display.set_mode((400, 400)) FELD.fill(WEISS) MX = 200; MY = 200; MP = ((MX, MY)) def punkt(A, W): w1 = radians(W * 6 – 90); x1 = int(MX + A * cos(w1)) y1 = int(MY + A * sin(w1)); return((x1, y1)) for i in range(60): pygame.draw.
De drie in de grafiek gebruikte kleuren worden in drie variabelen opgeslagen. FELD = pygame.display.set_mode((400, 400)); FELD.fill(WEISS) Een 400 x 400 pixel groot scherm wordt geopend en volledig met wit ingevuld. MX = 200; MY = 200; MP = ((MX, MY)) Drie variabelen leggen de coördinaten van het middelpunt vast, waarop de betrokken verdere grafische elementen, de wijzerplaat en de wijzers worden uitgelijnd.
Een lus tekent opeenvolgend de 60 minutenpunten op een cirkel. Alle punten worden met de functie punt() bepaald. Ze hebben de gelijke afstand vanaf het middelpunt, dat met 190 pixels in de vier kwadranten nog exact 10 pixels van de schermrand is verwijderd. De punten hebben een radius van 2 pixels. for i in range(12): pygame.draw.circle(FELD, SCHWARZ, punkt(190, i * 5), 4) Een tweede lus tekent 12 grotere cirkels, die de uren op de wijzerplaat markeren.
opgeteld. In elke minuut beweegt de urenwijzer 1/60 uur verder. De berekende waarde wordt met 5 vermenigvuldigd, omdat de urenwijzer in een uur vijf minuteneenheden op de wijzerplaat vooruitgaat. if s1 <> s: De duur van een lusdoorloop in een programma is niet bekend. Voor de analoge klok betekent dit, dat de grafiek niet bij elke lusdoorloop moet worden bijgewerkt, echter alleen, wanneer de actuele seconde afwijkt van degene die als laatste is getekend.
Deze regel tekent de secondewijzer als rode lijn met een breedte van 2 pixels, vanuit het middelpunt 180 pixels lang in een hoek, die door de secondewaarde wordt aangegeven. s1 = s Nu wordt de zojuist weergegeven seconde in de variabele s1 opgeslagen, om deze waarde in de volgende lusdoorlopen met de actuele seconde te vergelijken. pygame.display.set_caption("Actuele tijd: " + time.asctime()) Deze tijd schrijft de actuele tijd in digitale vorm in het schermonderwerp. Hiervoor wordt de functie time.
Benodigde onderdelen: 1x insteekprintplaat 1x LED rood 1x 220-ohm-weerstand 2x verbindingskabel Afb. 10.1: Eén LED aan de GPIO-poort 4. Sluit een LED via een voorweerstand aan op GPIO-poort 4. Het programma ledtk01.py zorgt ervoor dat deze gaan branden. import RPi.GPIO as GPIO from Tkinter import * LED = 4; GPIO.setmode(GPIO.BCM); GPIO.setup(LED,GPIO.
def LedEin(): GPIO.output(LED,True) def LedAus(): GPIO.output(LED,False) root = Tk(); root.title("LED") Label(root, text="Klik op de toets. om de LED aan- en uit te schakelen").pack() Button(root, text="Aan", command=LedEin).pack(side=LEFT) Button(root, text="Uit", command=LedAus).pack(side=LEFT) root.mainloop() GPIO.cleanup() Afb. 10.2: Zo zal het voltooide dialoogveld er uitzien. 10.1.
root = Tk() Tkinter werkt met zogenaamde widgets. Hierbij betreft het zelfstandige beeldschermelementen, in de meeste gevallen dialoogvelden, die van hun kant verschillende elementen bevatten. Elk programma heeft een root-widget nodig, van waaruit alle andere objecten worden opgeroepen. Deze root-widget heet altijd Tk(), genereert automatisch een scherm en initialiseert ook de Tkinter-bibliotheek. root.title("LED") Objecten in Tkinter stellen verschillende methoden voor vele doeleinden ter beschikking.
Nu zijn alle functies en objecten gedefinieerd en het eigenlijke programma kan starten. root.mainloop() Het hoofdprogramma bestaat slechts uit een losse regel. Het start de hoofdlus een methode van de root-widget. Deze programmalus wacht, tot de gebruiker een van de widgets bedient en hiermee een actie activeert. mainloop(), Het x-symbool rechtsboven voor het sluiten van het scherm hoeft bij Tkinter niet zelf te worden gedefinieerd.
Afb. 10.4: Opbouw insteekbord voor experiment 10.2.
Afb. 10.5: Vier LED's knipperen in verschillende patronen. Het programma ledtk02.py gebaseerd op het vorige programma, is echter met de radiobuttons alsmede met de functies voor de LED-looplichten en knippervoorbeelden uitgebreid. import RPi.GPIO as GPIO import time from Tkinter import * GPIO.setmode(GPIO.BCM) LED = [4,18,23,24] for i in LED: GPIO.setup(i, GPIO.OUT, initial=0) w = 5; t = 0.
] root = Tk(); root.title("LED"); v = IntVar(); v.set(1) def LedEin(): e = v.get() if e == 1: for i in range(w): for j in range(4): GPIO.output(LED[j], True) time.sleep(t) GPIO.output(LED[j], False) elif e == 2: for i in range(w): for j in range(4): GPIO.output(LED[j], True) time.sleep(t) for j in range(4): GPIO.output(LED[j], False) time.sleep(t) else: for i in range(w): for j in range(4): GPIO.output(LED[3-j], True): time.sleep(t) GPIO.
Muster = [ ("Loopflicht naar links",1), ("Knipperen",2), ("Looplicht naar rechts",3) ] De teksten van de drie patronen, die kunnen worden gekozen, worden in een speciale lijstvorm gedefinieerd. Elk van de drie lijstelementen bestaat uit een waardepaar, elk bestaand uit de aangegeven tekst en een getalwaarde, die later bij de keuze van de betreffende radiobuttons moet worden teruggegeven. root = Tk(); root.
else: for i in range(w): for j in range(4): GPIO.output(LED[3-j], True); time.sleep(t) GPIO.output(LED[3-j], False) Het derde geval is gelijk aan het eerste, met als verschil, dat de LED's achteruit worden geteld en hierdoor het looplicht in omgekeerde richting loopt. Nadat de functie is gedefinieerd, worden de elementen van de grafische oppervlakken gecreëerd. Label(root, text="Klik op de button, om het looplicht te starten").pack() De tekst van het dialoogveld wordt weer als Label-object gedefinieerd.
keuze maken. Door op Start te klikken, start aansluitend het gekozen patroon en laat het vijf keer lopen. Hierna kunt u een ander patroon kiezen. 10.3 Knippersnelheid instellen In de derde stap wordt het dialoogveld opnieuw uitgebreid. De gebruiker kan nu via een schuifregelaar de knippersnelheid instellen. Afb. 10.6: Keuze uit drie LED-patronen en de instelbare knippersnelheid.
e = v.get() t = 1.0/g.get() if e == 1: for i in range(w): for j in range(4): GPIO.output(LED[j], True); time.sleep(t) GPIO.output(LED[j], False) elif e == 2: for i in range(w): for j in range(4): GPIO.output(LED[j], True) time.sleep(t) for j in range(4): GPIO.output(LED[j], False) time.sleep(t) else: for i in range(w): for j in range(4): GPIO.output(LED[3-j], True): time.sleep(t) GPIO.output(LED[3-j], False) Label(root, text="Klik op de button, om het looplicht te starten").
Omdat een gebruiker intuïtief het sneller knipperen combineert met een hogere snelheid, wordt de schuifregelaar naar rechts hogere waarden teruggeven. In het programma is echter voor een hogere snelheid een kortere wachttijd, oftewel een lagere waarde nodig. Dit wordt bereikt door het berekenen van de omgekeerde waarde, die uit de waarden 1 tot en met 10 van de schuifregelaar, de waarden 1.0 tot en met 0.1 voor de variabele t bepaalt. In de formule moet 1.
Duitsland onder de naam Senso op de markt. Atari bracht een kopie onder de naam Touch Me ter grootte van een zakrekenmachine uit. Nog een kopie verscheen als Einstein, in de Engelstalige landen werd Senso als Simon op de markt gebracht. Raspbian levert een grafische versie van dit spel mee bij de Python Games onder de naam Simulate. Afb. 11.1: Het spel Simulate uit de Python games. Ons spel PiDance is tevens gebaseerd op dit spelprincipe. De LED's knipperen in een willekeurige volgorde.
Afb. 11.2: Opbouw insteekbord voor experiment 11.
Afb. 11.3: PiDance met LED's en toetsen op twee insteekprintplaten. De toetsen zijn tegenover de bijbehorende LED's gebouwd. De middelste lange rijen van de insteekprintplaten aan beide zijden van de verbindingsplaat dienen als 0-V- en +3,3-V-leiding voor de schakeling. Het programma pidance01.py bevat het kant-en-klare spel. # -*- coding: utf-8 -*import time, random import RPi.GPIO as GPIO GPIO.setmode(GPIO.BCM) rzahl = 10; kleur = [] for i in range(rzahl): farbe.append(random.
return 2 if(GPIO.input(TAST[3])): return 3 ok = True for runde in range(1, rzahl +1): print "Ronde", runde for i in range(runde): LEDein(farbe[i], 1) for i in range(runde): taste = Druecken() LEDein(taste, 0.2) if(taste != farbe[i]): print "Verloren!" print "Je hebt tot ronde", ronde – 1, "gehaald" for j in range(4): GPIO.output(LED[j], True) for j in range(4): time.sleep(0.5) GPIO.output(LED[j], False) ok = False break if(ok == False): break time.sleep(0.
LED = [23,24,25,8] for i in LED: GPIO.setup(i, GPIO.OUT, initial=False) De GPIO-poorten voor de LED's worden volgens het bekende schema in een lijst LED als uitgangen ingesteld en allemaal uitgeschakeld. TAST = [4,17,21,22] for i in TAST: GPIO.setup(i, GPIO.IN) Volgens hetzelfde principe worden de GPIO-poorten voor de vier toetsen in een lijst TAST als ingangen ingesteld. Hiermee is de basis vastgelegd en worden er nog twee functies gedefinieerd, die meerdere keren nodig zijn in het programma.
print "Ronde", runde De actuele ronde wordt in het Python-shell-scherm weergegeven. for i in range(ronde): LEDein(farbe[i], 1) Nu speelt het programma het voorbeeld af, dat de speler moet onthouden. Afhankelijk van het actuele aantal ronden, gaan achtereenvolgens het overeenkomstige aantal LED's branden, volgens de aan het begin van het programma vastgestelde lijst kleur met de willekeurig gekozen kleuren. Omdat de teller ronde met 1 begint, brandt al in de eerste ronde exact één LED.
if(ok == False): break Wanneer ok op False staat, wordt tevens de buitenste lus afgebroken, er volgens geen andere ronden meer. time.sleep(0.5) Als de invoer van de volgorde correct was, wacht het programma 0,5 seconden, tot de volgende ronde start. if(ok == True): Het programma bereikt deze plaats, wanneer de lus volledig is doorlopen, de speler dus alle volgordes correct heeft ingevoerd, of de eerdere lus door een speelfout is afgebroken. Indien ok nog op True staat, volgt de huldiging.
Impressum © 2014 Franzis Verlag GmbH, Richard-Reitzner-Allee 2, 85540 Haar bei München www.elo-web.de Auteur: Christian Immler ISBN 978-3-645-10145-5 Alle rechten voorbehouden, waaronder ook fotomechanische reproductie en het opslaan in/op elektronische media. Het maken en verspreiden van kopieën op papier, op gegevensdragers of op het internet, in het bijzonder als PDF, is alleen toegestaan met uitdrukkelijke toestemming van de uitgever en wordt bij gebreke hiervan berecht.