Multiroom-Audio: WLAN-Lautsprecher selber bauen

Wie ich das Thema Multiroom-Audio bei mir umgesetzt habe, habe ich ja hier schon erklärt. In diesem Beitrag möchte ich Euch nun zeigen, wie ich meine WLAN-Lautsprecher selber gebaut habe. Im Grunde ist da auch nicht viel dabei: Wir nutzen idealerweise einen Lautsprecher, den wir noch irgendwo herumfliegen haben und bauen da zwei Netzteile, einen Raspberry Pi, Verstärker und noch ein paar Kleinigkeiten ein. Dann haben wir das Gröbste geschafft.Selbstgebauter WLAN-Lautsprecher

Im Ergebnis erhalten wir dann einen aktiven WLAN-Lautsprecher, der sich per Logitech Media Server und den zugehörigen Apps ansteuern lässt, ein AirPlay-Empfänger für Apple-Geräte und ein DLNA-Renderer für andere Geräte liefert. Außerdem können die Grundfunktionen mit einer IR-Fernbedienung gesteuert werden. Um Stromkosten zu sparen, wird der Verstärker abgeschaltet, wenn er nicht benötigt wird.

Hardware

Material für einen WLAN-Lautsprecher

Beginnen wir mit dem benötigten Material. Das Ganze ist lediglich als Vorschlag zu verstehen und kann nach belieben angepasst werden. Ich habe viel Wert auf die Balance zwischen Preis und Leistung gelegt, immerhin soll der WLAN-Lautsprecher ja auch bezahlbar bleiben. Insbesondere das Kleinmaterial findet sich bestimmt in der ein oder anderen Schublade bei Euch zuhause.

Lautsprecher auna Line 501 HifiRaspberry Pi ZeroPHAT DACSure electronics TDA7498 100W VerstärkerSanDisk Ultra 16GB
WLAN-Stick mit abnehmbarer AntenneAntennenkabel mit RP-SMA-Stecker und RP-SMA-Einbaubuchse2-Kanal-Relaismodul5V-Netzteil24V-Netzteil
C8-EinbaubuchseChinch- und KlinkensteckerPrint-Anschlussklemme RM 5,0mmApple RemoteTSOP 4838 IR-Empfänger

Verstärker

Als ich den ersten WLAN-Lautsprecher gebaut habe, habe ich als Verstärker gleich mehrere TDA7498 100W Stereo Power Amp von Sure Electronics bestellt. Dieses Angebot gibt es jedoch nicht mehr, dafür jede Menge gute Alternativen. Zur Auswahl eines passenden Verstärkers folgende Tipps:

  • Die Angegebenen Leistungen sind in der Regel Spitzenleistungen, die nur bei extremen Spitzen und Lautsprechern mit 4Ω Impedanz erreicht werden.
  • Die tatsächliche Leistung ist auch von der Höhe der Spannung abhängig, mit der der Verstärker betrieben wird. Oft sind Bereiche von 9…30V DC, oder 14…36V DC angegeben. Je höher die Spannung, desto höher die Leistung.
  • Hilfreich ist immer ein Blick ins Datenblatt. Da sind meist Diagramme drin, mit denen man den optimalen Arbeitspunkt bestimmen kann.
  • Der Arbeitspunkt sollte so gewählt werden, dass die Verzerrung (THD) nicht zu hoch ist.
  • Mit der Spannungsversorgung wird der Arbeitspunkt dann festgelegt. Für meinen Verstärker und meine Ansprüche sind 28V optimal.
  • Netzteile, die 28V liefern, gibt es kaum. Man kann jedoch die Ausgangsspannung vieler 24V-Netzteile einstellen. Bei meinem ist die Obergrenze 27,6V. Die habe ich auch eingestellt.

Nach nunmehr über einem Jahr kann ich sagen, dass ich mit den Verstärkern von Sure Electronics sehr zufrieden bin. Es gab bisher keinerlei Ausfälle, Überhitzungen oder sonstige Probleme an meinen WLAN-Lautsprechern. Den Lüfter, der auf dem Kühlkörper montiert ist, hab ich übrigens abgeklemmt. Zum einen ist der recht laut und erzielt innerhalb eines geschlossenen Gehäuses kaum einen Effekt. Zum anderen wird der Verstärker auch nicht übermäßig warm, sodass ich darauf verzichten kann.

Alternatives Material

Ich habe schon verschiedene Komponenten verbaut und manchmal musste ich recht lange nach einer passenden oder preisgünstigen Lösung suchen. Deshalb nachfolgend noch 4 Dinge, die ich im ersten WLAN-Lautsprecher verbaut hatte. Damals noch mit einem Raspberry Pi Modell A. Vielleicht könnt Ihr ja etwas davon gebrauchen.

Lautsprecher zerlegen

Fangen wir also an. Wenn das Material beschafft ist, zerlegen wir den Lautsprecher in sämtliche Einzelteile. Ich habe zudem das Anschlussterminal komplett zerlegt. Darin sollen später Stromanschluss und WLAN-Antenne montiert werden.

Lautsprecher in seine Einzelteile zerlegt

Danach muss man einen Weg finden, wie man die ganzen Einzelteile am besten im Gehäuse unterbringt. Das kann relativ langwierig sein, wenn wenig Platz vorherrscht. Alle Teile müssen so gedreht werden, dass man sie nachher auch noch anschließen kann. Ganz wichtig dabei: man sollte in der Lage sein, die SD-Karte vom Raspberry Pi auszutauschen, ohne alles komplett zerlegen zu müssen.

Bei den von mir verwendeten Teilen ist folgende Anordnung sinnvoll (Gehäuse liegt wie oben abgebildet):

  • Rückwand: Netzteile (links oben und links unten)
  • Linke Seitenwand: Raspberry Pi + PHAT DAC
  • Rechte Seitenwand: Frequenzweiche
  • Unten: Verstärker und Relais-Modul

Einzelteile vorbereiten

Audiokabel löten

Das Audiokabel stellt die Verbindung zwischen der Soundkarte und dem Verstärker her. Wir nehmen zwei Drähte und löten sie zuerst am Chinch-Stecker an. Der Draht des inneren Kontaktes wird dann mit dem innern Kontakt des Klinkensteckers verbunden. Anschließend werden die beiden äußeren miteinander verbunden. Am Klinkenstecker bleibt der Kontakt, der zwischen dem inneren und dem äußeren liegt, frei, da es sich bei diesem WLAN-Lautsprecher um ein reines Mono-Gerät handelt. Sonst müsste man ein Y-Kabel bauen (oder kaufen). Nicht vergessen, die Gehäuse der Stecker über die Drähte zu schieben, bevor der zweite Stecker angelötet wird.

Chinch- und KlinkensteckerChinchstecker lötenKlinkenstecker lötenFertiges Audiokabel

Anschlussterminal

Im Anschlussterminal werden die C8-Buchse für den Stromanschluss, sowie das Antennenkabel montiert. Mit einer RJ45-Kupplung kann man den Lautsprecher auch perfekt für ein Netzwerkkabel vorbereiten. Die Umrisse habe ich auf der Rückseite angezeichnet, mit einem Bohrer in die Ecken gebohrt und den Rest mit Nadelfeilen weggefeilt.

C8-EinbaubuchseAntennenkabel mit RP-SMA-Stecker und RP-SMA-EinbaubuchseAnschlussterminal mit C8-Buchse und Antennenbuchse
RJ45-KupplungAnschlussterminal mit C8-Buchse und RJ45-Kupplung

Wer auf eine richtige Werkstatt verzichten muss und stattdessen alles nur am heimischen Schreibtisch machen kann, dem empfehle ich diesen Mini-Schraubstock.

Frequenzweiche löten

Um Platz im Gehäuse zu schaffen, wird die Frequenzweiche an einer neuen Stelle montiert. Die angelöteten Kabel sind dafür leider etwas zu kurz, daher habe ich die alten Drähte entfernt und neue angelötet. Weiß ist hier die Masse, die farbigen Drähte jeweils das Signal. Braun = Audiosignal vom Verstärker, Grau = Signal zum Tieftöner, Orange = Signal zum Hochtöner.

Frequenzweiche mit den alten DrähtenFrequenzweiche mit neuen, längeren Drähten

Micro-USB-Kabel

