Pi Radio

Hier ist, wie ich ein Internetradio aus einem Raspberry Pi, einem alten Flachbandfestplattenkabel, einem Kippschalter, zwei Widerständen, zwei LEDs und einem Lötkolben gebaut habe – das Ergebnis ist ein Raspberry Internet Radio. Man kann auch ein altes Radio umbauen und ein Raspberry Pi integrieren und so ein modernes Internetradio zusammenbauen.
Das obige Gehäuse ist nur der Karton, in dem RS-Komponenten den Pi versenden. Es stellte sich heraus, dass es eine natürliche Lösung für alle Komponenten war, die ich brauchte.
Hinweis: Dieses Projekt wurde bereits um 2012 durchgeführt, aber das meiste von dem, was Sie sehen, sollte noch anwendbar sein.

Radio Old School

Warum?

FM-Radio wird irgendwann Geschichte sein und einige Sendungen sind bereits jetzt rein digital. Leider ist DAB-Radio auf Sendung keine Option, wo ich wohne – ich habe es ausprobiert, und es gibt einfach kein Signal hier. Radio über das Internet ist jedoch kein Problem.

Also benutzte ich eine Weile ein Tablett, um Internet-Radio zu hören, aber es war einfach zu viel Mühe: Du musst es einschalten, du musst es freischalten, du musst die Radio-App starten, und die App muss angeklickt werden, um den Sender auszuwählen. Wovon ich träumte, war etwas so Einfaches wie ein physisches FM-Radio: Sie schalten es ein und es beginnt von selbst zu spielen. Der Wechsel zu einem anderen Radiosender sollte mit einem einfachen Tastendruck erfolgen.
Kurz gesagt, ich brauchte etwas, das ich tatsächlich programmieren konnte – der Pi ist großartig dafür – und wenn ich auch eine einfache Hardware anschließen könnte, um es zu steuern, wäre es perfekt. Der Pi hat einen ziemlich großen Satz von I/O-Pins, die Sie direkt an Schalter und LEDs anschließen können. Damit ist es einfach, ein Gerät zu bauen, das eine Benutzeroberfläche hat, die so einfach ist wie ein Autoradio. In Kombination mit einem WiFi-Dongle sollte der Pi perfekt sein, nicht wahr?

Wie ?

Grundeinstellung

Ich habe Debian Wheezy installiert und diese Standardkonfiguration als Ausgangspunkt verwendet.

WiFi

Ich habe einen D-Link Wireless N Nano USB-Adapter, DWA-131, gekauft, der standardmäßig auf dem Pi in Debian Wheezy unterstützt wird.
Um WiFi für einen Start zu konfigurieren, ändern Sie /etc/network/interfaces darauf:
root@raspberrypi:/etc/network# chmod 0600 Schnittstellen
root@raspberrypi:/etc/network# cat interfaces
Auto-Lo

iface lo inet loopback
iface eth0 inet dhcp

auto wlan0
iface wlan0 inet dhcp
wpa-ssid mein Netzwerkname
wpa-psk **************

root@raspberrypi:/etc/network#
Es scheint, dass das zuverlässigste Setup darin besteht, nur mit dem drahtlosen Netz zu booten. Wenn ich sowohl mit verkabeltem als auch mit drahtlosem Netzwerk boote und dann das verkabelte Netzwerk abziehe, ist mein Routing aus – ich kann zum Pi ssh, aber der Pi kann sich nicht ausloggen (?). Nun, das drahtlose Setup ist alles, was ich je benutzen werde.
Die obige Konfiguration funktionierte zunächst einwandfrei. Allerdings verlor ich nach etwa drei Stunden immer wieder die Verbindung. Im Router-Logbuch konnte ich sehen, dass der Pi wieder verbunden wurde und sich nicht mehr im drahtlosen Netzwerk authentifizieren konnte. Dieses Problem ist durch die Verwendung einer statischen IP-Adresse behoben worden. Dies mag ein Problem mit meinem speziellen Router sein, aber das ist zumindest ein Versuch, wenn DHCP für Sie nicht zuverlässig ist. Dies ist die Konfiguration, die ich benutzt habe (mein Router/Zugriffspunkt ist 192.168.0.1):
iface wlan0 inet static
wpa-ssid mein Netzwerkname
wpa-psk ***********************
Adresse 192.168.0.20
Netzmaske 255.255.255.255.255.0
Gateway 192.168.0.1
dns-nameserver <name-server1 IP> <name-server 2 IP>

