Bonus track

Zoals al is uitgelegd tijdens de les maken we dit jaar voornamelijk gebruik van de Arduino bij dit project. De rede hiervoor is dat jullie nooit geleerd hebben hoe je op school verbinding kunt maken met je Pi. De netwerkbeheerders zijn erg op hun hoede om andere devices dan laptops, smartphones en dergelijek aan het netwerk te hangen. Daarnaast is het ook niet mogelijk om jullie allemaal een scherm, toetsenbord en muis te geven voor dit project om op school op de Pi te programmeren. Voorheen zat in het vak IARCH een manier om je Pi en laptop in te stellen om je Pi aan je laptop aan te sluiten en via je laptop te benaderen, zonder je Pi aan het schoolnetwerk te hoeven hangen. Omdat dit heel veel gedoe is om goed in te stellen, hebben we dit uit het proejct gelaten. Het jammere is dat je nu geen gebruik kunt maken van je Pi tijdens dit project, want je beleving moet ook op school te gebruiken zijn. Mocht je toch graag gebruik willen maken van je Pi, dan kun je op deze pagina lezen hoe dat moet en krijg je wat extra informatie over het Pi-programmeren mee. Er zitten geen opdrachten bij deze Track, omdat deze optioneel is. Voel je dus vooral vrij om deze Track volledig ove te slaan en tijdens je project alleen gebruik te maken van de Arduino.

Headless werken

Zoals in de inleiding al is uitgelegd, kunnen we via headless werken toch met de Pi communiceren. Headless werken wil zeggen dat je via een externe computer verbinding maakt met een device om die te bedienen. In ons geval houd dit concreet in dat we via een lokaal netwerk vanaf onze laptop vrbinding maken met de Pi, zodat we op die maneir de Pi toch kunnen bedienen en geen schermen, tetsenborden ne muizen nodig hebben. Hiervoor is het wel belangrijk dat je de Pi via een ethernet kabel (internet kabel) aan kunt sluiten op je laptop. Veel laptops hebben tegenwoordig geen LAN aansluiting (internet aansluiting) meer. In dat geval moet je ook nog een losse USB naar LAN adapter in je bezit hebben.

Hieronder volgen de links naar de bestanden die nodig zijn om dit headless werken mogelijk te maken. Allereerst volgt er een link naar een oude handleiding van IARCH. Daarin wordt je tap voor stap meegenomen in het headless werken. Kort gezecht gaan we een virtuele machine op je laptop instellen als router, zodat de Pi via de LAN kabel een IP-adress krijgt van de virtuele machine en we via die virtuele machine via de Terminal de Pi kunnen bedienen.

Naast de handleiding staat er ook een link naar een .zip file met een speciale Raspbian image. In deze image staat SSH standaard aan, wat we nodig gaan hebben voro onze verbinding. Het is dezelfde image als die dit jaar bij IARCH is verpreid. Tot slot is er nog een link naar een .zip met daarin twee files die uiteindelijk op je Pi moeten komen. Vanuit de handleiding wordt heir vanzelf naar verwezen.

Download de handleiding

Download de speciale Raspbian image

Download de .zip met de twee losse files

Tot slot is het ook mogelijk om via je mobiel een lokaal netwerk op te zetten en zowel je Pi als je laptop op dat netwerk aan te sluiten. Op die manier kun je via een programma als Putty ook verbinding maken met je Pi. Als je voor deze opdtie wilt gaan, dan moet je zelf even op internet zoeken hoe je dit voor elkaar krijgt!

Basis Pi programmeren

Tijdens IARCH, maar vooral tijdens de challengeweek van Interactie-technologie, heb je gewerkt met de GPIO-pinnen (General Purpose Input/Output pinnen) van de Raspberry Pi. In totaal zitten er 40 pinnen op de Pi in de onderstaande hoeveelheden:

  • Twee 5 Volt pinnen
  • Twee 3.3 Volt pinnen
  • Acht Ground pinnen
  • 26 GPIO-pinnen
  • Twee pinnen om een EEPROM op aan te sluiten (gaan we niet gebruiken)

En voor het gemak op deze pagina ook nog maar eens het Pinout diagram van de Raspberry Pi:

Figuur B.1: Het pinout diagram van de Raspberry Pi.
(Klik op het plaatje voor een grotere weergave)

En dan nu naar het programma. Vrijwel ieder Python programma voor de Raspberry Pi volgt dezelfde structuur:

import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)

while True:
  #Doe iets voor altijd

Eerst importeer je alle libraries die je gaat gebruiken in je programma. In het geval dat je gaat werken met de GPIO pinnen dien je de eerste regel altijd neer te zetten.