Die Seite mit dem normalen USB-Stecker wird abgeschnitten (benötigen wir auch nicht mehr). Vom verbleibenden Kabelende (das mit dem Micro-USB-Stecker) entfernen wir ein Stück von der Ummantelung und schneiden den Schirm, den weißen und den gelben Draht ab. Vom roten und schwarzen Draht wird etwas Isolierung entfernt und Aderendhülsen aufgepresst.

Micro-USB-KabelMicro-USB-Kabel

Sonstiges

Die zwei Stiftleisten werden jeweils auf den Raspberry Pi Zero, sowie den PHAT DAC gelötet. Die zweipolige Anschlussklemme ist für den Verstärker gedacht, der für die Spannungsversorgung nur einen Hohlstecker besitzt. Direkt daneben befinden sich jedoch die Lötpunkte für ein Schraubterminal.

Komponenten einbauen und verkabeln

Wenn die Vorbereitungen abgeschlossen sind, machen wir uns an den Einbau und die Verdrahtung der Komponenten. Wie zu erkennen ist, habe ich die Soundkarte nicht huckepack auf den Raspberry Pi gesetzt, sondern daneben gesetzt beide mit Drähten verbunden. Dies schien mir angesichts dessen, dass noch weitere Komponenten an die GPIO angeschlossen werden müssen, die einfachste Lösung.

Verdrahtung der Komponenten im WLAN-Lautsprecher

Verdrahtung der Komponenten im WLAN-Lautsprecher

Es gilt nun, alle Komponenten im Lautsprechergehäuse einzubauen. Je nach Größe des Gehäuses kann einen das schon zur Verzweiflung bringen. Daher noch ein paar Tipps, wie es etwas einfacher geht:

  • Drähte einseitig anschließen und das jeweils andere Ende frei hängen lassen, bevor man die Komponenten einbaut. So muss man nur das jeweils andere Drahtende innerhalb des Gehäuses anschließen.
  • Komponenten, die im hinteren Teil des Gehäuses montiert werden sollen, zuerst einbauen.
  • Teilweise ist es einfacher, wenn man die Löcher ohne die Komponenten erstmal vorbohrt. Das geht auch mit den Schrauben, mit denen die Teile nachher befestigt werden sollen.
Einbau der Komponenten im WLAN-Lautsprecher (1/6)Einbau der Komponenten im WLAN-Lautsprecher (2/6)Einbau der Komponenten im WLAN-Lautsprecher (3/6)Einbau der Komponenten im WLAN-Lautsprecher (4/6)Einbau der Komponenten im WLAN-Lautsprecher (5/6)Einbau der Komponenten im WLAN-Lautsprecher (6/6)

Der mechanische Teil unseres WLAN-Lautsprechers ist nun weitestgehend fertig. Kommen wir also zur Software.

Software

Image aufspielen

Im Beitrag Raspberry Pi: meine Standardkonfiguration habe ich die schonmal recht ausführlich erläutert beschrieben, wie ich meine Raspberry Pi einrichte. Da der Schwerpunkt hier jedoch auf einem funktionierenden WLAN-Lautsprecher liegt, beschränken wir uns hier auf das Wesentliche und nutzen die Boardmittel.

Statt des offiziellen Images von der Raspberry Pi-Downloadseite verwenden wir hier eines, das den benötigten Player bereits beinhaltet. Es gibt da verschiedene zur Auswahl, die je nach Geschmack und Anspruch gewisse Vorteile bieten.

  • piCorePlayer: Basiert auf Tiny Core Linux und ist extrem schlank und schnell, sehr übersichtlich und Komfortabel, läuft selbst auf der schwächsten Hardware und den ältesten Speicherkarten. Einziger Nachteil für mich: keine python-lirc-Bibliothek verfügbar. Somit funktioniert mein Script mit der Fernbedienung leider nicht. Das Image ist nur 78 MB groß.
  • Max2Play: Basiert auf Raspbian und liefert entsprecht auch alles mit, was man gewöhnt ist. Für verschiedene Soundkarten gibt es auch optimierte Images. Allerdings ist die „beworbene“ Oberfläche meiner Ansicht nach viel zu unübersichtlich, schlecht erklärt, recht durcheinander und keineswegs etwas für Anfänger, die sich überhaupt nicht auskennen. Außerdem muss selbst für recht einfache Dinge eine Lizenz erworben werden.

Die PHAT DAC Soundkarte besitzt den gleichen Soundchip wie die HiFiBerry DAC/DAC+ Light, deshalb verwende ich das für HifiBerry optimierte Image von Max2Play. Da ich keine der sonst angebotenen Features benötige, komme ich auch ohne Lizenz aus.

Wenn der Download abgeschlossen ist, spielen wir das Image auf.

Netzwerk einrichten

Wer wie ich einen Raspberry Pi Zero benutzt, hat nun erstmal das Problem, dass dieser keinen LAN-Port besitzt und WLAN erst noch konfiguriert werden muss. Dafür gibt es verschieden-einfache Wege:

  1. Falls der WLAN-Stick eine WPS-Taste besitzt, kann die WPS-Funktion von Max2Play genutzt werden.
  2. Die SD-Karte in einen normalen Raspberry Pi stecken, diesen per Kabel ins Netzwerk holen, die WLAN-Einstellungen vornehmen, und die Karte dann in den Pi Zero packen.
  3. Den Pi Zero zusammen mit einem USB-Hub, sowie WLAN-Stick, Tastatur und/oder Maus an einen Bildschirm anschließen und die Daten direkt einstellen.
  4. Google bemühen.

Für mich ist Variante 2 die einfachste, und mit der geht es auch weiter.

Die Einstellungen nehmen wir per Weboberfläche vor. Diese ist in der Regel unter max2play.local zu erreichen. Alternativ findet Ihr die IP-Adresse über den Router. Anschließend navigieren wir zum Menüpunkt „WLAN & LAN“, geben SSID und Passwort des Netzwerkes ein, oder nutzen die Scan-Funktion.

Max2Play: WLAN-Einstellungen

Max2Play: WLAN-Einstellungen

Soundkarte einstellen

In dem von mir verwendeten HifiBerry-Image kann man direkt auf der Startseite den entsprechenden Typen der Soundkarte auswählen.

Max2Play: HifiBerry-Karte auswählen

Max2Play: HifiBerry-Karte auswählen

Im Standardimage wird die Soundkarte unter dem Menüpunkt „Raspberry Einstellungen“ ausgewählt, sofern man eine Lizenz besitzt. Besitzt man diese nicht, kann man unter dem Menüpunkt „Audioplayer“ lediglich zwischen den vorkonfigurierten wählen. Alternativ können Soundkarten per Kommandozeile eingestellt werden. Dafür benötigt man keine Lizenz.

$ sudo nano /boot/config.txt

Am Ende der Datei kann per dtoverlay die Soundkarte eingestellt werden. Bei meiner sähe das so aus:

dtoverlay=hifiberry-dac

Playername und Dateisystem

Als nächstes geben wir dem WLAN-Lautsprecher einen vernünftigen Namen, mit dem er dann auch im Logitech Media Server angezeigt wird. Dies geschieht im Menü „Einstellungen / Reboot“. Hier können auch Sprache und Zeitzone eingestellt werden.

Max2Play: Playernamen einstellen

Max2Play: Playernamen einstellen

Beim Benennen des Players wird gleichzeitig auch der Hostname angepasst. Mir persönlich gefällt das nicht so gut, deshalb werde ich diesen später nochmal über die Kommandozeile anpassen.

Dann noch das obligatorische Expandieren des Dateisystems. Die passende Schaltfläche befindet sich auf der gleichen Seite etwas weiter unten.

Max2Play: Dateisystem expandieren

Max2Play: Dateisystem expandieren

Erweiterte Konfiguration & LIRC

Passwort & Hostname

Für die Steuerung unseres WLAN-Lautsprechers per Apple Remote (oder einer anderen Fernbedienung) und das Abschalten des Verstärkers, wenn dieser nicht benötigt wird, müssen wir auf der Kommandozeile noch ein paar Einstellungen vornehmen. Dazu verbinden wir uns per SSH und loggen uns mit dem Benutzernamen pi und dem Passwort raspberry ein.

Optional: Bei Bedarf das Passwort ändern:

$ sudo passwd pi

Optional: Um dem Raspberry Pi einen anderen Hostname zu geben, begeben wir uns über die aktive SSH-Verbindung in die Konfigurationsoberfläche…

$ sudo raspi-config