Den Sound herausholen

Ich habe den VLC Media Player installiert (siehe Update unten):
apt-get install vlc installieren
Als ich es zum ersten Mal ausprobierte, beschwerte sich vlc über „alsa audio output error: cannot commit hardware parameters: Ungültiges Argument“. Anscheinend meldet der Fahrer die Fähigkeiten nicht korrekt – oder das’Plug‘-Gerät wird nicht wie erwartet neu abgetastet, so dieser Beitrag: http://www.raspberrypi.org/phpBB3/viewtopic.php?t=7107&p=121986.
Die Lösung besteht darin, eine ~/.asoundrc-Datei wie unten beschrieben zu erstellen.
pi@raspberrypi ~ $ cat .asoundrc
pcm.!default { default {
Typ hw
Karte 0
}

ctl.!default {
Typ hw
Karte 0
}
pi@raspberrypi ~ $ $
Nun, um Radio Denmark, Programm 1 zu spielen, kann ich einfach den folgenden Konsolenbefehl ausführen – Hinweis: Es ist keine grafische Anmeldung erforderlich, da ich VLC bitte, seine „Dummy“-Schnittstelle mit der Option -I Dummy zu verwenden. Die URL wurde auf der Website von Radio Denmark dr.dk gefunden.
vlc http://live-icy.gss.dr.dk:8000/A/A03H.mp3.m3u -I Dummy
Wenn VLC einen Radiosender abspielt, verbraucht es ca. 25% CPU. Überraschend schwer, aber nicht wirklich beunruhigend.
Update 2015-01-10-10:Ich habe jetzt auf die Wiedergabe von Streams mit mpc/mpd umgestellt. Die CPU-Auslastung ist beim Spielen mit mpc auf etwa 9% gesunken. Vielen Dank an Claus Holmelin Høyer für den Tipp, stattdessen mpc/mpd zu verwenden :-).
Zur Installation von mpc:
apt-get install mpc mpd mpd installieren
Um einen Stream mit mpc abzuspielen, mache ich dies:
mpc-load
mpc play 1 # Spielt einen der geladenen Streams ab. Der erste Stream, der oben geladen wird, ist Nummer 1.
mpc Volumen 100

Bereiten Sie Ihre Lötkolben vor!

Nun, zum größten Teil, zum Spaß: Hardware anschließen! Die GPIO-Pins des Pi sind über einen 26-poligen Stecker zugänglich.
Einer meiner Freunde gab mir ein altes 40-poliges IDE-Flachbandkabel. Es passt gut zu den GPIO-Anschlüssen. Die restlichen 14 unbenutzten Pins lassen das Kabel ein wenig herausstecken, aber es ist nicht schlechter als die SD-Karte, die ebenfalls aus dem Mainboard herausragt.
Die GPIO-Pins 0 und 1 sind standardmäßig für den Eingang mit Pull-up-Widerständen konfiguriert, so dass sie ideal für den Anschluss von Schaltern sind. Ich benutzte einen großen roten Kippschalter, den ich herumliegen hatte. Tatsächlich vereinfacht die Verwendung eines Kippschalters auch die Programmierung, denn das Erkennen, dass die Taste gedrückt wurde, ist nun eine Frage des Vergleichs des aktuellen Zustands mit einem vorherigen Zustand – es ist kein Zeitfenster beteiligt.
Der erste leicht konfigurierbare Ausgangspin ist GPIO 4 auf Pin 7, also habe ich ihn für den Anschluss an eine rote LED verwendet. Eine grüne LED wird an Pin 1 (+3,3V) am GPIO-Anschluss angeschlossen, um anzuzeigen, dass der Pi eingeschaltet ist.
Der Schaltplan ist dann:
GND Pin 6
GPIO0 Pin 3 Durch Umschalter auf GND.
GPIO4 Pin 7 Rote LED, 510 Ohm, zieht 3,1 mA (1,6V Abfall über Widerstand).
+3,3V Pin 1 Grüne LED, 1200 Ohm, zieht 1,1 mA (1,4V Abfall über Widerstand).

