Een Raspberry Pi kun je voor allerlei handige toepassingen gebruiken. Wil je graag je eigen radio maken, dan is dat natuurlijk ook mogelijk. Het bedienen van de radio via de command prompt is echter niet altijd even handig, daarom gaan we een internet radio maken met een display en knop-bediening.
In dit project gebruiken we een Raspberry Pi en een PiFace Control & Display 2. Dit is een LCD scherm (16×2) met 5 fysieke knoppen, tuimelschakelaar en infrarood ontvanger. Met behulp van speciale python library en script kunnen we internet radio luisteren.
Componenten voor dit project
• PiFace Control & Display 2 (CAD)
PiFace CAD configuratie
Vanzelfsprekend dient de PiFace CAD aangesloten te zijn op de Raspberry Pi en de bijbehorende software te zijn geïnstalleerd. Doorloop hiervoor de onderstaande stappen:
Activeer de SPI functionaliteit in de configuratie:
sudo raspi-config
Ga naar Advanced Options, selecteer SPI en activeer de optie en sluit raspi-config af.
Om met de PiFace te kunnen communiceren hebben een speciale Python library nodig, dan kunnen we installeren met behulp van het commando:
sudo apt-get install python3-pifacecad
Herstart nadat de installatie is voltooid:
sudo reboot
Het python radio script
Om de audiostreams te kunnen afspelen hebben we een media player nodig, in het script maken we gebruik van mplayer, deze installeer je met het commando:
sudo apt-get install mplayer
Bijna klaar! Als laatste hebben we natuurlijk het python radio script nodig. In de python library is een demo script aanwezig om radio te luisteren echter werkt deze helaas niet. Om die reden hebben we zelf een script gemaakt dat wel werkt.
#!/usr/bin/env python3 | |
# requires `mplayer` to be installed | |
# v1.0 | |
# https://raspberrytips.nl/internet-radio-luisteren-raspberry-pi/ | |
from time import sleep | |
import os | |
import sys | |
import signal | |
import shlex | |
import math | |
import lirc | |
PY3 = sys.version_info[0] >= 3 | |
if not PY3: | |
print("Radio only works with python3") | |
sys.exit(1) | |
from threading import Barrier | |
import subprocess | |
import pifacecommon | |
import pifacecad | |
from pifacecad.lcd import LCD_WIDTH | |
UPDATE_INTERVAL = 1 | |
STATIONS = [ | |
{'name': "NPO Radio 2", | |
'source': 'http://icecast.omroep.nl/radio2-bb-mp3', | |
'info': "NPO Radio 2"}, | |
{'name': "NPO 3FM", | |
'source': 'http://icecast.omroep.nl/3fm-bb-mp3', | |
'info': None}, | |
{'name': "Radio 538", | |
'source': 'http://vip-icecast.538.lw.triple-it.nl/RADIO538_MP3.m3u', | |
'info': None}, | |
{'name': "Q-music", | |
'source': 'http://icecast-qmusic.cdp.triple-it.nl/Qmusic_nl_live_96.mp3.m3u', | |
'info': None}, | |
{'name': "Sky Radio", | |
'source': 'http://provisioning.streamtheworld.com/pls/skyradio.pls', | |
'info': None} | |
] | |
PLAY_SYMBOL = pifacecad.LCDBitmap( | |
[0x10, 0x18, 0x1c, 0x1e, 0x1c, 0x18, 0x10, 0x0]) | |
PAUSE_SYMBOL = pifacecad.LCDBitmap( | |
[0x0, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x0, 0x0]) | |
PLAY_SYMBOL_INDEX = 0 | |
PAUSE_SYMBOL_INDEX = 1 | |
class Radio(object): | |
def __init__(self, cad, start_station=0): | |
self.current_station_index = start_station | |
self.playing_process = None | |
cad.lcd.blink_off() | |
cad.lcd.cursor_off() | |
cad.lcd.backlight_on() | |
cad.lcd.store_custom_bitmap(PLAY_SYMBOL_INDEX, PLAY_SYMBOL) | |
cad.lcd.store_custom_bitmap(PAUSE_SYMBOL_INDEX, PAUSE_SYMBOL) | |
self.cad = cad | |
@property | |
def current_station(self): | |
"""Returns the current station dict.""" | |
return STATIONS[self.current_station_index] | |
@property | |
def playing(self): | |
return self._is_playing | |
@playing.setter | |
def playing(self, should_play): | |
if should_play: | |
self.play() | |
else: | |
self.stop() | |
@property | |
def text_status(self): | |
"""Returns a text represenation of the playing status.""" | |
if self.playing: | |
return "Now Playing" | |
else: | |
return "Stopped" | |
def play(self): | |
"""Plays the current radio station.""" | |
print("Playing {}.".format(self.current_station['name'])) | |
if self.current_station['source'].split("?")[0][-3:] in ['m3u', 'pls']: | |
play_command = "mplayer -quiet -playlist {stationsource}".format( | |
stationsource=self.current_station['source']) | |
else: | |
play_command = "mplayer -quiet {stationsource}".format( | |
stationsource=self.current_station['source']) | |
self.playing_process = subprocess.Popen( | |
play_command, | |
shell=True, | |
preexec_fn=os.setsid) | |
self._is_playing = True | |
self.update_display() | |
def stop(self): | |
"""Stops the current radio station.""" | |
print("Stopping radio.") | |
os.killpg(self.playing_process.pid, signal.SIGTERM) | |
self._is_playing = False | |
self.update_playing() | |
def change_station(self, new_station_index): | |
"""Change the station index.""" | |
was_playing = self.playing | |
if was_playing: | |
self.stop() | |
self.current_station_index = new_station_index % len(STATIONS) | |
if was_playing: | |
self.play() | |
def next_station(self, event=None): | |
self.change_station(self.current_station_index + 1) | |
def previous_station(self, event=None): | |
self.change_station(self.current_station_index - 1) | |
def update_display(self): | |
self.update_station() | |
self.update_playing() | |
def update_playing(self): | |
"""Updated the playing status.""" | |
if self.playing: | |
char_index = PLAY_SYMBOL_INDEX | |
else: | |
char_index = PAUSE_SYMBOL_INDEX | |
self.cad.lcd.set_cursor(0, 0) | |
self.cad.lcd.write_custom_bitmap(char_index) | |
def update_station(self): | |
"""Updates the station status.""" | |
message = self.current_station['name'].ljust(LCD_WIDTH-1) | |
self.cad.lcd.set_cursor(1, 0) | |
self.cad.lcd.write(message) | |
def toggle_playing(self, event=None): | |
if self.playing: | |
self.stop() | |
else: | |
self.play() | |
def close(self): | |
self.stop() | |
self.cad.lcd.clear() | |
self.cad.lcd.backlight_off() | |
def radio_preset_switch(event): | |
global radio | |
radio.change_station(event.pin_num) | |
if __name__ == "__main__": | |
try: | |
subprocess.call(["mplayer"], stdout=open('/dev/null')) | |
except OSError as e: | |
if e.errno == os.errno.ENOENT: | |
print( | |
"MPlayer was not found, install with " | |
"`sudo apt-get install mplayer`") | |
sys.exit(1) | |
else: | |
raise | |
cad = pifacecad.PiFaceCAD() | |
global radio | |
radio = Radio(cad) | |
radio.play() | |
global end_barrier | |
end_barrier = Barrier(2) | |
switchlistener = pifacecad.SwitchEventListener(chip=cad) | |
for pstation in range(4): | |
switchlistener.register( | |
pstation, pifacecad.IODIR_ON, radio_preset_switch) | |
switchlistener.register(4, pifacecad.IODIR_ON, end_barrier.wait) | |
switchlistener.register(5, pifacecad.IODIR_ON, radio.toggle_playing) | |
switchlistener.register(6, pifacecad.IODIR_ON, radio.previous_station) | |
switchlistener.register(7, pifacecad.IODIR_ON, radio.next_station) | |
switchlistener.activate() | |
end_barrier.wait() | |
radio.close() | |
switchlistener.deactivate() | |
Je kunt het script naar je Raspberry Pi downloaden met behulp van wget
.
wget https://raspberrytips.nl/radio.py
Radio luisteren
Sluit een speaker of koptelefoon aan op de audio uitgang van de Raspberry Pi, start nu het radio script:
sudo python3 radio.py
Hierna kun je direct luisteren naar NPO Radio 2, de fysieke knoppen op de PiFace CAD hebben de volgende functies:
Knop (1) t/m (4) ▸ Radiostation voorkeuze 1 (Radio 2),2 (3FM),3 (538),4 (Q-music)
Navigatieknop (5) links/rechts ▸ vorig/volgend radiostation.
Navigatieknop (5) indrukken ▸ Pauze.
Knop (6) ▸ Radio applicatie afsluiten.
Radiostations toevoegen
In het script zijn 5 Nederlandse stations aanwezig (NPO Radio 2, NPO 3FM, Radio 538, Q-music en Sky Radio). Je kunt zelf meerdere stations toevoegen of wijzigen in het script. De URL’s van alle Nederlandse radio stations kun je terugvinden op listenlive.
{'name': "NPO Radio 2", 'source': 'http://icecast.omroep.nl/radio2-bb-mp3', 'info': None},
Wijzig in het script de name
en source
van een radio station of voeg een nieuwe toe, ‘info’ wordt niet gebruikt, geef deze de waarde None
.
Als beginnende RPI gebruiker leek mij dit wel een leuk probeersel. Ik heb echter 1 vraag.
Ik wil maar 1 radiostation dus de pi face is niet echt noodzakelijk. Ook wil ik graag dat hij zodra er spanning op de Pi komt dat hij na het booten direct dat ene station gaat afspelen.
Ik ben al op zoek naar een oplossing maar als beginnende Pi user zou ik graag een steuntje in de rug hebben
ruud
Er is iets met het opstarten van programma’s, bij opstarten wel te verstaan.
Het zou inderdaad makkelijk zijn om bij opstart een opgegeven zender of programma op te starten, een soort autoexec.bat, maar dan voor python.
In afwachting op uw reactie…
hallo,
ik heb de aanwijzingen nauwkeurig opgevolgd (op ’n raspberry pi 3 en piface), maar krijg helaas de volgende foutmelding (op de display staat wel: NPO radio2):
%==================
pi@raspberrypi:~ $ sudo python3 radio.py
Playing NPO Radio 2.
MPlayer2 2.0-728-g2c378c7-4+b1 (C) 2000-2012 MPlayer Team
Cannot open file ‘/root/.mplayer/input.conf’: No such file or directory
Failed to open /root/.mplayer/input.conf.
Cannot open file ‘/etc/mplayer/input.conf’: No such file or directory
Failed to open /etc/mplayer/input.conf.
Playing http://icecast.omroep.nl/radio2-bb-mp3.
Resolving icecast.omroep.nl for AF_INET6…
Couldn’t resolve name for AF_INET6: icecast.omroep.nl
Resolving icecast.omroep.nl for AF_INET…
Connecting to server icecast.omroep.nl[145.58.52.144]: 80…
Name : Radio 2
Genre : Mixed
Website: http://www.radio2.nl
Public : no
Bitrate: 192kbit/s
Cache size set to 320 KiB
Cache fill: 0.00% (0 bytes)
ICY Info: StreamTitle=’NPO Radio 2 – Muziekcaf� – TROS’;
Detected file format: Audio only
Selected audio codec: MPEG 1.0/2.0/2.5 layers I, II, III [mpg123]
AUDIO: 48000 Hz, 2 ch, s16le, 192.0 kbit/12.50% (ratio: 24000->192000)
AO: [pulse] Init failed: Connection refused
AO: [alsa] 48000Hz 2ch s16le (2 bytes per sample)
[AO_ALSA] Unable to find simple control ‘Master’,0.
Video: no video
Starting playback…
%==================
enig idee wat ik moet doen?
Vriendelijke groet,
Jan
@jan speelt de muziek wel af?
Je kunt de ontbrekende input.conf downloaden en zelf op de juiste plaats zetten.
Sorry Richard,
Hij werkt nu.
Heel dom, maar ik zag het icoontje met het speakertje rechts boven.
Blijkbaar staat daar de boel standaard op HDMI ingesteld i.p.v. Analog.
Na het instellen op Analog werkte de internetradio !!!
Nogmaals dank en excuse voor het ongemak.
Vriendelijke groet,
Jan
Nog 1 vraagje:
Nu is het zo dat als de Raspberry opstart dat ik daarna via de terminal de radio moet starten.
Is het mogelijk de radio automatisch te laten starten?
Je moet hem inderdaad starten, hier kun je terugvinden hoe je het script automatisch kunt starten: https://raspberrytips.nl/python-script-automatisch-reboot/
Mooi werk!
Er is een volledig Internet Radio programma van http://www.bobrathbone.com/raspberrypi_radio.htm beschikbaar.
Bob Rathbone
9 maart 2017 om 09:26 | Beantwoorden
Mooi werk!
Er is een volledig Internet Radio programma van http://www.bobrathbone.com/raspberrypi_radio.htm beschikbaar.
link werkt niet
sudo apt-get install python3-pifacecad
geeft bij mij
E: Unable to locate package python3-pifacecad
Hi ,
Ik krijg een waslijst aan fouten , graag advies a.u.b
Groet Patrick
pi@raspberrypi:~ $ sudo python3 radio.py
Traceback (most recent call last):
File “radio.py”, line 185, in
cad = pifacecad.PiFaceCAD()
File “/usr/lib/python3/dist-packages/pifacecad/core.py”, line 50, in __init__
self.init_board()
File “/usr/lib/python3/dist-packages/pifacecad/core.py”, line 80, in init_board
h=self.hardware_addr, b=self.bus, c=self.chip_select))
pifacecad.core.NoPiFaceCADDetectedError: No PiFace Control and Display board detected (hardware_addr=0, bus=0, chip_select=1).
Hij Werkt !!!
Hi Patrick, ik heb hetzelfde probleem. hoe heb je het opgelost?
LIRC bleek niet standaard mee geïnstalleerd te zijn…
Deze heb ik handmatig toegevoegd.
“`python
pi@raspberrypi:~ $ sudo python3 radio.py &
[1] 2540
pi@raspberrypi:~ $ Traceback (most recent call last):
File “radio.py”, line 13, in
import lirc
ModuleNotFoundError: No module named ‘lirc’
“`
Nadat ik deze heb toegevoegd met
“`python
sudo apt-get install lirc
“`
krijg ik de volgende foutmelding, iemand een ide hoe ik dit kan oplossen?
“`python
pi@raspberrypi:~ $ sudo python3 radio.py &
[2] 3146
pi@raspberrypi:~ $ Traceback (most recent call last):
File “radio.py”, line 13, in
import lirc
File “/usr/lib/python3/dist-packages/lirc/__init__.py”, line 7, in
from .client import get_default_lircrc_path
File “/usr/lib/python3/dist-packages/lirc/client.py”, line 38, in
import _client
ModuleNotFoundError: No module named ‘_client’
“`
[code]
pi@raspberrypi:~ $ sudo python3 radio.py &
[2] 3146
pi@raspberrypi:~ $ Traceback (most recent call last):
File “radio.py”, line 13, in
import lirc
File “/usr/lib/python3/dist-packages/lirc/__init__.py”, line 7, in
from .client import get_default_lircrc_path
File “/usr/lib/python3/dist-packages/lirc/client.py”, line 38, in
import _client
ModuleNotFoundError: No module named ‘_client’
[/code]