…wählen 9 Advanced Options -> A2 Hostname und tragen hier den neuen Hostname ein. Wir verlassen die Oberfläche und starten neu.

LIRC installieren & konfigurieren

Über das Thema LIRC, und wie man Python-Scripte mittels Fernbedienung steuert, hatte ich hier schon einmal sehr ausführlich geschrieben. Daher machen wir hier einen Schnelldurchlauf. Zuerst installieren wird LIRC:

$ sudo apt-get update

$ sudo apt-get install lirc python-lirc

Nach Abschluss der Installation machen wir uns an die Konfiguration. Als erstes der „Autostart“ von LIRC.

$ sudo nano /etc/modules

Die markierten Zeilen werden einfach unten angehangen.

# /etc/modules: kernel modules to load at boot time.
#
# This file contains the names of kernel modules that should be loaded
# at boot time, one per line. Lines beginning with "#" are ignored.
# Parameters can be specified after the module name.

lirc_dev
# GPIO in BCM-Zählweise
lirc_rpi gpio_in_pin=23

Auf Zeile 9 geben wir in BCM-Zählweise an, welchen GPIO wir mit LIRC nutzen wollen – also die GPIO-Nummer, nicht die Pin-Nummer. Danach passen wir die Hardware-Konfiguration von LIRC an.

$ sudo nano /etc/lirc/hardware.conf

Hier tragen wir für LIRCD_ARGSDRIVERDEVICE und MODULES die Werte wie abgebildet ein.

# /etc/lirc/hardware.conf
#
# Arguments which will be used when launching lircd
LIRCD_ARGS="--uinput"

#Don't start lircmd even if there seems to be a good config file
#START_LIRCMD=false

#Don't start irexec, even if a good config file seems to exist.
#START_IREXEC=false

#Try to load appropriate kernel modules
LOAD_MODULES=true

# Run "lircd --driver=help" for a list of supported drivers.
DRIVER="default"
# usually /dev/lirc0 is the correct setting for systems using udev
DEVICE="/dev/lirc0"
MODULES="lirc_rpi"

# Default configuration files for your hardware if any
LIRCD_CONF=""
LIRCMD_CONF=""

Zuletzt müssen wir noch einen Eintrag in der Datei /boot/config.txt ergänzen.

$ sudo nano /boot/config.txt

Hier passen wir Zeile 51 wie folgt an:

# Uncomment this to enable the lirc-rpi module
dtoverlay=lirc-rpi,gpio_in_pin=23

Tasten-Mapping & Aktionen

Wer eine andere Fernbedienung als die Apple Remote nutzen möchte, startet den Raspberry Pi jetzt neu und macht an dieser Stelle weiter. Alle mit Apple Remote können mein Tasten-Mapping einfach übernehmen.

$ sudo nano /etc/lirc/lircd.conf

Die Datei befüllen wir, je nach verwendetem IR-Empfänger, mit folgendem Inhalt:

TSOP 31238

# Please make this file available to others
# by sending it to <lirc@bartelmus.de>
#
# this config file was automatically generated
# using lirc-0.9.0-pre1(default) on Tue Aug 18 19:23:09 2015
#
# contributed by
#
# brand:                       /home/pi/lircd.conf
# model no. of remote control:
# devices being controlled by this remote:

begin remote

  name  appleremote
  bits            8
  flags SPACE_ENC|CONST_LENGTH
  eps            30
  aeps          100

  header       9058  4422
  one           624  1595
  zero          624   497
  ptrail        623
  repeat       9058  2194
  pre_data_bits   16
  pre_data       0x77E1
  post_data_bits  8
  post_data      0x4E
  gap          107798
  toggle_bit_mask 0x0

      begin codes
          KEY_UP                   0xD0
          KEY_DOWN                 0xB0
          KEY_LEFT                 0x10
          KEY_RIGHT                0xE0
          KEY_OK                   0xBA 0x20
          KEY_MENU                 0x40
          KEY_PLAYPAUSE            0x7A 0x20
      end codes

end remote
TSOP 4838

# Please make this file available to others
# by sending it to <lirc@bartelmus.de>
#
# this config file was automatically generated
# using lirc-0.9.0-pre1(default) on Sun Oct 16 17:40:15 2016
#
# contributed by
#
# brand:                       /home/pi/lircd.conf
# model no. of remote control:
# devices being controlled by this remote:

begin remote

  name  appleremote
  bits            8
  flags SPACE_ENC|CONST_LENGTH
  eps            30
  aeps          100

  header       9057  4419
  one           600  1616
  zero          600   525
  ptrail        600
  repeat       9058  2190
  pre_data_bits   16
  pre_data       0x77E1
  post_data_bits  8
  post_data      0x4E
  gap          107804
  toggle_bit_mask 0x0

      begin codes
          KEY_UP                   0xD0
          KEY_DOWN                 0xB0
          KEY_LEFT                 0x10
          KEY_RIGHT                0xE0
          KEY_OK                   0xBA 0x20
          KEY_MENU                 0x40
          KEY_PLAYPAUSE            0x7A 0x20
      end codes

end remote


Damit beim Tastendruck auch etwas passiert, werden Aktionen definiert. In unserem Fall wollen wir lediglich die Information, welche Taste gedrückt wurde, per String an unser Steuer-Script übergeben. Dazu erzeugen wir uns die Datei lircrc

$ sudo nano /etc/lirc/lircrc

…und packen folgenden Inhalt rein:

# ~/.lircrc
#
# button: Name der Taster (wie angelernt)
# prog:   Ziel, wohin die Information übergeben werden soll (Socket oder Programm)
# config: Übergebener String

# Apple Remote
# KEY_UP
# KEY_DOWN
# KEY_LEFT
# KEY_RIGHT
# KEY_OK
# KEY_MENU
# KEY_PLAYPAUSE

begin
    button = KEY_UP
    prog = appleremote
    config = KEY_UP
end

begin
    button = KEY_DOWN
    prog = appleremote
    config = KEY_DOWN
end

begin
    button = KEY_LEFT
    prog = appleremote
    config = KEY_LEFT
end

begin
    button = KEY_RIGHT
    prog = appleremote
    config = KEY_RIGHT
end

begin
    button = KEY_OK
    prog = appleremote
    config = KEY_OK
end

begin
    button = KEY_MENU
    prog = appleremote
    config = KEY_MENU
end

begin
    button = KEY_PLAYPAUSE
    prog = appleremote
    config = KEY_PLAYPAUSE
end

Damit ist LIRC fertig eingerichtet und der WLAN-Lautsprecher soweit vorbereitet. Sollte es später irgendwelche Probleme mit LIRC geben, findet Ihr in oben genanntem Beitrag auch Möglichkeiten, die Teilschritte einzeln zu testen.

Zum Abschluss starten wir den Raspberry Pi neu.

Steuerscript für den WLAN-Lautsprecher

Damit die Fernbedienung den WLAN-Lautsprecher steuern kann und der Verstärker beim Abspielen von Musik auch eingeschaltet wird, benötigen wir noch ein Script, das mit dem Server kommuniziert und die entsprechenden Informationen besorgt, bzw. weiterleitet. Eins auf diesen Lautsprecher zugeschnittenes findet Ihr unten. Vom Grunde her könnt Ihr das Script auch 1:1 übernehmen.

Wir erzeugen also die Script-Datei…

$ nano ~/squeezebox-control.py

…und packen folgenden Inhalt hinein:

#!/usr/bin/env python
#coding: utf-8 

####################################################################
# squeezebox-control.py
# Script zur Steuerung eines WLAN-Lautsprechers
# von Sebastian Köhler - https://indibit.de
#
# LETZTE ÄNDERUNG:	17.04.2016
####################################################################

import fcntl, socket, struct	# für MAC-Adresse
import lirc
import RPi.GPIO as GPIO
import sys
import telnetlib
import thread
import time

# ----------------------------------------------------------------------------
#  Konfiguration
# ----------------------------------------------------------------------------
HOST            = "192.168.243.5"   # IP-Adresse des LMS
PORT            = "9090"            # CLI-Port des LMS
OFF_DELAY       = 180               # Verstärker-Abschalt-Verzögerung (in Sekunden)
VOL_NORM        = 50                # Lautstärke, die nach beim Einschalten eingestellt werden soll

