Reageren op de Raspberry Pi GPIO pins

Met deze IPython Notebook verbinden we hardware met software. We zullen een knop verbinden met de General Purpose Input/Output (GPIO) pinnen* op de Raspberry Pi en wanneer de knop ingedrukt wordt, de Pi een functie laten uitvoeren.

GPIO pinnen zijn de 40 (genummerde) pinnen tegenover de HDMI/scherm aansluiting waarop elektronische componenten aangesloten kunnen worden.

Maar eerst maken we de functie die we willen aanroepen. Er staan al enkele geluiden in de vorm van .wav files op de Pi (d.i. zoiets als MP3 bestanden) en er staat een bibliotheek op de Pi die deze geluiden kan afspelen (de pygame bibliotheek die gebruikt wordt om spelletjes te maken in Python)

Dus we importeren de mixer module van de pygame bibliotheek en initaliseren ze:

IPython Instructies:

Plaats je cursor in de cel hieronder en druk Shift+Enter of klik op de Play knop in de menubalk bovenaan om de code in de cel uit te voeren

  • Shift + Enter: Voer de cel uit en spring naar de volgende cel
  • Ctrl + Enter: Voer de cel uit, maar blijf op de huidige cel staan
  • Alt + Enter: Voer de cel uit en maak een nieuwe cel aan

Zolang er een [*] staat links van de cel is de code nog aan het lopen. Zodra de code beëindigd is, komt er een volgnummmer en wordt eventuele output uitgeprint onder de cel


In [ ]:
import pygame.mixer
pygame.mixer.init()

We vragen de pygame bibliotheek een .wav bestand in het geheugen te laden en er een geluid van te maken (en omdat we het niet kunnen laten spelen we het ineens een keertje af; vergeet geen boxen of hoofdtelefoon aan te sluiten)

nota: het wav bestand halen we uit een map die geïnstalleerd is als onderdeel van de Sonic Pi software


In [ ]:
drum = pygame.mixer.Sound("/opt/sonic-pi/etc/samples/drum_tom_mid_hard.wav")
drum.play()

De play() methode van het drum geluid kunnen we in een zelfgemaakte functie stoppen, zodat we ze later kunnen hergebruiken.


In [ ]:
def play():
    print("Drumroffel !")
    drum.play()

nota: de "pin" parameter gebruiken we (nog) niet, maar verderop hebben we ze wel nodig

Laat ons de play functie al eens aanroepen met een willekeurige pin waarde.


In [ ]:
play()

Hoog tijd om een knop aan te sluiten. We gebruiken de BCM nummering, zoals gegraveerd op de case en geprint op het GPIO pinout document.

Gebruik de onderstaande illustratie als leidraad:


In [ ]:
#GPIO bibliotheek inladen
import RPi.GPIO as GPIO
#Methode van pin nummering (BCM) instellen
GPIO.setmode(GPIO.BCM)

#pin 17 activeren als input en de ingebouwde pull-up/pull-down instellen als pull-up
GPIO.setup(17, GPIO.IN, GPIO.PUD_UP)

En met dit alles achter de rug kunnen we Python vragen een event te registreren.

Telkens er een "FALLING" event gedetecteerd wordt op pin 17, moet Python de eerder gecreëerde functie play aanroepen. Bovendien zal Python, ook al gebruiken we het nog niet, het pin nummer van de pin die het event veroorzaakte, meegeven aan de play functie.

Omdat de add_event_detect functie aan de play functie moet kunnen vertellen welke pin het signaal heeft gedetecteerd, voegen we wel eerst nog een pin_number parameter toe aan de play functie:


In [ ]:
def play(pin_number):
    print("Drumroffel !")
    drum.play()

GPIO.add_event_detect(17, GPIO.FALLING, play, 200)

Test maar uit door op de knop te drukken.

Als je tevreden bent van het resultaat, kan je het event weer verwijderen met de volgende functie:


In [ ]:
GPIO.remove_event_detect(17)

Ok, dit was zo leuk dat we er nog wel eentje kunnen doen:


In [ ]:
cymbal = pygame.mixer.Sound("/opt/sonic-pi/etc/samples/drum_cymbal_open.wav")
cymbal.play()

Alleen pakken we het ditmaal lichtjes anders aan. We zullen de geluiden opslaan in een dictionary, waarbij we het pin nummer koppelen aan het geluid dat we willen laten horen:


In [ ]:
sound_pins = {
    17: drum,
    27: cymbal,
}

Eens proberen?


In [ ]:
sound_pins[17].play()

Dat maakt dat we, in plaats van twee functies te maken die we apart registreren, we met één functie kunnen volstaan door gebruik te maken van het feit dat het pin nummer wordt doorgegeven aan de play functie en de dictionary die ons vertelt welk geluid erbij hoort.


In [ ]:
def play(pin):
    sound = sound_pins[pin]
    print("Geluid spelen voor pin %s" % pin)

    sound.play()

Zie hieronder het schema dat nagebouwd kan worden:

Ook het opzetten van de pins en de registratie van een event kunnen we zo "aan de lopende band" doen door ze in een loop te stoppen die één keer uitgevoerd wordt voor elke pin in de dictionary (twee dus, in dit geval, maar het zou een hele piano kunnen zijn)


In [ ]:
for pin in sound_pins:
    GPIO.setup(pin, GPIO.IN, GPIO.PUD_UP)
    GPIO.add_event_detect(pin, GPIO.FALLING, play, 200)

Music time!

probeer maar uit...

En dan kunnen we op dezelfde manier de event registraties weer verwijderen.


In [ ]:
for pin in sound_pins:
    GPIO.remove_event_detect(pin)

In [ ]:
#Alle GPIO instellingen weer opkuisen
GPIO.cleanup()

In [ ]: