Raspberry-Webradio

Aus der Mikrocontroller.net Artikelsammlung, mit Beiträgen verschiedener Autoren (siehe Versionsgeschichte)
Wechseln zu: Navigation, Suche

von Michael Schwarz

Dieser Artikel nimmt am Artikelwettbewerb 2012/2013 teil.

Raspberry Webradio

Einleitung

Wer kennt das nicht, man möchte einfach nur Musik hören und egal auf welchen Radio Sender man schaltet, entweder hört man Werbung, Nachrichten, unnötige Ansagen irgendwelcher Moderatoren oder die gefühlte 317te Wiederholung der Charts. Glücklicherweise gibt es eine bessere und obendrein kostenlose Alternative: Internet-Radio. Mit SHOUTcast gibt es dazu auch ein Verzeichnis, das annähernd 50.000 Online-Radiosender listet. Doch da ich nicht immer meinen PC einschalten möchte um Musik zu hören, musste ein Standalone Gerät her. Und da ich gerade meinen Raspberry Pi erhalten hatte, schien das ein gutes Projekt zu sein um den Mini-Computer sinnvoll einzusetzen.

Das Projekt hat dann doch mehr Zeit in Anspruch genommen als zuerst gedacht, doch das Ergebnis kann sich sehen lassen und muss sich auch nicht vor kommerziellen Geräten verstecken, die in höheren Preisklassen liegen.

Eine ausführliche Anleitung gibt es natürlich auch, in welcher die Bedienung des Gerätes genau beschrieben wird.

Features

Hier ist eine Liste der Hauptfeatures des Raspberry Webradios

  • Abspielen von MP3 Shoutcast Streams über WLAN oder Ethernet
  • Abspielen von MP3s von USB-Medien mit Unterstützung von Playlists
  • Anzeige der Song Informationen (sowohl von MP3s als auch von Streams)
  • Vollständige Shoutcast Unterstützung (Suchen von Stations, Top Stations, Stationen nach Genre, Zufällige Stations)
  • Lieblingsstationen und Verwaltung der Favoriten
  • Android App zur Fernsteuerung
  • Schlummerfunktion

Hardware

Das Hauptprogramm läuft auf einem Raspberry Pi (Model B) mit 256 MB RAM, getaktet auf 700MHz. Die Interaktion mit dem Benutzer erfolgt über ein Blau-Weiß Grafik-Display mit KS0108 Controller und einer Auflösung von 128x64 Pixel, sowie über einen Drehencoder und 6 Tasten.

Um den Raspberry Pi zu entlasten, und da dieser nicht besonders viele I/O Pins zur Verfügung stellt, stehen ihm zwei Mikrocontroller als "Co-Prozessoren" zur Verfügung. Ein ATMega32 dient als Bridge zwischen Raspberry und GLCD und ein ATTiny2313 wird verwendet um den Drehencoder und die Tasten auszuwerten.

Technische Daten

Funktion Hardware
Prozessor Raspberry Pi (Model B, 256MB RAM)
LCD Controller ATMega32 @ 14,3181 MHz
I/O Controller ATTiny2313 @ 8 MHz
Display GLCD KS0108 (128x64) S/W Display
Eingabe Drehencoder und 6 Taster


Schaltplan

Stromversorgung

Der Raspberry Pi wird über den GPIO Pin Header mit 5V versorgt. Der ATMega32 und das Display werden ebenfalls mit 5V versorgt. Die 3,3V für den ATTiny2313 stellt der Raspberry Pi an seinen GPIO Ports zur Verfügung [1].

Raspberry Pi I/O Pins

Der Stromverbrauch des Raspberry liegt laut Spezifikation bei 700mA, das Gerät sollte also mit einem Netzteil versorgt werden das 1A liefern kann, vor allem wenn ein WLAN Stick verwendet wird. Mein Webradio wird durch ein USB Handy-Ladegerät (5V @ 1A) mit Strom versorgt.


GLCD Bridge