Na de imports zet je de Pi in de juiste mode om de pinnen aan te kunnen spreken. Wij gebruiken vaak GPIO.BCM. Op die manier kun je alle GPIO.pinnen aanspreken met de tekst in de gekleurde labels van het Pinout diagram. (GPIO2, GPIO3, etc.) De andere optie is GPIO.BOARD. In dat geval spreek je de pinnen aan volgens de getallen die in de cirkels staan. Wij raden je echter aan om GPIO.BCM te gebruiken. Op die manier voorkom je dat je pinnen gaat aanspreken, die niet aan te spreken zijn (De Volt, Ground en EEPROM pinnen).

Daarna volgen de declaraties van globale variabelen, als die er zijn. Hier gaan we verderop voorbeelden van geven.

De hoofdtaak van het programma volgt achter de 'while True:' loop. Alles was hierachter staat, blijft zich net zo lang herhalen totdat de Pi van het stroom gaat, de interpreter een fout in de code tegenkomt of de wereld vergaat.

Let goed op de verschillen tussen Python en JAVA! Let bijvoorbeeld op True met een hoofdletter, de dubbele punt achter de while loop, de # voor commentaar en de indenties (inspringen) bij code blokken. Denk er aan dat Python strikt is op het gebruik van dezelfde karakters om code te laten inspringen. Een tab en vier spaties lijken in je teksteditor vaak hetzelfde, maar zijn voor Python totaal verschillend en kunnen er voor zorgen dat je programma hopeloos vast loopt. Wij raden aan om altijd spaties (vaak twee of vier) te gebruiken om code te laten inspringen en geen tabs.

Dan tot slot nog even opfrissen hoe je ook alweer een Python programma schrijft. Als je via de terminal bent ingelogd op je Raspberry Pi, open je met nano (of je eigen favoriete teksteditor) een file die eindigt op .py.

nano [code].py

Typ daarin je code, sla de file op, sluit deze af en run de code vervolgens met het commando sudo python en de naam van je file.

sudo python [code].py

De hoogste tijd om deze theorie eens in praktijk te gaan brengen.

Pi output

In je bordspel wil je uiteindelijk sensoren (knopjes, lichtsensoren, magneetsensoren) kunnen uitlezen. Op basis van de input die je uit die sensoren krijgt, wil je actuatoren (leds, displays, led-matrixen) kunnen aansturen. De GPIO pinnen die op de Raspberry Pi zitten, kunnen voor beide toepassingen worden gebruikt. Om een GPIO-pin te kunnen gebruiken voor output (het aansturen van een actuator) heb je de volgende functies tot je beschikking:

LED = 18
GPIO.setup(LED, GPIO.OUT)
GPIO.output(LED, GPIO.HIGH)
GPIO.output(LED, GPIO.LOW)

Je ziet dat we gebruik maken van een variabele om een pin in op te slaan. Op deze manier staat maar op één plek in je code aangegeven op welke pin een component is aangesloten. Wanneer je besluit om je led op een andere pin aan te sluiten, hoef je dit dus maar op een plek in je code aan te passen. Daarnaast kun je meteen zien wel component je aanspreekt met de GPIO.output() functie. We raden jullie dus heel sterk aan om dit te gebruiken! Als je het programma hebt ingesteld op GPIO.BCM wordt in dit voorbeeld de pin met het label GPIO18 gebruikt. Je hoeft daar niet de tekst GPIO voor te zetten.

In de GPIO.setup() functie geven we aan welke instelling we de pin willen meegeven. We geven eerst het nummer van de pin mee (hier via een variabele) en vervolgens geven we hier aan dat we de pin instellen als output.

Tot slot geven we via de GPIO.output() functie aan of we spanning op de pin (GPIO.HIGH) willen zetten of het er juist af willen halen (GPIO.LOW). Denk eraan dat de spanning nooit zomaar van de pin afgaat. Als je een actuator aan zet, gaat hij pas uit wanneer hij expliciet uit wordt gezet.

Pi input

In je bordspel wil je uiteindelijk ook sensoren (knopjes, lichtsensoren, magneetsensoren) kunnen uitlezen. Op basis van de input die je uit die sensoren krijgt, wil je actuatoren (leds, displays, led-matrixen) kunnen aansturen. De GPIO pinnen die op de Raspberry Pi zitten, kunnen voor beide toepassingen worden gebruikt. Om een GPIO-pin te kunnen gebruiken voor input (het uitlezen van een sensor) heb je de volgende functies tot je beschikking:

BUTTON = 18
GPIO.setup(BUTTON, GPIO.IN, pull_up_down=GPIO.PUD_UP)

if GPIO.input(BUTTON) == FALSE:
  #Doe iets als de knop is ingedrukt
else:
  #Doe iets als de knop NIET is ingedrukt

Je ziet dat we wederom gebruik hebben gemaakt van een variabele om een pin aan te spreken. Als je het programma hebt ingesteld op GPIO.BCM, wordt in dit voorbeeld wederom de pin met het label GPIO18 gebruikt.