# ----------------------------------------------------------------------------
#  sonstige Variablen
# ----------------------------------------------------------------------------
mac = ''       # MAC-Adresse
status = ''    # Status des Players
tn = ''        # Telnet-Verbindung
lastPlay = 0   # Zeit, wann der Player das letzte Mal gespielt hat

# ----------------------------------------------------------------------------
#  MAC-Adresse auslesen
# ----------------------------------------------------------------------------
def getMAC(ifname):
	s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
	info = fcntl.ioctl(s.fileno(), 0x8927,  struct.pack('256s', ifname[:15]))
	return '%3A'.join(['%02x' % ord(char) for char in info[18:24]])

# ----------------------------------------------------------------------------
#  Telnet-Verbindung herstellen
# ----------------------------------------------------------------------------
def tn_connect():
	global tn
	try:
		tn = telnetlib.Telnet(HOST,PORT)
		player("startup")
	except:
		time.sleep(10)

# ----------------------------------------------------------------------------
#  WLAN-Lautsprecher bei Start initialisieren
# ----------------------------------------------------------------------------
def startup():
	setGPIO("startup","")
	tn_connect()

# ----------------------------------------------------------------------------
#  Fernbedienung/LIRC abfragen
# ----------------------------------------------------------------------------
def remote():
	while True:
		try:
			codeIR = lirc.nextcode()
			if codeIR != []:
				if codeIR[0] == 'KEY_UP':
					player('vol_up')			
				elif codeIR[0] == 'KEY_DOWN':
					player('vol_down')
				elif codeIR[0] == 'KEY_LEFT':
					player('back')
				elif codeIR[0] == 'KEY_RIGHT':
					player('next')
				elif codeIR[0] == 'KEY_OK':
					pass
				elif codeIR[0] == 'KEY_MENU':
					player('playlist')
				elif codeIR[0] == 'KEY_PLAYPAUSE':
					if status == "play":
						player('pause')
					else:
						player('play')
			time.sleep(0.05)
		except:
			time.sleep(0.1)
	
# ----------------------------------------------------------------------------
#  Befehle senden, Status abfragen
# ----------------------------------------------------------------------------
def player(cmd):
	p0 = ""
	p1 = ""
	p2 = ""
	if cmd == "startup":
		try:
			player("stop")
			#tn.write("subscribe play,pause,stop,playlist\r")
			tn.write(mac + " mode ?\r")
			resetVol()
		except (EOFError, socket.error):
			tn_connect()
			
	else:
		if cmd == "play":               # Wiedergabe
			p0 = "play"
		elif cmd == "pause":            # Pause
			p0 = "pause"
		elif cmd == "stop":             # Stop
			p0 = "stop"
		elif cmd == "back":             # Titel zurück
			p0 = "playlist"
			p1 = "index"
			p2 = "-1"
		elif cmd == "next":             # Titel überspringen
			p0 = "playlist"
			p1 = "index"
			p2 = "%2B1"
		elif cmd == "vol_up":           # Lauter
			p0 = "mixer"
			p1 = "volume"
			p2 = "%2B5"
		elif cmd == "vol_down":         # Leiser
			p0 = "mixer"
			p1 = "volume"
			p2 = "-5"
		elif cmd == "playlist":         # Playlist abspielen
			p0 = "playlist"
			p1 = "play"
			p2 = "smooth_jazz.m3u"
		else:
			p0 = ""
			p1 = ""
			p2 = ""

		if p0 != "":
			try:
				tn.write(mac + " " + p0 + " " + p1 + " " + p2 + "\r")
			except (EOFError, socket.error):
				tn_connect()
	
	p0 = ""
	p1 = ""
	p2 = ""

def getStatus():
	while True:
		global status
		try:
			tn.write(mac + " mode ?\r")
			q = tn.read_until('\r')
			s = q.split('\r')[0].split(' ')
			if s:
				if s[0] == mac:

					if s[1] == "mode":
						status = s[2]

		except (EOFError, socket.error):
			tn_connect()
		except KeyboardInterrupt:
			getOut()
		time.sleep(0.1)

# ----------------------------------------------------------------------------
#  Verstärker am WLAN-Lautsprecher ein-/ausschalten
# ----------------------------------------------------------------------------
def ampOnOff():
	global lastPlay
	if status == "play":
		setGPIO("amp","on")
		lastPlay = time.time()
	else:
		if time.time() - lastPlay >= OFF_DELAY:
			if status == "pause":
				resetVol()
				player("stop")
			setGPIO("amp","off")

def setGPIO(channel,state):
	amp = 22
	on  = GPIO.LOW
	off = GPIO.HIGH

	if channel == "startup":
		GPIO.output(22, GPIO.HIGH)
		#GPIO.output(24, GPIO.HIGH)
	else:
		if (channel in locals()) and (state in locals()):
			GPIO.output(locals()[channel], locals()[state])

# ----------------------------------------------------------------------------
#  Standard-Lautstärke setzen
# ----------------------------------------------------------------------------
def resetVol():
	try:
		tn.write(mac + " mixer volume " + str(VOL_NORM) + " \r")
	except (EOFError, socket.error):
		tn_connect()
	
# ----------------------------------------------------------------------------
#  Script beenden
# ----------------------------------------------------------------------------
def getOut():
	GPIO.cleanup()
	sys.exit(0)

# ----------------------------------------------------------------------------
#  Hauptprogramm
# ----------------------------------------------------------------------------
if __name__ == '__main__':
	#GPIO.setwarnings(False)
	GPIO.setmode(GPIO.BOARD)                            # Zählweise der Pins festlegen
	GPIO.setup(22, GPIO.OUT)                            # Pin 22 (GPIO 25) = Verstärker-Relais 1
	#GPIO.setup(24, GPIO.OUT)                           # Pin 24 (GPIO  8) = Verstärker-Relais 2
	sockid=lirc.init("appleremote", blocking = False)   # Fernbedienung einbinden

	mac = getMAC('wlan0')
	startup()

	thread.start_new_thread(getStatus,())
	thread.start_new_thread(remote,())

	while True:
		try:
			ampOnOff()
			n = True
			time.sleep(0.1)
		except KeyboardInterrupt:
			getOut()

Auf den Zeilen 23 bis 26, und 133 müsst Ihr die für Euch zutreffenden Daten eintragen.

  • Zeile 23 (HOST): Die IP-Adresse des Computers/NAS ein, auf dem der Logitech Media Server läuft.
  • Zeile 24 (PORT): Der Port für die Steuerung per Telnet. Den Findet Ihr so heraus: Im LMS -> Einstellungen -> Erweitert -> Befehlszeilenschnittstelle (CLI) [oben links im Dropdown-Menü auswählen].
  • Zeile 25 (OFF_DELAY): Zeit, die verstreichen muss, bis der Verstärker abgeschaltet wird, wenn die Wiedergabe pausiert wird.
  • Zeile 26 (VOL_NORM): Lautstärke die automatisch eingestellt wird, wenn der Verstärker sich ausschaltet (STOP) oder bei Neustart des Raspberry Pi, bzw. LMS
  • Zeile 133: Hier könnt Ihr eine Playlist festlegen, die beim Drücken auf die Menü-Taste an der Apple-Remote abgespielt wird.

Die Tasten auf der Fernbedienung sind in diesem Script wie folgt belegt:

  • hoch/runter: lauter/leiser
  • links/rechts: nächster/vorheriger Titel
  • Mitte: nicht belegt
  • Menü: spielt voreingestellte Playlist ab
  • Play/Pause: befindet sich der Player im Ruhezustand, wird das abgespielt, was zuletzt wiedergegeben wurde. Pause pausiert, anschließend Play setzt die Wiedergabe fort

Das Script muss noch ausführbar gemacht werden:

$ chmod +x ~/squeezebox-control.py

Autostart

Damit alles auch nach einem Stromausfall oder Neustart wie gewünscht von alleine läuft, muss das Script noch automatisch gestartet werden. Im Blog von Stephen C. Phillips habe ich eine tolle Möglichkeit gefunden, das Script als Dienst laufen zu lassen.

Dazu legen wir zuerst das Start-/Stopp-Script an…

$ sudo nano /etc/init.d/squeezebox-control

… und befüllen es mit folgendem Inhalt:

#!/bin/sh

### BEGIN INIT INFO
# Provides:          myservice
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Squeezebox-control
# Description:       Reads IR input and controls GPIO for switching the AMP
### END INIT INFO