Stift

1 ————————-> + Grüne LED — 1200 Ohm –+
|
2 x |
|
3 ————————-> Kippschalter ————-+ |
| |
4 x | |
| |
5 x | |
| |
6 ————————-> GND <——————————+-+-+-+-+
|
7 ————————-> + Rote LED — 510 Ohm —-+
Und so sieht es im wirklichen Leben aus (alle gelben Drähte sind mit Pin 6 verbunden, rote Drähte gehen zu Pin 1, 3 und 7):
Ich habe mich entschieden, die einfache Art des Lesens und Einstellens der Pins zu verwenden – durch Lesen und Schreiben in Gerätedateien in /sys/class/gpio/. Dazu benötigen Sie zunächst Gerätedateien für jeden GPIO-Pin, auf den Sie zugreifen möchten. Gerätedateien werden für einen GPIO-Pin erstellt, indem der Pin wie folgt exportiert wird:
echo „4“ > /sys/class/gpio/export
echo „out“ > /sys/class/gpio/gpio/gpio4/direction
Der erste Befehl weist den GPIO-Treiber an, Gerätedateien für GPIO 4 zu erstellen. Das Verzeichnis /sys/class/gpio/gpio/gpio4/ existiert nun und Sie können den Pin dann so konfigurieren, dass er ein Ausgabepin ist, wie ich es mit dem zweiten Befehl tue, der in die Richtungsgeräte-Datei schreibt. Es gibt eine entsprechende Wert-Gerätedatei, die den Pin-Zustand „0“ oder „1“ anzeigt oder setzt. Sehr einfach zu bedienen, und Sie können sogar von der Kommandozeile aus damit experimentieren.
Ich habe ein Startup-Skript /etc/init.d/init-gpio erstellt, das die GPIO-Pins beim Booten initialisiert und als Boot-Dienst einrichtet.
root@pi-radio:/etc/init.d# cat init-gpio
#! /bin/sh
#### BEGIN INIT INFO
# Provides:          GPIO-Pin-Initialisierung
# Erforderlicher Start: $local_fs
# Required-Stop:

# Standard-Start:     2 3 4 5
# Standard-Stop: 0 1 6
# Kurzbeschreibung: GPIO-Init
# Beschreibung:       GPIO-Pin-Initialisierung für das Pi Radio Gerät.
#### INIT INFO BEENDEN

#
# Autor: Jan Holst Jensen.
#

NAME=“init-gpio“.
SCRIPTNAME=/etc/init.d/$NAME

# LSB log_* Funktionen definieren.
. /lib/lsb/init-funktionen

Fall „$1“ in
Start)
log_daemon_msg „GPIO init“.
# Initialisieren Sie die GPIO-Pins und beginnen Sie mit dem Blinken der roten LED, damit wir das erkennen können.
# der Pi hat damit begonnen, Dienste zu starten.

# GPIO 0 (Eingang standardmäßig) und 4 (als Ausgangspin eingestellt) aktivieren.
echo „0“ > /sys/class/gpio/export

echo „4“ > /sys/class/gpio/export
echo „out“ > /sys/class/gpio/gpio/gpio4/direction

