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
.