# Change the next 3 lines to suit where you install your script and what you want to call it
DIR=/home/pi
DAEMON=$DIR/squeezebox-control.py
DAEMON_NAME=squeezebox-control

# Add any command line options for your daemon here
DAEMON_OPTS=""

# This next line determines what user the script runs as.
# Root generally not recommended but necessary if you are using the Raspberry Pi GPIO from Python.
DAEMON_USER=root

# The process ID of the script when it runs is stored here:
PIDFILE=/var/run/$DAEMON_NAME.pid

. /lib/lsb/init-functions

do_start () {
    log_daemon_msg "Starting system $DAEMON_NAME daemon"
    start-stop-daemon --start --background --pidfile $PIDFILE --make-pidfile --user $DAEMON_USER --chuid $DAEMON_USER --startas $DAEMON -- $DAEMON_OPTS
    log_end_msg $?
}
do_stop () {
    log_daemon_msg "Stopping system $DAEMON_NAME daemon"
    start-stop-daemon --stop --pidfile $PIDFILE --retry 10
    log_end_msg $?
}

case "$1" in

    start|stop)
        do_${1}
        ;;

    restart|reload|force-reload)
        do_stop
        do_start
        ;;

    status)
        status_of_proc "$DAEMON_NAME" "$DAEMON" && exit 0 || exit $?
        ;;

    *)
        echo "Usage: /etc/init.d/$DAEMON_NAME {start|stop|restart|status}"
        exit 1
        ;;

esac
exit 0

Auf den Zeilen 14 und 15 könnt Ihr Pfad und Dateinamen anpassen, falls Ihr die anders gewählt habt, als ich vorgeschlagen habe.

Jetzt muss das Script noch ausführbar gemacht werden…

$ sudo chmod +x /etc/init.d/squeezebox-control

… und dem System bekannt gemacht werden, dass das neue Start-/Stopp-Script existiert und verarbeitet werden soll:

$ sudo update-rc.d squeezebox-control defaults

Das Ganze kann nun wie folgt gesteuert werden:

Status abfragen$ /etc/init.d/squeezebox-control status
Script starten$ sudo /etc/init.d/squeezebox-control start
Script stoppen$ sudo /etc/init.d/squeezebox-control stop
Script neustarten$ sudo /etc/init.d/squeezebox-control restart

Nach einem letzten Neustart ist der WLAN-Lautsprecher nun vollständig betriebsbereit. Viel Spaß  😎

Sebastian

Sebastian

...ist staatlich geprüfter Techniker für Elektrotechnik, Schwerpunkt Prozessautomatisierung und Energietechnik. Die Themen Automatisierung und Programmierung haben es ihm besonders angetan.
Außerdem ist er für jede technische Spielerei zu haben 😉
Sebastian

Hinterlasse einen Kommentar

71 Kommentare auf "Multiroom-Audio: WLAN-Lautsprecher selber bauen"

Benachrichtige mich zu:
avatar
Sebastian
Gast
Sebastian

Hi Sebastian,

Prima Anleitung! Mich würde der energieverbrauch interessieren wenn gerade kein stream übertragen wird, also nur das Netzteil den raspizero + phatdac im wartemodus betreibt.

Gruß Basti

Sebastian
Gast
Sebastian

Ah, das geht ja. Hatte überlegt das ganze per wifi Relais schaltbar zu machen, aber viel mehr holt man damit auch nicht mehr raus. Danke fürs nachmessen!

Sebastian
Gast
Sebastian

Nochmal ne Frage zum 24v Netzteil. Das von dir verwendete hat nur ca. 25 Watt wenn ich das richtig auf dem Bild sehe. Der Lautsprecher bei vollast aber 50watt. Wie bist du jetzt auf die Leistung beim Netzteil gekommen? Hängt eher vom verstärker ab, oder? Hab mir einen verstärker mit 2×50 Watt ausgesucht, da ich gerne den zweiten Lautsprecher mit nutzen möchte für echtes stereo. Allerdings bin ich mir nicht sicher wie ich das Netzteil dafür dimensionieren sollte. Irgendwelche tipps? Bei nem 100 Watt Netzteil ist das dann auch ein ganz schönes Trumm.

Grüße
P.S. Gibt’s einen besonderen Grund für das doppel Relais Modul?

Sebastian
Gast
Sebastian

Ah, ok, das ist schon mal ein Guter Ratschlag. Vielleicht teste ich den Verstärker erstmal mit nem labornetzteil und prüfe die maximalen Leistungspeaks. Wobei ich noch nicht genau weiß wie ich das messen soll. Digital Multimeter müsste da nen Spitzenwert merken. Sowas kann meins nur nicht.
Ich denke es macht sicher auch Sinn einen Elko mit 35V und 1000uF am Netzteil Ausgang parallel zu schließen um das Netzteil bei Spitzen zu entlasten. Oder nicht so viel überlegen und einfach über den Daumen peilen 🙂

Jens
Gast
Jens

Hallo,
das ist ja eine super Anleitung. Da ich mich mit dem Thema schon länger beschäftige, leider aber ein ziemlich Unerfahren in dem Thema bin, hat mir vor allem die Ausführlichkeit besonders gut gefallen.
Ich habe ein Frage zu den Boxen. Gab es für die verwendeten Boxen einen bestimmten Grund. Ich habe bei mir noch 2 ältere 2 Wege Boxen, für die ich derzeit keine Verwendung habe. Könnte ich diese auch nehmen?
Danke für die Hilfe

Jens

Jens
Gast
Jens

Hallo Sebastian,
vielen Dank für die schnelle Antwort. Hast du schon Erfahrungen mit dem Betreiben der Boxen im Bad? Muß man da wegen der manchmal auftretenden Feuchtigkeit mehr Vorsichtsmaßnahmen treffen?

Jens
Gast
Jens

Hallo Sebastian,
vielen Dank für die schnellen Antworten. Ich bin gerade dabei meine Einkaufsliste zusammen zu stellen. Habe aber ein bisschen Probleme mit dem Verstärker und dem Sound Modul.Das Phat Dac habe ich nicht gefunden. Ich denke, ich kann da auch auf die HifiBerry Dac+ um switchen, wobei die preislich sicher deutlich höher liegt. Das Bundle von Pimoroni gibt es zu mindestens bei Amazon gerade nicht. Beim Verstärker weis ich gar nicht so recht. Da gibt es so viele. Und an Hand von Parameter – keine Ahnung. Ich habe jetzt einmal den „TDA7498 Leistungsverstaerkermodul – SODIAL(R)TDA7498 Binaural Stereo 2x100W High Power digital“ oder den „Sure Electronics 2×100 Watt TRIPATH Digitalverstärker Amplifier Board – STA508 „, jeweils bei Amazon in die engere Wahl gezogen. Wobei ich nicht weis ob sich der teurere lohnt. Hast Du einen Tipp wo man den Raspberry Zero gut bekommen kann?

Jens
Gast
Jens

Hallo Sebastian,
vielen Dank für Deine Hilfe. Dann werde ich jetzt mal shoppen gehen und dann mal schauen wie es klappt. Wenn es passt würde ich zur gegebenen Zeit Dioch weiter als Informationsquelle anzapfen. 😉

Jens
Gast
Jens

Hallo Sebastian,
noch mal eine Frage zu dem Verstärker. Reicht an sich nicht auch der
2 x 25 Watt Klasse D Audioverstärkerplatine – TDA7492
für einen kleineren Raum. 100W klingt immer so viel. 😉

Jens
Gast
Jens

Hallo Sebastian,
ich war in den letzten Tagen zeimlich viel shoppen. Leider ist aber noch nicht alles angekommen. Trotzdem habe ich ein bissel experimentiert.Und da sind doch glatt neue Fragen und Probleme aufgetreten. Mein NAS ist eine Buffalo LS-WXL. Auf der ist schon der Squeezebox-Server. Leider aber nicht in der aktuellen Variante. Laut Auskunft der Hotline geht es auch nicht diesen selbst zu aktualisieren. Keine Ahnung ob das was ausmacht. Ich habe Version 7.5.1. Nur schlecht ist, daß mir immer angezeigt wird, daß er im abgesicherten Modus läuft. Hast Du damit Erfahrungen?
Das andere Frage ist. Ich möchte auch meine Musik vom NAS auf meine etwas ältere Anlage bringen. Wo, oder besser an welchen Parametern kann ich sehen ob die Eingänge das überhaupt hergeben. Mein receiver ist von Technics. Ein: SA -DX930. Man kann, zu mindestens laut Bedienungsanleitung, analoge und digitale Geräte anschließen. Dann sollte das doch eigentlich gehen oder?