# Rote LED am GPIO4 blinkt. Sobald alle Systeme betriebsbereit sind und das Funkgerät startet,
# die Datei ‚do_blink‘ wird entfernt und dies führt zum Skript’blink_led‘.
# zum Aussteigen.
berühren Sie /home/pi/do_blink
/home/pi/blink_led.sh &

log_end_msg 0

;;
stop|stop|neustart|force-reload|status)
log_daemon_msg „Nur’start‘ wird alles tun“.
log_end_msg 0
;;
*)
echo „Verwendung: $SCRIPTNAME {start|stop|stop|restart|force-reload|status}““. >&2
Ausfahrt 3
;;

esac
root@pi-radio:/etc/init.d#

root@pi-radio:/etc/init.d# chmod +x init-gpio
root@pi-radio:/etc/init.d# update-rc.d -n init-gpio Standardeinstellungen
update-rc.d: Verwendung von abhängigkeitsbasierter Boot-Sequenzierung
insserv: Dienst aktivieren ../init.d/init-gpio -> /etc/init.d/../rc0.d/K01init-gpio
insserv: Dienst aktivieren ../init.d/init-gpio -> /etc/init.d/../rc1.d/K01init-gpio
insserv: Dienst aktivieren ../init.d/init-gpio -> /etc/init.d/../rc2.d/S01init-gpio
insserv: Dienst aktivieren ../init.d/init-gpio -> /etc/init.d/../rc3.d/S01init-gpio
insserv: Dienst aktivieren ../init.d/init-gpio -> /etc/init.d/../rc4.d/S01init-gpio
insserv: Dienst aktivieren ../init.d/init-gpio -> /etc/init.d/../rc5.d/S01init-gpio
insserv: Dienst aktivieren ../init.d/init-gpio -> /etc/init.d/../rc6.d/K01init-gpio
insserv: dryrun, nicht erstellen von .depend.boot,.depend.start und.depend.stop
root@pi-radio:/etc/init.d# update-rc.d init-gpio Standardeinstellungen
update-rc.d: Verwendung von abhängigkeitsbasierter Boot-Sequenzierung
root@pi-radio:/etc/init.d#
Das Skript blink_led.sh, auf das das init-gpio-Skript verweist, lautet wie folgt:
pi@raspberrypi ~ $ cat blink_led.sh
#!/bin/bash/bash

während [ -f /home/pi/do_blink ]
tun
echo „1“ > /sys/class/gpio/gpio/gpio4/value
Schlaf 0,5
echo „0“ > /sys/class/gpio/gpio/gpio4/value
Schlaf 0,5
erledigt
pi@raspberrypi ~ $ $
Es blinkt die rote LED, solange die Datei /home/pi/do_blink existiert.

Die Radio-Control-Software

Das Programm, mit dem wir das Radio über den Druckknopf steuern können, ist ein kleines Python-Skript, das bei jedem Start gestartet wird. Es hat eine konfigurierbare Liste von Funkkanälen (die Kanalliste), die Sie durch Drücken der großen roten Taste (der Kippschalter an GPIO 0 angeschlossen) durchlaufen können. Jedes Mal, wenn Sie die Taste drücken, stoppt das Programm den aktuell wiedergegebenen Kanal (der radio_process – ein Griff zu einem VLC-Prozess), spielt eine kanalspezifische Signatur ab, so dass Sie hören können, welcher Kanal auftaucht, und startet dann VLC mit dem neuen Stream neu.
Das Programm ist /home/pi/radio.py :

Importzeit
Import-Teilprozess

