Python exemplarisch |
Alle Programme können von hier heruntergeladen werden. |
Sound mit dem Raspberry Pi |
Der Raspberry Pi ist mit einer eingebauten Soundkarte ausgestattet, die Sound über eine Audio-Buchse ausgibt. Sounddateien in verschiedenen Audioformaten (am häufigsten WAV und MP3) können mit vorinstallierten oder zusätzlichen Soundplayern abgespielt werden. Um beispielsweise die Datei mysong.wav abzuspielen, geben Sie in der Konsole den Befehl aplay <mysong.wav> ein. Dabei wird der Song mit dem ALSA-Player (Advanced Linux Sound Architecture) über die eingebaute Soundkarte abgespielt. Die Qualität ist nicht berauschend, so dass es besser ist, einen USB-Soundadapter verwenden, der Raspberry Pi-kompatibel ist. Dazu müssen Sie den standardmässigen Soundport auf die USB-Karte umstellen. (Anleitungen dazu findet man im Internet, leider sind aber die meisten aufgrund von Änderungen in der Linux-Distribution veraltet und funktionieren nicht.) Gehen Sie ausgehend von der aktuellen NOOBS-Distribution wie folgt vor: Edieren Sie die Datei .asoundrc, die Sie im Verzeichnis /home/pi finden. Ändern Sie den Eintrag card 0 auf card 1.
Wir empfehlen, als Soundapplikation SoX (Sound eXchange) zu verwenden, die auch als "Das Schweizer Taschenmesser der Klangverarbeitungsprogramme " bezeichnet wird. SoX ist auf unserer SD-Karten-Distribution vorinstalliert. Um SoX auf einem neuen NOOBS- System zu installieren, schliessen Sie den Raspberry Pi an das Internet an und geben in einem Terminal Folgendes ein: sudo apt-get install sox Jetzt können mit dem Befehl play <mysong.mp3> einen MP3-Song abspielen. Wenn Sie SoX eintippen, sehen Sie alle unterstützten Audio-Formate. (Weitere Informationen finden Sie auf der Website von SoX .) Mit SoX können Sie die Soundkarte softwaremässig on-the-fly wechseln, indem Sie die Umgebungsvariable AUDIODEV auf hw:0 oder hw:1 setzen. Dazu geben Sie in der Kommandozeile ein: AUDIODEV=hw:1 play <mysong.mp3> wobei mit hw:0 oder hw:1 der Soundport gewählt wird (es ist nicht nötig, die Datei .asoundrc zu editieren.) Informationen über die verfügbaren Abspielgeräte erhalten Sie mit aplay -l. Mit amixer können Sie die Eigenschaften der voreingestellten Soundkarte anzeigen. | ||||
Zugriff auf das Sound-System mit Python |
Für das ALSA-Soundsystem wird üblicherweise das vorinstallierte Python-Modul pygame verwendet. Leider unterstützt es nur die eingebaute Soundkarte. Um den USB-Soundadapter mit Python anzusprechen, haben wir eine kleine Python-Klasse SoundPlayer geschrieben, welche die Linux-Befehle für den SoX-Player aufruft. Damit können Sie die Soundkarte softwaremässig auswählen. Die Python-Dokumentation finden Sie hier. |
Experiment 1: Sounddateien mit Python abspielen |
Ziel: Downloaden Sie als erstes die Datei soundplayer.py von hier und kopieren Sie sie in das gleiche Verzeichnis, im dem sich Ihr Programm befindet (üblicherweise /home/scripts). Kopieren Sie dann eine Songdatei, die Sie spielen möchten, in irgendein Verzeichnis (zum Beispiel salza1.wav in /home/pi/sound). Verbinden Sie die Audio-Buchse mit dem Eingang eines beliebigen Audioverstärkers. Programm:[►] # Sound1a.py import time from soundplayer import SoundPlayer # Use device with ID 1 (mostly USB audio adapter) p = SoundPlayer("/home/pi/sound/salza1.wav", 1) print "play for 10 s with volume 0.5" p.play(0.5) # non-blocking, volume = 0.5 print "isPlaying:", p.isPlaying() time.sleep(10) print "pause for 5 s" p.pause() print "isPlaying:", p.isPlaying() time.sleep(5) print "resume for 10 s" p.resume() time.sleep(10) print "stop" p.stop() print "isPlaying:", p.isPlaying() print "done" Bemerkungen: Da das Abspielen eines Sounds in einem eigenen Linux-Prozess erfolgt, spielt die Musik weiter, auch wenn das Python-Programm beendet wird. Um den Linux-Prozess zu stoppen, müssen Sie am Ende des Programms die Funktion stop() aufrufen. Die Funktion isPlaying() gibt True zurück, so lange der Prozess läuft, sie liefert also auch während einer Pause den Wert True. |
Experiment 2: Raspberry Pi als ein 4-Button Music-Player |
Ziel: Zur Steuerung des Players verwenden wir 4 Tastenschalter (Run, Pause, Stop, Select) und implementieren folgende Spezifikationen:
Es wird dringend empfohlen, das Programm als eine Zustandsmaschine zu schreiben. Folgende Zustände werden verwendet:
Programm:[►] # Sound1b.py from soundplayer import SoundPlayer import RPi.GPIO as GPIO import time ''' states: STOPPED : play process terminated PAUSED: play process stopped (playing still underway) PLAYING: play process executing ''' # Button pins, adapt to your configuration P_PLAY = 24 P_PAUSE = 16 P_STOP = 22 P_SELECT = 12 def setup(): GPIO.setmode(GPIO.BOARD) GPIO.setup(P_STOP, GPIO.IN, GPIO.PUD_UP) GPIO.setup(P_PAUSE, GPIO.IN, GPIO.PUD_UP) GPIO.setup(P_PLAY, GPIO.IN, GPIO.PUD_UP) GPIO.setup(P_SELECT, GPIO.IN, GPIO.PUD_UP) setup() nbSongs = 4 songID = 0 p = SoundPlayer("/home/pi/songs/song" + str(songID) + ".mp3", 1) p.play() print "playing, song ID", songID state = "PLAYING" while True: if GPIO.input(P_PAUSE) == GPIO.LOW and state == "PLAYING": state = "PAUSED" print "playing->paused" p.pause() elif GPIO.input(P_PLAY) == GPIO.LOW and state == "STOPPED": state = "PLAYING" print "stopped->playing, song ID", songID p.play() elif GPIO.input(P_PLAY) == GPIO.LOW and state == "PAUSED": state = "PLAYING" print "paused->playing" p.resume() elif GPIO.input(P_STOP) == GPIO.LOW and (state == "PAUSED" or state == "PLAYING"): state = "STOPPED" print "paused/playing->stopped" p.stop() elif (GPIO.input(P_SELECT) == GPIO.LOW and state == "STOPPED") \ or (state == "PLAYING" and not p.isPlaying()): songID += 1 if songID == nbSongs: songID = 0 p = SoundPlayer("/home/pi/songs/song" + str(songID) + ".mp3", 1) print "stopped->playing, song ID", songID p.play() state = "PLAYING" time.sleep(0.1) # Do not waste processor time Bemerkungen: |
Experiment 3: Sinuston-Generator |
Ziel: Für einfache Robotik-Anwendungen werden lediglich bestimmte Signaltöne benötigt. Dazu ist Qualität der internen Soundkarte ausreichend. Die Klasse SoundPlayer enthält die (statische) Funktion playTone(), die einen Ton mit der vorgegebener Frequenz und Dauer abspielt. Im folgenden Beispiel verwenden wir die blockierende Version, um einen Ton nach dem anderen abzuspielen. Dann spielen wir alle drei Töne zusammen und verwenden für die Frequenzen eine Listenotation. Programm:[►] # Sound2a.py from soundplayer import SoundPlayer import time # Sine tone during 0.1 s, blocking, device 0 dev = 0 SoundPlayer.playTone(900, 0.1, True, dev) # 900 Hz SoundPlayer.playTone(800, 0.1, True, dev) # 600 Hz SoundPlayer.playTone(600, 0.1, True, dev) # 600 Hz time.sleep(1) SoundPlayer.playTone([900, 800, 600], 5, True, dev) # 3 tones together print "done" Bemerkungen: Im nächsten Beispiel verwenden wir die nicht-blockierende Version der Funktion playTone(), damit das Programm während dem Abspielen eine LED blinken lassen kann. Programm:[►] # Sound2b.py import RPi.GPIO as GPIO from soundplayer import SoundPlayer import time P_LED = 18 # adapt to your wiring def setup(): GPIO.setmode(GPIO.BOARD) GPIO.setup(P_LED, GPIO.OUT) setup() # Sine of 1000 Hz during 5 s, non-blocking, device 0 SoundPlayer.playTone(1000, 5, False, 0) while SoundPlayer.isPlaying(): GPIO.output(P_LED, GPIO.HIGH) print "on" time.sleep(0.5) GPIO.output(P_LED, GPIO.LOW) print "off" time.sleep(0.5) print "done" |
Experiment 4: Mit einem Mikrofonmodul akustische Ereignis erfassen |
Ziel: Wir verwenden ein Mikrofon als Schallempfänger. Dieses gibt ein analoges Schallsignal (als Spannung) ab. Hier ist aber nicht notwendig ist, das Signal zu digitalisieren und mit dem Raspberry Pi zu analysieren. (Dies ist sowieso wegen des kleinen Spannungspegels und der schnellen Änderung des Signals mit grösseren Schwierigkeiten verbunden.) Es genügt, aus dem analogen Signal ein digitales Signal mit zwei Spannungspegeln LOW/HIGH zu erzeugen, das an einen GPIO-Port angelegt wird. Dabei soll der Wert HIGH sein, wenn das analoge Signal einen bestimmten Pegel (Threshold) überschritten hat. Dies kann elektronisch leicht mit einem Operationsverstärker erreicht werden. Hier wird ein billiges Soundmodul verwendet (z.B. KY-038 gekauft über Ebay oder als Teil eines Arduino Sensorkits).
Das KY-038-Modul ist kein sehr empfindliches Gerät und kann nur sehr laute Geräusche erkennen. Stellen Sie das Potentiometer so ein, dass die eingebaute Status-LED gerade abschaltet. Wenn Sie einen Ton in der Nähe des Mikrofons erzeugen (zum Beispiel indem Sie auf dem Mikrofon tippen), sollte die Status-LED für eine kurze Zeit aufleuchten. Programm:[►] # Sound3a.py # Sound Sensor Module KY-038 # Using GPIO events import RPi.GPIO as GPIO import time P_SOUND = 22 # adapt to your wiring P_LED = 24 # adapt to your wiring def setup(): GPIO.setmode(GPIO.BOARD) GPIO.setup(P_LED, GPIO.OUT) GPIO.output(P_LED, GPIO.LOW) GPIO.setup(P_SOUND, GPIO.IN) GPIO.add_event_detect(P_SOUND, GPIO.BOTH, onButtonEvent) def onButtonEvent(channel): global isOn if GPIO.input(P_SOUND) == GPIO.HIGH: isOn = not isOn if isOn: GPIO.output(P_LED, GPIO.HIGH) else: GPIO.output(P_LED, GPIO.LOW) # Have to wait a while # because event is triggered several times (like button bouncing) time.sleep(0.5) setup() isOn = False while True: time.sleep(0.1) Bemerkungen: |