Jens
Gast
Jens

Hi Sebastian,
Zugriff per SSH bedeutet doch aber, daß man die Zugangsdaten weiß. Ich komme zwar per putty hin, scheiter dann aber an diesen Daten. (die ich nicht kenne)
Ja er hat Chinch Eingänge. Ich habe gestern mal versucht. Leider aber kam noch kein Ton raus. Meine Kombi:Raspberry 3 plus Hifiberry + zero plus Volumio.

Jens
Gast
Jens

Hallo Sebastian,
nochmal wegen dem LMS auf den Raspberry. Ich habe das mal versucht und noch nicht ganz hinbekommen. Falls das aber mal klappen sollte und der Pi dann mein LMS ist mit den entsprechenden Freigaben zu meinem NAS, muß dieser dann auch immer an sein. ist das richtig?

Jens
Gast
Jens

Habe jetzt den LMS auf dem PI installiert.Wie mache ich das mit dem Einbinden der Dateifreigabe des NAS? NAS und PI sind im gleichen Netz.
Leider wird auch meine Hifiberry DAC+ zero nicht erkannt. Ich habe sie auf die Steckleiste gesteckt. Aber irgendwie wird sie nicht erkannt. Muss ich da noch etwas tun?

Jens
Gast
Jens

Hallo Sebastian,
noch eine dumme Frage. Von wo genau gehen die Kabel zum Lautsprecher weg?

Sebastian
Gast
Sebastian

Vom Verstärker-Ausgang zur Frequenzweiche (falls vorhanden), und von da zu den Lautsprechern.

Jens
Gast
Jens

Hallo Sebastian,
dank Deiner guten Anleitung habe ich heute meinen ersten Wlan-Lautsprecher fertig bekommen. Es sind aber doch ein paar kleine Fragen offen.
Die Einbindung der Apple Remote hat noch nicht richtig geklappt. Das Komische dabei. Ich habe es vorher entsprechend Deiner Extra Anleitung getestet und da hat es meiner Meinung auch geklappt.Also zumindestens habe ich bei dem Test im Terminal die „Tastensignale“ gesehen.
Ich werde einfach noch mal alles von vorne eingeben. Vlleicht klappt es ja dann. Aber zu den Einstellungen noch ein Frage. Gibt es die Möglichkeit mit der Remote sowas wie ein richtiges „aus“ oder „an“ zu erreichen? Oder ist das schon und ich habe es nur übersehen.
Ach und wegen dem Lüfter vom Verstärker. Wenn ich das richtig in Erinnerung habe, hattest Du den abgeklemmt. Hast Du damit schon Erfahrungen gemacht ob das so passt?

Jens
Gast
Jens

Okay, das ist gut zu wissen. Naja und wegen der Fernbedienung. Ich hatte so gedacht, daß mit der auch den Lautsprecher aus oder anschalten kann.

Jens
Gast
Jens

Ja hast recht. Ich hatte da einen falschen Gedankengang. Aber leider bekomme ich die Apple Remote nicht zum Laufen. Ich habe jetzt auch deine Extra Anleitung mal ausprobiert, dort auch die Tasten angelernt und auch die Dateien aus der Anleitung hier, noch mal geprüft. Mit dem Ipad kann ich den Lautsprecher prima bedienen, aber mit der Fernbedienung geht gar nichts. Wo ist da mein Fehler?

Jens
Gast
Jens

Ich habe es. Sorry…ein Kabel war um eine Stelle falsch gesteckt.
Danke noch mal für die prima Anleitung.

Jens
Gast
Jens

Hallo Sebastian,
noch mal eine Frage zu den Boxen. Würde es auch gehen das an und ausschalten über einen Bewegungs Melder zu steuern?

Jens
Gast
Jens

Hallo Sebastian,
okay, ich glaube dann frage ich noch mal wenn ich das Teil zusammengebaut habe. Eine Frage habe ich gleich noch. Und zwar wegen der „Playliste“ welche abgespielt wenn ich Menü drücke. Aber irgendwie fehlt mir da noch das Verständnis. Ich habe gesehen, daß Du eine Playliste in die „squeezebox-control.py – Datei“ eingetragen hast. Aber wo muß die liegen? und womit hast Du die erstellt? Ich habe versucht eine Playlist im LMS zu erstellen und auch abzuspeichern. as hat auch geklappt. Kann die auch abspielen wenn ich Sie direkt in der Android-App unter „Wiedergabelisten“ anwähle. Aber wahrscheinlich sind das 2 verschiedene Dinge die „Wiedergabelisten“ in der APP und die Playlist in der squeezebox-control. Aber kanns Du mir sagen wie ich die zusammenbringen kann?

Jens
Gast
Jens

Und muß ich dann in die „control“ den genauen Pfad angeben? Weil nur mit dem Namen, welchen ich beim erstellen der playlist im LMS vergeben habe, konnte mein Player nix anfangen.

Jens
Gast
Jens

Sorry, ich muß noch mal fragen.Ich erstelle im LMS eine Wiedergabeliste in dem ich Lieder aussuche und dann im rechten Fenster des LMS unten auf „Speichern“ drücke.Den vergebenen Namen(ohne Freizeichen) gebe ich auch noch squeezebox-control unter dem Punkt „Befehle senden…“ „p2“ den Namen an. Ich kann die Wiedergabeliste über meinen PC im Webbrowser und auch über die App auswählen und abspielen. Wenn ich aber die Menütaste auf der Remote drücke kommt immer „unbekannstes Lied“. Hast Du eine Idee?
Mit dem Telnet – habe ich leider keine Ahnung und mit der englischen Hilfe im LMS bin ich etwas überfordert.

Jens
Gast
Jens

Hallo Sebastian,
ich beobachte bei meinem laufenden WlanLautsprecher zur Zeit das Problem, daß er, wenn er etwas länger nicht in Betrieb war (über Nacht zum Beispiel), Probleme macht wieder aktiv zu sein. Auf der App sehe ich zwar das der Player läuft aber es kommt kein Ton. So nehme ich an, daß der Verstärker nicht aktiviert wird. Hast Du auch solcher Erfahrungen gemacht? Woran kann das liegen?

Jens
Gast
Jens

Okay, jetzt bin ich überfordert. Ich habe das Script 1 zu 1 von Dir übernommen. Außer natürlich meine pers. Daten. Also gehe ich mal davon aus, daß ich es auch so wie im Beitrag starte.Wo und wie müsste ich da nachschauen?

Jens
Gast
Jens

Hallo Sebastian,
ich habe noch mal geschaut. Ich habe den Script so übernommen wie du ihn in dieser Anleitung hier geschrieben hast. Die Probleme treten nur auf wenn der Verstärker aus war, also nach den 180 Sekunden (was bei mir nur 120 sind).(Die kleine Lampe am Relais ist dann auch aus.) Ich gehe dann mal davon aus, daß zu diesen Zeitpunkt das Script nicht mehr läuft.
Dann verzögert sich das anschalten erheblich. Teilweise können das sogar Minuten sein. Wenn er dann einmal an ist, reagiert er fast immer sofort auf den Tastendruck an der Remote oder der Handy APP.
Ich würde mich freuen wenn mir da weiter helfen könntest.
Gruß Jens

Jens
Gast
Jens

Ich finde, die von dir geplante Variante auch richtig gut so.Der Verstärker muß ja wirklich nicht immer an sein. Ich finde aber einfach nicht den Fehler. Liegt sicher auch an den nicht vorhandenen Programierkenntnissen. (Auch wenn ich mich damit beschäftige – Aber Doityurself dauert halt länger)
Es ist bei mir so, daß, so bald der Verstärker durch das Script ausgeschaltet wurde, das Anschalten sehr lange (teilweise 5 Minuten und länger) dauert. Wie gesagt, mir fehlen leider die Kenntnisse das in der Software zu finden. Und Ferndiagnosen sind immer schwierig. Ist mir klar. Aber vielleicht kann ich Dir irgendetwas zusenden (Protokoll, Logdatei oder…) und du kannst das auswerten.
Vielleicht geht es aber auch anders. Was ich mir noch gedacht habe.
Die „OK“ Taste ist ja derzeit nicht in Benutzung. Kann diese nicht für das reine Anschalten des Verstärkers genutzt werden? Ausschalten tut er sich ja zeitgesteuert – wie eingestellt. Ich habe mal versucht Teile des Script aus deinem anderen Tutorial –
Raspberry Pi: Mit Apple Remote+LIRC Python-Scripte steuern – zu verwenden. War da aber nicht erfolgreich.
Gruß Jens