Da der Raspberry nur wenige Pins hat und diese nur 3,3V Pegel haben dient der ATMega32 sowohl als Pegel-Converter, Portexpander und Display Treiber. Die Stromversorgung erfolgt über die 5V mit welchen auch der Raspberry Pi gespeist wird. Die 3,3V der I/O Pins reichen für den ATMega um es als High-Pegel zu erkennen, eine Kommunikation in die andere Richtung findet nicht statt. Die einzige Aufgabe des Mikrocontrollers ist es, die vom Raspberry erhaltenen Daten an das Display weiterzuleiten. Die Kommunikation erfolgt über ein Clock und ein Data Signal. Bei jedem high-low Übergang wird das Bit vom Data-Pin übernommen und in einem Ringbuffer gespeichert, damit keine Daten verloren gehen. Der Inhalt des Ringbuffer wird dann regelmäßig an das Display gesendet. Ein vollständiges Bild hat eine Größe von 1024 Bytes (128x64 Bit). Danach werden die Daten für das nächste Bild gesendet. Überprüfungen finden nicht statt und es werden ausschließlich die Rohdaten des Bildes gesendet um den Overhead so gering wie möglich zu halten und damit eine hohe Bildaufbaugeschwindigkeit zu erhalten.

Das Format der Daten schaut folgendermaßen aus

Byte 0-127 Byte 128-255 ... Byte 895-1023
Bilddaten 1.-8. Zeile Bilddaten 9.-16. Zeile Bilddaten 17.-120. Zeile Bilddaten 121.-128. Zeile

Jedes gesendete Byte enthält 8 vertikale Pixel, es werden also durch das Senden von 128 Bytes immer 8 Zeilen auf das Display geschrieben.

Bei einer Taktung des ATMegas mit 14,3181MHz wird damit eine maximale Refresh-Rate von 12 Bildern/Sekunde erreicht. Im Produktiveinsatz hat sich eine Refreshrate von ungefähr 6,5 Bildern/Sekunde als völlig ausreichend herausgestellt und sich als sehr stabil bewährt.

Zusätzlich zur Grafik steuert der ATMega auch noch die Hintergrundbeleuchtung des Displays. Diese ist so geschaltet, dass beim Einschalten des Gerätes die Beleuchtung aktiviert wird und bei Bedarf vom Raspberry deaktiviert werden kann.

Raspberry Pi, Platine mit GLCD- und IO-Bridge

I/O Bridge

Da der ATMega32 mit den Aufgaben als Grafik-Bridge schon ziemlich ausgelastet ist handhabt ein weiter Mikrocontroller, ein ATTiny2313, die Eingabe über den Drehencoder und die 6 Taster. Kommuniziert wird bei beim ATMega ebenfalls über ein Data- und Clock-Signal, diesmal jedoch in die andere Richtung. Der ATTiny agiert nur als Slave und sendet die Zustände der Taster und des Encoders an den Raspberry wenn dieser ein Clock-Signal anlegt.

Eine vollständige Übertragung ist 3 Byte (24 Bit) lang und enthält für jeden Taster ein Bit ob er seit der letzten Abfrage gedrückt wurde, weiters für jeden Taster ein Bit ob er seit der letzten Abfrage für längere Zeit gedrückt wurde und schließlich noch ein Byte das die Anzahl der Steps des Drehencoders seit der letzten Abfrage enthält.

Erstes Byte, wenn das entsprechende Bit gesetzt ist, wurde der Taster seit der letzten Abfrage gedrückt, sonst nicht.

Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
0 0 Taster 5 Taster 4 Taster 3 Taster 2 Taster 1 Taster 0

Zweites Byte, wenn das entsprechende Bit gesetzt ist, wurde der Taster seit der letzten Abfrage für längere Zeit gedrückt, sonst nicht.

Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
0 0 Taster 5 Taster 4 Taster 3 Taster 2 Taster 1 Taster 0

Drittes Byte, die Anzahl der Steps die der Drehencoder seit der letzten Abfrage gedreht wurde. Positive Werte bedeuten eine Drehung nach rechts, negative eine Drehung nach links.

Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0
Drehencoder Änderung (als 8-Bit signed char)

Die Entprellroutinen für die Taster und die Auswerte-Routine für den Drehencoder sind in diesem Controller implementiert, sodass sich der Raspberry Pi nicht mehr darum kümmern muss.

Internet