channels = [\
(„P1.wav“, „http://live-icy.gss.dr.dk:8000/A/A03H.mp3.m3u“), \
(„P2.wav“, „http://live-icy.gss.dr.dk:8000/A/A04H.mp3.m3u“) \
]

def get_switch_value():
f = open(„/sys/class/gpio/gpio/gpio0/value“)
Wert = f.read()
f.close()

Rückgabewert[0:1].

def play_channel(idx):
globaler radio_prozess
wenn radio_process <> Keine:
radio_process.terminate()

kanal_signatur = kanäle[idx][0]
url = kanäle[idx][1]

subprocess.call([„/usr/bin/aplay“, „/home/pi/“ + channel_signature]))
radio_process = subprocess.Popen([„/usr/bin/vlc“, url, „-I“, „dummy“]))

####

radio_process = Keine
channel_index = 0
play_channel(channel_index)

latest_switch_value = get_switch_value()

versuche es:
während Wahr:
v = get_switch_value()
# Taste gedrückt: Wechseln Sie zum nächsten Kanal.
wenn v <> latest_switch_value:
print „Taste gedrückt.“
letzter_Schalterwert = v

channel_index = channel_index + 1
if channel_index >= len(channels):
channel_index = 0
play_channel(channel_index)

# Poll-Intervall.
time.sleep(0.1)
außer:
# Keyboard interrupt or other stuff that causes termination –
# jeden laufenden Kindprozess bereinigen.
wenn radio_process <> Keine:
radio_process.terminate()
Die Python-Radiosoftware wird beim Booten gestartet, indem sie in /etc/rc.local direkt vor der letzten Ausfahrt 0 Zeile hinzugefügt wird.
# Start the radio.
su -c „python radio.py &“ – pi
# Entfernen Sie die Datei’do_blink‘, um die rote LED zu stoppen.
# blinkt: Der Bootvorgang ist abgeschlossen.
rm /home/pi/do_blink
Und das ist alles. Schalten Sie den Pi ein und er beginnt, Radio zu spielen. Drücken Sie die Taste und sie wechselt zum nächsten Kanal in der Liste. Einfach und bequem.
Und als Nerd gefällt mir das sehr gut, dass ich in mein Radio schieben kann :-).

Was kommt als nächstes?

Der Pi funktioniert hervorragend als Internetradio, aber natürlich könnte es noch besser sein. Dinge, die ich verbessern möchte:
– Bootzeit – vom Einschalten an dauert es etwa 45 Sekunden, bis der Pi die Kanalsignatur wiedergibt. Das ist ein bisschen zu lang.
– Es wäre schön, wenn VLC mit einem neuen Stream neu gestartet werden könnte, während die Kanalsignatur abgespielt wird. Das würde ein paar Sekunden Totluft eliminieren.
– Die rote LED beginnt erst sehr spät im Bootvorgang zu blinken, so dass sie jetzt nicht mehr so nützlich ist. Aber es hat Spaß gemacht, es zu tun:-).
Bootzeit: Wenn ich das Python-Skript als Dienst gestartet habe, der vom Netzwerk abhängt, könnte es sich ein paar Sekunden lang abschalten, da es dann gestartet werden könnte, sobald das Netzwerk aktiv ist. Das Netzwerk wird jedoch erst 30-35 Sekunden nach dem Start initialisiert. So können dramatischere Beschleunigungen einen angepassten Kernel (?) erfordern – oder vielleicht nur das Optimieren der Initskripte (?).
Mehrere Sounds werden abgespielt: Wenn ich versuche, die Kanalsignatur in einem Hintergrundprozess abzuspielen, um VLC neu starten zu können, während die Signatur abgespielt wird, kann VLC normalerweise die Audioausgabe nicht öffnen, wenn sie an sie herangeht, da das Audiogerät noch von aplay verwendet wird. Es kann einfach darum gehen, mein .asoundrc anders zu konfigurieren, um das Mischen zu ermöglichen.
Die LED blinkt: Wenn ich die rote LED dazu bringen könnte, zu blinken, sobald der Kernel aktiv ist, damit er zeigt, dass der Pi bootet, wäre es schön. Derzeit blinkt sie am Ende des Startvorgangs nur etwa 10 Sekunden lang.