Jens
Gast
Jens

Der Fehler tritt auf wenn der Lautsprecher längere Zeit nicht in Betrieb war. Ich habe mal versucht Zeiten zu stoppen. Also bei 4 – 6 Minuten aus, ging er wieder recht flott an.Bei um die 10 Minuten aus , hat er etwas mehr 7 Minuten gebraucht.
Mit dem „Extra-Anschalten“ würde mich in der Situation erst mal gar nicht so stören. Aber geht das mit nur einer Taste? Obwohl das Ausschalten wäre ja über das vorhandene Script geregelt.Man müßte dafür ein eigenes Script schreiben oder?

Walter
Gast
Walter

Habe einige Beiträge hier verfolgt. Super dokumentiert, vielen Dank.

Eine generelle Frage habe ich noch: was ist der Unterschied zw Eingang und Ausgang bei den GPIOs?

Herbert
Gast
Herbert

Hallo Sebastian,
tolle Anleitung. Ich möchte das gerne auf meine Stereo- Standboxen übertragen, also das ganze zweimal aufbauen. Wie bekomme ich dann beim Streamen die Kanaltrennung hin?

Herbert
Gast
Herbert

Klasse,ddas hört sich richtig gut an. Die zweite Variante käme mir dann entgegen, damit ich keine Kabel legen muss. Ich habe zwei hochwertige Boxen, die ich gerne umrüsten möchte. Wenn ich das Ganze richtig verstanden habe, benötige ich die von Dir aufgeführte Hardware dann zweimal. Geht das ganze auch mit eine PI 3, der schon ein wlan-Modul eingebaut hat?
Danke für Deinen Einsatz
Herbert

Herbert
Gast
Herbert

ok, verstanden ;-))

Markus
Gast
Markus

Hallo Sebastian,

als erstes, DIY Projekt!

Du hast mir tolle Informationen zum Selbstbau gegeben.
Ich würde gerne wissen ob es keine Probleme gibt, den Verstärker nur mit einem Kanal zu benutzen.
Ich möchte das Prinzip gerne für ein Radio am Arbeitsplatz (keine Netzwerkverbindung möglich) zu benutzen
Als Empfänger dachte ich an einen DVB-T-Stick. Damit ist es möglich UKW-Sender zu empfangen.
Hast Du eine Idee wie es möglich ist, diesen Sender im Raspberry Pi über Verstärker auszugeben?

Wäre schön wenn du mir weiterhelfen könntest.

P.S. Ach ja, mit welcher Software hast du das Bild 29 erstellt. Würde mich mal interessieren…

Gruß Markus

Markus
Gast
Markus

Hallo Sebastian,
es sollte eigendlich heißen, „Tolles DIY Projekt!“ Sorry

Danke für die Info zum Verstärker. Das hilft mir weiter.

Markus

Markus
Gast
Markus

Ok, für den Fall das es jemand Interessiert oder selber testen möchte:

Benötigt einen DVB-Stick mit RTL2832u (ca. 9€)