In de GPIO.setup() functie geven we weer aan welke instelling we de pin willen meegeven. We geven eerst het nummer van de pin mee (hier via een variabele) en vervolgens geven we hier aan dat we de pin instellen als input. Als laatste parameter zie je pull_up_down=GPIO.PUD_UP staan. Met deze regel zetten we de pull-up resistor die aangesloten zit op de desbetreffende pin hoog. Een pull-up resistor is een ingebouwde weerstand in de pi of Arduino, die intern aangesloten zit op een pin. Door de pull-up resistor hoog te zetten, zetten we spanning op de pin via deze ingebouwde weerstand. Zo hoef je dus niet bang te zijn dat je Pi of Arduino doorbrand, want er zit al een standaard weerstand in. Deze optie gebruik je meestal speciaal voor knopjes en dergelijke.

Let op! Soms vind je schakelingen op het internet waar mensen hun knopje op de 5V (of 3.3V) hebben aangesloten. Er zijn manieren om dit werkend te krijgen, maar altijd met behulp van een weerstand. Als je een knopje op de 5V aansluit en er geen weerstand tussen doet, is de kans groot dat je Pi of Arduino doorbrand! De bovenstaande methode met de pull-up resistor raden wij als docenten aan, omdat dit de meest veilige is.

Onder de setup functie zie je een if-statement. De functie GPIO.input() geeft de status terug van de pin die je als parameter hebt meegegeven. Als er spanning op de pin staat geeft de functie True terug, anders geeft de functie False terug. (Ook Output pins zou je met deze functie kunnen uitlezen) Omdat de pull-up resistor hoog staat, geeft de functie False terug als de knop wordt ingedrukt. Als de knop namelijk niet is ingedrukt, kan de spanning nergens heen en zal volledig op de pin staan en leest de functie True uit. Op het moment dat de knop wordt ingedrukt loopt de stroom weg van de pin naar de Ground en leest de functie False uit.

Pi serieel

Nu je weet hoe je met de Arduino teksten kan versturen, is het de hoogste tijd om te kijken hoe we die data op de Pi kunnen opvangen.

Voordat we daar in gaan duiken willen we je één ding meegeven. Dit is wellicht het lastigste onderdeel van de Hardware Heaven. Als je ook wilt dat de Pi seriële data naar de Arduino kan sturen, dan moet je zelf even op internet zoeken naar code hoe de Arduino seriële data kan ontvangen.

Om op de Pi een Seriële verbinding te kunnen openen, moeten we op de Pi eerst de Seriële library installeren. Doe dit met behulp van het volgende commando:

sudo apt-get install python-serial

Vervolgens moeten we erachter zien te komen op welke poort de Arduino is aangesloten. Met onderstaand commando kunnen we kijken welke poorten er allemaal beschikbaar zijn.

ls /dev/tty*

Voer het commando eerst een keer uit, zonder dat je Arduino is aangesloten op je Pi. Je ziet nu een hele rij met mogelijke poorten staan, maar die van je Arduino staat er nog niet tussen. Koppel nu je Arduino door middel van een USB-kabel aan je Pi en voer het commando nog een keer uit. Nu is er een poort bij gekomen. Dit is vaak de laatste in de lijst en lijkt vaak op /dev/ttyUSB0. Onthoud deze poort, want deze hebben we zo dadelijk in de code nodig om de Arduino aan te spreken.

Nu we de poort van de Arduino weten, kunnen we een seriële verbinding vanuit de Pi gaan opzetten. Dit wordt gedaan met behulp van de onderstaande code, die we daarna weer uitleggen.

import serial

port = serial.Serial("/dev/ttyUSB0", baudrate=9600, timeout=3.0)

while True:
 rcv = port.readline().strip()
 port.write("\r\nYou sent:" + repr(rcv))

Allereerst moeten we de gedownloade library importeren, om vervolgens een seriële verbinding te kunnen openen. Hiervoor maak je een variabele aan waar je een serieel object in stopt. Door serial.Serial() aan te roepen, maken we een dergelijk object en tevens een seriële verbinding aan. De eerste parameter is de poort waar de Arduino op is aangesloten, die we in de vorige stap hebben gevonden. De tweede parameter is de baudrate, die hetzelfde moet zijn als die waar de Arduino mee communiceert. Het derde argument is de timeout, die aangeeft hoe lang de Pi moet proberen de verbinding op te starten (hier 3 seconden).

Vervolgens kunnen we de buffer uitlezen met de readline() functie. De strip() functie zorgt er daarna weer voor dat alle overbodige karakters van de input worden afgehaald. En om vervolgens tekst naar de Arduino te sturen kun je de write() functie gebruiken. Simpel uitgelegd zorgt de functie repr() ervoor dat er vervolgens geen String-object maar gewoon een String naar de write() functie wordt gestuurd.