Für den Zugriff auf das Internet kann man entweder die Ethernet Buchse des Raspberry Pi verwenden oder einen WLAN Stick an einen der USB Ports anschließen. Hier ist der Netgear N150 Wireless USB Microadapter empfehlenswert, da er sowohl klein als auch recht günstig ist und es für den Raspberry Pi einen Treiber gibt. Eine Anleitung zur Installations des Treibers gibt es hier: http://pkern.at/1342/netgear-n150-wireless-usb-microadapter-auf-dem-raspberry-pi

Die Konfiguration des WLAN (Suche, Verbinden und Authentifizierung) kann vollständig über das Gerät erfolgen, sodass es auch möglich ist das Radio mitzunehmen und mit einem anderen WLAN Hotspot zu verbinden.

Software

Die Software des Webradios besteht aus mehreren Teilen und kann in folgende Kategorien eingeteilt werden

Software
Hauptprogramm das am Raspberry Pi läuft ("Firmware"), programmiert in C
Stream Player und USB-Player, programmiert in C
Android Fernsteuerungsprogramm, programmiert in Java
Installer zur erstmaligen Einrichtung, programmiert in Bash
Interfaces
Kleine Hilfstools zur Kommunikation mit dem Betriebssystem, programmiert in Bash
Firmware für die Bridges (I/O und GLCD), programmiert in C
Mobile Webseite zur Fernsteuerung, programmiert in PHP und JavaScript
Developer Tools
Simulator, programmiert in C++
Bild-Konverter für Firmware, programmiert in Bash
Font-Creator von F. Maximilian Thiele (apetech)

Der Zusammenhang der wichtigsten Teile ist in diesem Diagramm zu sehen

Software Module

Graue Rechtecke sind Hardware-Komponenten (Display, Taster, Drehencoder), die Software-Hardware Bridges sind blau eingezeichnet, die gelben Elemente sind Software-Interfaces (Bash-Scripts), Software Komponenten sind weiß und in grün gehalten sind Betriebssystem-Anwendungen.


Bridges

Die Software für die beiden Mikrocontroller ist in C geschrieben und kann mit einem Aufruf von

  make hex

erstellt werden bzw. mit

  make flash

erstellt und geflasht werden. Vor dem Flashen sollte man allerdings noch die Zeile mit dem Programmer im Makefile anpassen. Die Fuses können durch den Aufruf von

  make fuses

richtig gesetzt werden. Für den ATMega32 bedeutet das: Taktfrequenz auf Quarz und JTAG deaktivieren (damit PORTC verwendet werden kann). Das Entspricht den Fuse-Werten Low-Fuse 0xde und High-Fuse 0xd9) Am ATTiny stellen die Fuses die interne Taktfrequenz auf 8MHz. Die Fuse-Werte sind Low-Fuse 0xe4, High-Fuse 0xdf und Extended-Fuse 0xff.

Die Taktfrequenzen der Mikrocontroller sind nicht kritisch, für den ATMega32 sollte alles im Bereich von 12MHz bis 16MHz funktionieren. Schlimmstenfalls muss der Wert GLCD_DELAY in der glcd.h erhöht werden.

Die Firmware für den ATMega32 enthält auch das Boot-Logo, welches mit dem convert Script aus einem PNG erzeugt wurde. Das Bild kann durch ein beliebiges anderes Bild ausgetauscht werden, es muss dann nur der Aufruf zu GLCDD_XBMDraw_P(data, x, y, width, height) in der main.c angepasst werden (außer das neue Bild ist ebenfalls 59x56 Pixel groß).


Firmware

Die Firmware ist das Herzstück des Projekts. Sie ist zuständig für die Ein- und Ausgabe, das Starten und Stoppen von Musik und für die Verwaltung. In regelmäßigen Intervallen werden die Benutzereingaben von der I/O Bridge geholt, auf diese reagiert und der neue Display Inhalt an die Grafik-Bridge gesendet.

Möchte der User Musik abspielen, entscheidet die Firmware ob es ein lokales File oder ein Stream ist, und delegiert die Aufgabe dann entweder an den USB-Player oder den Stream-Player.

Konfigurationsdatei