Zu installieren auf Raspberry Pi, Orange Pi, Friendly Arm, Banana Pi usw.
Getestet mit Orange Pi Zero (512MB Ram) mit Erweiterungsplatine (ca. 14€)
(https://de.aliexpress.com/item/New-Orange-Pi-Zero-Set-6-Orange-Pi-Zero-512MB-Expansion-Board-Black-Case-development-board/32782429852.html?spm=2114.13010608.0.0.eNyFWD)

sudo apt-get install git cmake sox

git clone git://git.osmocom.org/rtl-sdr.git

cd rtl-sdr/
mkdir build
cd build
cmake ../ -DINSTALL_UDEV_RULES=ON -DDETACH_KERNEL_DRIVER=ON
make
sudo make install
sudo ldconfig

Zur Ausgabe:
z. B. FFH in Hessen Frequenz 100.0

rtl_fm -M wbfm -f 100.0M | play -r 32k -t raw -e s -b 16 -c 1 -V1 –

…Radioempfang mit DVB-T Stick und Ausgabe.

Tim
Gast
Tim

Morgen Sebastian,
Hab mich auch mal an ein ähnliches Projekt begeben. Wollte allerdings anstatt der Fernbedienung Taster an der GPIO Port anschließen. Hab dein Script soweit geändert wie ich denke das es richtig ist. Habe allerdings folgenden Fehler beim Mac-Adresse auslesen.

File „/home/pi/squeezebox-control.py“, line 42
return ‚%3A‘.join([‚%02x‘ % ord(char) for char in info[18:24]])
^
IndentationError: unindent does not match any outer indentation level
File „/home/pi/squeezebox-control.py“, line 42
return ‚%3A‘.join([‚%02x‘ % ord(char) for char in info[18:24]])
^
IndentationError: unindent does not match any outer indentation level

Hab im Moment kein Wlan Adapter angeschlossen (benutze Pi2). Liegt das dadran? Hab aber Zeile 221 von wlan0 auf eth0 geändert.
Hast du eine Idee woran das liegen könnte?

Tim
Gast
Tim

Hi Sebastian,
Danke für den Tip. Läuft jetzt ohne Fehler durch. Habe auch eine Verbindung per Telnet. Standard Lautstärke wird gesetzt. Allerdings klappt das noch nicht mit den Gpio Tastern. Die Taster funktionieren und kommen am Pi an, werden aber nicht an den LMS weitergeleitet. Hast du da vielleicht auch noch einen Tip für?
Code sieht so aus:

def setGPIO(channel,state):
        #GPIO.setwarnings(False)
        GPIO.setmode(GPIO.BOARD)                            # Zählweise der Pins festlegen
        #GPIO.setup(22, GPIO.OUT)                            # Pin 22 (GPIO 25) = Verstärker-Relais 1
        #GPIO.setup(24, GPIO.OUT)                           # Pin 24 (GPIO  8) = Verstärker-Relais 2
        GPIO.setup(32, GPIO.IN)
        GPIO.setup(33, GPIO.IN)
        GPIO.setup(35, GPIO.IN)
        GPIO.setup(36, GPIO.IN)
        GPIO.setup(38, GPIO.IN)
        GPIO.setup(40, GPIO.IN)

        if GPIO.input(32) == GPIO.HIGH:
                player('playlist')
        if GPIO.input(33) == GPIO.HIGH:
                if status == "play":
                        player('pause')
                else:
                        player('play')
        if GPIO.input(35) == GPIO.HIGH:
                player('next')
       if GPIO.input(36) == GPIO.HIGH:
                player('back')
        if GPIO.input(38) == GPIO.HIGH:
                player('vol_up')
        if GPIO.input(40) == GPIO.HIGH:
                player('vol_down')

Der Programm Teil der die Befehle sendet sieht genauso aus wie deiner.
Muss dazu sagen das ich mich erst seit ein paar Tagen mit python und dem GPIO-Port am Pi beschäftige und deshalb bestimmt noch etwas auf dem Schlauch stehe 🙂
Gruß Tim

Tim
Gast
Tim

Besten dank. Werd ich morgen mal ausprobieren.
Hab aber noch eine Frage zu der Print funktion. Wo wird das dann ausgegeben? Wenn ich im terminal sudo ./squeezebox-control.py ausführe oder in der Log-Datei?

Tim
Gast
Tim

Ich habs hingekriegt 🙂
besten dank für deine Hilfe. Das Start-Script sieht jetzt so aus:

#!/usr/bin/env python
#coding: utf-8 
 
####################################################################
# squeezebox-control.py
# Script zur Steuerung eines WLAN-Lautsprechers
# von Sebastian Köhler - http://indibit.de
#
# LETZTE ÄNDERUNG:    17.04.2016
####################################################################
 
import fcntl, socket, struct    # für MAC-Adresse
#import lirc
import RPi.GPIO as GPIO
import sys
import telnetlib
import thread
import time
 
# ----------------------------------------------------------------------------
#  Konfiguration
# ----------------------------------------------------------------------------
HOST            = "192.168.178.58"   # IP-Adresse des LMS
PORT            = "9090"            # CLI-Port des LMS
OFF_DELAY       = 180               # Verstärker-Abschalt-Verzögerung (in Sekunden)
VOL_NORM        = 100                # Lautstärke, die nach beim Einschalten eingestellt werden soll
 
# ----------------------------------------------------------------------------
#  sonstige Variablen
# ----------------------------------------------------------------------------
mac = ''       # MAC-Adresse
status = ''    # Status des Players
tn = ''        # Telnet-Verbindung
lastPlay = 0   # Zeit, wann der Player das letzte Mal gespielt hat
 
# ----------------------------------------------------------------------------
#  MAC-Adresse auslesen
# ----------------------------------------------------------------------------
def getMAC(ifname):
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    info = fcntl.ioctl(s.fileno(), 0x8927,  struct.pack('256s', ifname[:15]))
    return '%3A'.join(['%02x' % ord(char) for char in info[18:24]])
 
# ----------------------------------------------------------------------------
#  Telnet-Verbindung herstellen
# ----------------------------------------------------------------------------
def tn_connect():
    global tn
    try:
        tn = telnetlib.Telnet(HOST,PORT)
        player("startup")
    except:
        time.sleep(10)
 
# ----------------------------------------------------------------------------
#  WLAN-Lautsprecher bei Start initialisieren
# ----------------------------------------------------------------------------
def startup():
    setGPIO("startup","")
    tn_connect()
 
# ----------------------------------------------------------------------------
#  Fernbedienung/LIRC abfragen
# ----------------------------------------------------------------------------
def remote():
    while True:
        try:
            #codeIR = lirc.nextcode()
            #if codeIR != []:
            #    if codeIR[0] == 'KEY_UP':
                if GPIO.input(40):
		    print 'lauter'
     		    player('vol_up')            
            #    elif codeIR[0] == 'KEY_DOWN':
		elif GPIO.input(38):
		    print 'leiser'
                    player('vol_down')
            #    elif codeIR[0] == 'KEY_LEFT':
		elif GPIO.input(35):
		    print 'zurück'
                    player('back')
            #    elif codeIR[0] == 'KEY_RIGHT':
		elif GPIO.input(36):
		    print 'next'
                    player('next')
            #    elif codeIR[0] == 'KEY_OK':
	    #       pass
            #    elif codeIR[0] == 'KEY_MENU':
		elif GPIO.input(33):
                    print 'playlist'
		    player('playlist')
            #    elif codeIR[0] == 'KEY_PLAYPAUSE':
		elif GPIO.input(32):
                    if status == "play":
			print 'pause'
                        player('pause')
                    else:
			print 'play'
                        player('play')
                time.sleep(0.50)
        except:
                time.sleep(0.10)
     
# ----------------------------------------------------------------------------
#  Befehle senden, Status abfragen
# ----------------------------------------------------------------------------
def player(cmd):
    p0 = ""
    p1 = ""
    p2 = ""
    if cmd == "startup":
        try:
            player("stop")
            #tn.write("subscribe play,pause,stop,playlistr")
            tn.write(mac + " mode ?r")
            resetVol()
        except (EOFError, socket.error):
            tn_connect()
             
    else:
        if cmd == "play":               # Wiedergabe
            p0 = "play"
        elif cmd == "pause":            # Pause
            p0 = "pause"
        elif cmd == "stop":             # Stop
            p0 = "stop"
        elif cmd == "back":             # Titel zurück
            p0 = "playlist"
            p1 = "index"
            p2 = "-1"
        elif cmd == "next":             # Titel überspringen
            p0 = "playlist"
            p1 = "index"
            p2 = "%2B1"
        elif cmd == "vol_up":           # Lauter
            p0 = "mixer"
            p1 = "volume"
            p2 = "%2B5"
        elif cmd == "vol_down":         # Leiser
            p0 = "mixer"
            p1 = "volume"
            p2 = "-5"
        elif cmd == "playlist":         # Playlist abspielen
            p0 = "playlist"
            p1 = "play"
            p2 = "test.m3u"
        else:
            p0 = ""
            p1 = ""
            p2 = ""
 
        if p0 != "":
            try:
                tn.write(mac + " " + p0 + " " + p1 + " " + p2 + "r")
            except (EOFError, socket.error):
                tn_connect()
     
    p0 = ""
    p1 = ""
    p2 = ""
 
def getStatus():
    while True:
        global status
        try:
            tn.write(mac + " mode ?r")
            q = tn.read_until('r')
            s = q.split('r')[0].split(' ')
            if s:
                if s[0] == mac:
 
                    if s[1] == "mode":
                        status = s[2]
 
        except (EOFError, socket.error):
            tn_connect()
        except KeyboardInterrupt:
            getOut()
        time.sleep(0.1)
 
# ----------------------------------------------------------------------------
#  Verstärker am WLAN-Lautsprecher ein-/ausschalten
# ----------------------------------------------------------------------------
def ampOnOff():
    global lastPlay
    if status == "play":
        setGPIO("amp","on")
        lastPlay = time.time()
    else:
        if time.time() - lastPlay &gt;= OFF_DELAY:
            if status == "pause":
                resetVol()
                player("stop")
            setGPIO("amp","off")
 
def setGPIO(channel,state):
    amp = 22
    on  = GPIO.LOW
    off = GPIO.HIGH

    if channel == "startup":
        GPIO.output(22, GPIO.HIGH)
        #GPIO.output(24, GPIO.HIGH)
    else:
        if (channel in locals()) and (state in locals()):
            GPIO.output(locals()[channel], locals()[state])
 
# ----------------------------------------------------------------------------
#  Standard-Lautstärke setzen
# ----------------------------------------------------------------------------
def resetVol():
    try:
        tn.write(mac + " mixer volume " + str(VOL_NORM) + " r")
    except (EOFError, socket.error):
        tn_connect()
     
# ----------------------------------------------------------------------------
#  Script beenden
# ----------------------------------------------------------------------------
def getOut():
    GPIO.cleanup()
    sys.exit(0)
 
# ----------------------------------------------------------------------------
#  Hauptprogramm
# ----------------------------------------------------------------------------
if __name__ == '__main__':
    #GPIO.setwarnings(False)
    GPIO.setmode(GPIO.BOARD)                            # Zählweise der Pins festlegen
    GPIO.setup(22, GPIO.OUT)                            # Pin 22 (GPIO 25) = Verstärker-Relais 1

    #GPIO.setup(24, GPIO.OUT)                           # Pin 24 (GPIO  8) = Verstärker-Relais 2
    GPIO.setup(32, GPIO.IN)
    GPIO.setup(33, GPIO.IN)
    GPIO.setup(35, GPIO.IN)
    GPIO.setup(36, GPIO.IN)
    GPIO.setup(38, GPIO.IN)
    GPIO.setup(40, GPIO.IN)
#   sockid=lirc.init("appleremote", blocking = False)   # Fernbedienung einbinden
 
    mac = getMAC('eth0')
    startup()
 
    thread.start_new_thread(getStatus,())
    thread.start_new_thread(remote,())
 
    while True:
        try:
            ampOnOff()
            n = True
            time.sleep(0.1)
        except KeyboardInterrupt:
            getOut()

Vielleicht steht ja einer vor dem gleichem Problem 😉
Hab mich eigentlich an deine Anleitung gehalten und nur die Lirc installation übersprungen.

mfg Tim

Michael
Gast
Michael

Michael
und wenn Du jetzt mal überschlägst auf was für Gesamtkosten kommst Du?

Jens
Gast
Jens

Hallo Sebastian,
dank Deiner Anleitung habe ich ja schon seit einiger Zeit bei mir 2 WLan Lautsprecher am Laufen. Die an sich auch ganz prima funktionieren. Nur ein Problem tritt immer mal wieder auf. Die Dauer vom Anschalten bis zum Angehen ist manchmal recht lang. Ich kann auch nicht nachvollziehen ob es irgendeinen Auslöser dafür gibt. Wenn der Fall eingetreten ist, hilft dann immer nur ein komplettes runter / hoch fahren. Danach geht es wieder. Ist sowas bei Dir auch schon mal aufgetreten?

Jens
Gast
Jens

Hallo Sebastian,
ja bei 5 Sekunden würde mich das auch nicht weiter beschäftigen. Bei mir dauert es leider manchmal mehrere Minuten.

wpDiscuz
Translate »