Alle Einstellungen die konfiguriert werden können sind in der default.conf zu finden. Die Optionen sollten selbsterklärend sein, es sollte jedoch nicht notwendig sein hier manuell etwas anzupassen (ausgenommen der Eintrag des Shoutcast API Keys).

Streaming und Local-Player

Zum Abspielen von Musik gibt es zwei getrennte Applikationen: den Local-Player zum Abspielen von lokalen Dateien (von USB-Stick oder externen Festplatte) und den Stream-Player zum Wiedergeben von SHOUTcast Streams.

Die Konfigurationsdatei play.conf wird allerdings von beiden Programmen verwendet. In ihr kann der verwendete Player eingestellt werden (es funktionieren jedoch nur Player, welche die Musik Daten von einer Pipe verarbeiten können) sowie die Größe des Buffers den der Player verwendet.

Simulator

Simulator nach dem Starten

Da es relativ umständlich ist, die Software jedesmal auf den Raspberry zu übertragen und zu testen existiert auch ein Simulator, der die komplette Hardware simuliert. Der Simulator ist in C++ geschrieben mit wxWidgets als GUI Framework. Der Simulator ist nur unter Linux getestet, da die Software auch unter Linux entwickelt wurde. Das liegt auch nahe, da auf dem Raspberry Pi ein modifiziertes Debian läuft und es nie geplant war, dass die Software auf einer anderen Plattform als auf dem Raspberry Pi läuft.

Um das Programm im Simulator zu testen muss der Quellcode nur mit dem Debugging Makefile kompiliert werden. Dieses setzt das Simulationsmakro und linkt die wiringPi Bibliothek nicht zum Programm. Weiters müssen noch die default.conf folgendermaßen angepasst werden:

[hardware]
lcd=sim
io=sim

Die Hardware Zugriffe werden dadurch auf Datei-Operationen umgeleitet. Diese Dateien sind die Kommunikationsschnittstelle zum Simulator.


Beim Starten des Simulators kann man als Parameter den Pfad zur Software mitgeben, damit diese sofort geladen wird. Der Simulator selbst kann im Grunde nicht mehr als das Display, den Drehencoder und die Tasten zu simulieren, das ist aber ausreichend, um die komplette Funktionalität (bis auf die Hintergrundbeleuchtung) der Firmware zu testen. Die Oberfläche des Simulators ist zwar nicht schön, aber zweckmäßig.

Die Buttons in der ersten Zeile simulieren den Drehencoder (linke, Ok, rechts), die zweite und dritte Zeile enthalten die Buttons und die letzte Zeile ermöglicht das Simulieren des Gedrückthaltens der Tasten 1-4 für längere Zeit. Ein Klick auf den Screenshot Button speichert das aktuelle Bild im Ordner des Simulators als "lcd.png".

Android App

Startseite der Android App

Da der Raspberry Pi noch genügend Ressourcen hat, läuft im Hintergrund ein Webserver, der es erlaubt das Gerät auch über ein Android-Smartphone zu steuern. Die App dafür ist ebenfalls auf der Downloadseite des Projekts zu finden.

Das Smartphone muss natürlich im gleichen Netzwerk sein (WLAN), damit das Webradio gefunden werden kann. Um das Gerät zu finden, braucht man nicht einmal die IP-Adresse wissen, da in der App ein Zeroconf-Client implementiert wurde, der den Raspberry automatisch findet (der Zeroconf Name ist raspberrypi.local).

Wurde das Raspberry Webradio gefunden, kann man ihn der App sehen, welches Lied gerade abgespielt wird (inklusive Bild des Interpreten, falls vorhanden), Stationen aus der Favoriten-Liste und vom USB-Medium abspielen sowie neue SHOUTcast Stationen und SHOUTcast Streams hinzufügen.

Um das App zu installieren, kopiert man die apk Datei einfach auf das Smartphone und öffnet sie mit einem beliebigen Datei-Explorer auf dem Handy. Die einzigen Voraussetzungen für die App sind Android 2.2 und aufwärts sowie WLAN, da das Smartphone natürlich im gleichen Netzwerk sein muss wie das Webradio.


SHOUTcast Unterstützung

Die Unterstützung für die SHOUTcast API kann alles was man braucht

  • Suchen nach Stationen
  • Anzeigen der Stationen nach Genre
  • Liste der Top Stationen
  • Zufällige Stationen (wenn man sich gerne überraschen lässt)

Leider benötigt man für die SHOUTcast API einen Developer Key der nicht so einfach zu bekommen ist (und den man auch nicht veröffentlichen darf). Wer die oben erwähnten Features also verwenden möchte, kann entweder versuchen einen SHOUTcast Developer Key zu bekommen, oder man verwendet einfach einen der Keys die im Internet umherschwirren... (siehe Links). Das Abspielen von SHOUTcast Streams funktioniert natürlich auch ohne Developer Key.

Der Developer Key muss in der Konfigurations-Datei default.conf überall eingetragen werden, wo [DevKey] vorkommt.

Installation

Die Firmware ist entwickelt und getestet auf Raspbian Wheezy. Die Installation von Raspbian wird auf der Raspberry Pi Seite beschrieben. Die einfachste Art das Raspberry Webradio aufzusetzen ist mit dem automatischen Installer. Hierfür kopiert man alle Ordner, die man aus dem SVN ausgecheckt hat auf den Raspberry Pi und führt den Installer wie unten beschrieben aus.

Eine andere, noch einfachere Möglichkeit ist, ein fertiges Image zu verwenden. Dieses braucht nur auf eine SD-Karte mit mindestens 2GB geschrieben werden. Das Image (Stand: 11.07.2013) ist zu finden auf misc0110.net/download/webradio-image.rar. Auf die SD-Karte schreiben kann man es (nach dem Entpacken) mit

sudo dd if=/pfad/zum/image.img of=/dev/sdX bs=4M

wobei /dev/sdX durch den Pfad zur SD Karte ersetzt werden muss. Man kann statt dd auch das graphische Tool ImageWriter (sudo apt-get install usb-imagewriter) verwenden.

Die Login Daten für das Image sind User: pi und Passwort: raspberry.

Installer

Der Installer ist ein Bash-Script das alle erforderlichen Dateien auf dem Raspberry Pi installiert. Damit der Installer funktioniert, wird Internetzugang benötigt (am besten über die LAN Buchse) und er muss als root ausgeführt werden.

Folgende Schritte werden vom Installer durchgeführt

  • Installation aller notwendigen Softwarepakete, falls diese noch nicht installiert sind (avahi-daemon, mpg123, id3v2, usbmount, lighttpd + php5, wiringPi, libcurl, libxml2)
  • Einrichten des lighttpd Servers und der mobilen Webseite
  • Kompilieren der Firmware, des USB-Players und des Streaming-Players
  • Kopieren aller Dateien in die richtigen Ordner (/home/pi wird als Installationsordner verwendet) und setzen der Berechtigungen
  • Standard Konfiguration einspielen

Der Installer wird mit einem Aufruf von

 sudo ./installer.sh

gestartet.

Nach der Installation muss - sofern die Firmware auf der Hardware ausgeführt wird, und nicht im Simulator - die default.conf bearbeitet werden:

[hardware]
lcd=hardware
io=hardware

Sollte der Webserver nicht starten, kann dies durch ein

 sudo chown pi:pi /var/log/lighttpd/

behoben werden.

Autostart und Autologin

Um die Firmware automatisch beim Starten des Raspberrys zu starten müssen zwei Dateien angepasst werden. Zuerst editiert man die Datei /etc/inittab (z.B. mit sudo nano /etc/inittab).

Man sucht die Zeile

 1:2345:respawn:/sbin/getty --noclear 38400 tty1

und kommentiert sie aus, indem man # davor setzt. Die Zeile sieht danach so aus:

 #1:2345:respawn:/sbin/getty --noclear 38400 tty1

Unter der geänderten Zeile fügt man folgende neue Zeile ein

 1:2345:respawn:/bin/login -f pi tty1 </dev/tty1 >/dev/tty1 2>&1

Dies sorgt dafür, dass man automatisch als User pi angemeldet wird wenn das Betriebssystem startet.


Danach muss noch die Datei /etc/profile geändert werden (z.B. mit sudo nano /etc/profile). Hier fügt man einfach am Ende der Datei folgende zwei Zeilen ein

  cd /home/pi
  ./firmware

Dadurch startet die Firmware automatisch wenn man den Raspberry Pi hochfährt.

Troubleshooting

  • Ich kann keine Musik hören

Es kann sein, dass die Standard Audio Ausgabe auf dem HDMI Port erfolgt. Umschalten auf die Audio Buchse kann man mit

  sudo amixer cset numid=3 1

Eine weitere Möglichkeit ist, dass entweder die Bash Scripts nicht dort liegen, wie es in der default.conf angegeben ist, oder die Bash-Scripts nicht ausführbar sind. Wenn die Software allerdings mit dem Installer Script installiert wurde sollte das nicht der Fall sein.

  • Es wird eine falsche Uhrzeit angezeigt

Das ist dann der Fall, wenn die Zeitzone nicht richtig eingestellt ist. Das Ändern der Zeitzone ist nicht schwer und sieht z.B. für Wien so aus

  sudo mv /etc/localtime /etc/localtime.old
  sudo cp /usr/share/zoneinfo/Europe/Vienna /etc/localtime
  • Der Drehencoder funktioniert nicht/verhält sich seltsam

Möglicherweise sind die beiden Ausgänge vertauscht. Tauschen der Pins PD5 und PD6 sollte helfen (entweder in Software oder Hardware)

  • Im Simulator funktioniert das Abspielen von Streams/MP3s nicht

Die Firmware geht davon aus, das alle notwendigen Dateien in /home/pi legen. Abhilfe schafft entweder das Anlegen des Ordners /home/pi und hineinkopieren der relevanten Dateien in diesen Ordner oder das Ändern der Pfade in der default.conf

  • Das Display zeigt Streifen an/ist verschoben/unleserlich nachdem ich das Audio-Kabel ein/ausgesteckt habe

Das ist ein bekannter Bug, der manchmal auftritt, den ich aber noch nicht lokalisieren konnte. Beheben kann man ihn im Moment nur, indem man das Gerät herunterfährt (Settings -> Shutdown), vom Strom trennt und wieder mit Strom versorgt. Dadurch wird der Display Controller zurückgesetzt und man sollte wieder ein normales Bild haben.

  • Die Android App zeigt nur Loading... Please wait... an

Wenn ein Neustart der App nichts hilft (manchmal wird der Raspberry nicht gefunden), dann kann es daran liegen, dass das Handy nicht im gleichen Netwzerk ist (wenn es z.B. über 3G im Internet ist und nicht mit WLAN) oder dass der Raspberry im Moment keine aktive Internet Verbindung hat. Der zweite Fall kann dann auftreten, wenn der Raspberry über WLAN verbunden ist, und für längere keine Zeit kein Traffic verursacht wurde. Abhilfe schafft hier das manuelle Starten einer Internet Radio Station, danach sollte es auch über die Android App wieder funktionieren.

Fertiges Gerät

Fotos

Gehäuse mit offenem Deckel
Offenes Gerät
Bootlogo (vor dem Lackieren)

Video

Raspberry Webradio Demo

Ausblick

Wie jeder Entwickler weiß, ist ein Produkt nie fertig. Das gilt auch bei diesem Projekt und so habe ich bereits einige Ideen für zukünftige Software Updates.

  • Abspielen von Musik aus YouTube Videos (bereits in der Testphase)
  • Eine Weckerfunktion
  • Erweitern des Simulators um die Simulation der Hintergrundbeleuchtung und einer Debug Console
  • Unterstützung weiterer Musik Formate (ogg und wma)
  • Bessere USB Wiedergabe (Anzeige der Restzeit/Gesamtzeit, voriges Lied, zufälliges Lied, Wiederholen, ...)
  • Aufnahme der Internet Streams als MP3
  • Erweiterung der Android App um mehr Funktionen

Um immer auf dem neuesten Stand zu sein, empfiehlt es sich hin und wieder die Projektseite zu besuchen, bei größeren Updates werde ich natürlich auch diesen Artikel aktualisieren. Sollte das Projekt jemand nachbauen, wünsche ich viel Spaß dabei und ich würde mich über Fotos und/oder Videos freuen.

Downloads

Siehe auch