element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products & Partners
    Products & Partners
    • Arduino
    • Avnet & Tria Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • About Us
    About the element14 Community
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Japan
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      •  Vietnam
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
Raspberry Pi Projects
  • Products & Partners
  • Raspberry Pi
  • Raspberry Pi Projects
  • More
  • Cancel
Raspberry Pi Projects
Blog Internet Radio Player with Raspberry Pi, PiFace CAD and MPD/MPC
  • Blog
  • Documents
  • Events
  • Polls
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
Join Raspberry Pi Projects to participate - click to join for free!
  • Share
  • More
  • Cancel
Group Actions
  • Group RSS
  • More
  • Cancel
Engagement
  • Author Author: fvan
  • Date Created: 18 Jan 2014 4:18 PM Date Created
  • Views 9736 views
  • Likes 8 likes
  • Comments 22 comments
  • python
  • rpibeginner
  • radio
  • raspberrypi
  • raspberry_pi_projects
  • piface
Related
Recommended

Internet Radio Player with Raspberry Pi, PiFace CAD and MPD/MPC

fvan
fvan
18 Jan 2014

  • Project Components
  • Required Software
  • Python Script
    • Code explanation
      • Custom bitmaps
      • MPC status
      • Event listener
    • Full code
    • Autostart
  • Demo

 

I recently worked with the PiFace Control and Display for my Santa Catcher, in which I used the PiFace CAD as an IR receiver and display without using any of the local controls.

So I decided to create an Internet Radio player which could be controlled using the PiFace CAD's buttons.


The result is mainly a software project, but I had fun diving a little deeper into the Python programming language.

 

Project Components

 

For this project, I used following components:

 

  • Raspberry Pi Model B running Raspbian
  • PiFace Control and Display
  • Enclosure for Pi and PiFace CAD
  • Wi-Pi
  • Portable speaker
  • 5V 1A micro USB power supply

image

 

Required Software

 

As mentioned earlier, I started off by using Raspbian with wifi and ssh enabled.

 

These were the modifications on top of Raspbian to get everything I needed up and running:

  • Updated Raspbian to latest version
    • sudo apt-get upgrade
      sudo apt-get update
                     

  • Enabled SPI support for the PiFace CAD
    • sudo raspi-config
                     

    • Select option 8: "Advanced options"
    • Select option A5: "SPI"
    • Select "Yes"
    • Select "Finish" to exit
  • Installed the mpd (music player daemon) and mpc (music player controller) applications
    • sudo apt-get install mpd mpc
                     

 

Python Script

 

From this point on, everything is done via Python.

 

Using Python, I am able to control the mpc application using the PiFace CAD's buttons and display the status on its LCD.

 

Code explanation

 

You can find the full code a bit further down, but I'll try to explain some bits of code here.

 

Custom bitmaps

 

I wanted to display some icons on the LCD to clarify the meaning of some values being displayed or to visualise the current state.

It is possible to define "custom bitmaps" to be displayed. This tool comes in very handy to create your own. (be sure to select 5x8 when using PiFace CAD)

 

Following function defines and stores custom bitmaps:

 

def custom_bitmaps():
    speaker = pifacecad.LCDBitmap([1,3,15,15,15,3,1,0])
    play = pifacecad.LCDBitmap([0,8,12,14,12,8,0,0])
    stop = pifacecad.LCDBitmap([0,31,31,31,31,31,0,0])
    playlist = pifacecad.LCDBitmap([2,3,2,2,14,30,12,0])

    cad.lcd.store_custom_bitmap(0, speaker)
    cad.lcd.store_custom_bitmap(1, play)
    cad.lcd.store_custom_bitmap(2, stop)
    cad.lcd.store_custom_bitmap(3, playlist)
           

 

The custom bitmaps can then be displayed on the LCD as follows, using the id of the corresponding bitmap:

 

cad.lcd.write_custom_bitmap(0)
          

 

MPC status

 

In order to display correct information on the LCD (volume & playlist position and size), I rely on the information coming from the mpc application itself.

 

A sample output looks as follows:

 

pi@piRadio ~ $ mpc status

mms://streaming.q-music.be/QBE_HI
[playing] #1/2 1187:22/0:00 (0%)
volume:100%   repeat: off   random: off   single: off   consume: off
          

 

Using Python, it is possible to execute that command, take the output and parse the interesting bits of information.

 

Playlist:

 

def display_playlist():
    playlist = subprocess.check_output("mpc status | grep playing", shell=True, stderr=subprocess.STDOUT)
    playlist = playlist[playlist.find("#")+1:playlist.find("/")+2]


    cad.lcd.set_cursor(4, 1)
    cad.lcd.write_custom_bitmap(3)
    cad.lcd.write(playlist)
          

 

This bit of code executes the "mpc status" command and only keeps the part of the output containing the word "playing".

Then, it parses the output and keeps the part after "#" and up to two character after the "/". This covers playlists of up to 99 items.

 

The playlist information is then written to the LCD, with an icon to clarify the meaning of the value.

 

Volume:

 

def display_volume():
    volume = subprocess.check_output("mpc status | grep volume", shell=True, stderr=subprocess.STDOUT)
    volume = volume[7:volume.find("%")+1]

    cad.lcd.set_cursor(12, 1)
    cad.lcd.write(volume)
          

 

Similar to the playlist parsing, this bit of code takes the output of the "mpc status" command containing the word "volume".

It parses the characters after the word "volume" up to and including the "%" character.

 

The volume is then written to the LCD.

 

Event listener

 

The script needs to know when a button on the PiFace CAD has been pressed and trigger the appropriate action.

 

I recuperated this bit of code from one of the PiFace examples and extended it to fit my application.

 

First, a listener is defined which will register which button has been pressed:

 

listener = pifacecad.SwitchEventListener(chip=cad)

for i in range(8):
        listener.register(i, pifacecad.IODIR_FALLING_EDGE, update_pin_text)

listener.activate()
         

 

The listener executes the specified function in which it execute different actions depending on the button that was pressed:

 

def update_pin_text(event):
        global channel_pos
        global status
        if(event.pin_num == 0):
                status = "playing"
                os.system('mpc play')
                event.chip.lcd.set_cursor(0, 1)
                event.chip.lcd.write_custom_bitmap(1)
                event.chip.lcd.write(" ")
                display_channel()
                display_playlist()

        elif(event.pin_num == 1):
                status = "stopped"
                os.system('mpc stop')
                event.chip.lcd.set_cursor(0, 1)
                event.chip.lcd.write_custom_bitmap(2)
                event.chip.lcd.write(" ")
                clear_channel()

        elif(event.pin_num == 2 and status == "playing" and channel_pos > 1):
                os.system('mpc prev')
                clear_channel()
                display_channel()
                display_playlist()

        elif(event.pin_num == 3 and status == "playing" and channel_pos < len(channelLink)):
                os.system('mpc next')
                clear_channel()
                display_channel()
                display_playlist()

        elif(event.pin_num == 4):
                global backlight
                if(backlight == 1):
                        event.chip.lcd.backlight_off()
                        backlight = 0
                else:
                        event.chip.lcd.backlight_on()
                        backlight = 1

        elif(event.pin_num == 5):
                sleep(1)

        elif(event.pin_num == 6):
                os.system('mpc volume -5')
                display_volume()

        elif(event.pin_num == 7):
                os.system('mpc volume \+5')
                display_volume()

        else:
                sleep(1)
         

 

Above actions correspond to following button mapping:

image

 

Full code

 

The code still requires to be cleaned up a little, but it should be clear what I'm trying to do.

 

 

Autostart

 

The script needs to be started automatically after the system booted. This is done by adding following entry to /etc/rc.local:

 

sudo python /home/pi/radio.py &
    

 

Demo

 

image

 

You don't have permission to edit metadata of this video.
Edit media
x
image
Upload Preview
image

  • Sign in to reply
  • e14 Contributor
    e14 Contributor over 11 years ago

    Cool introduction.
    I had, however a "TypeError: expected an object with the buffer interface" on every line with a find() method on the return of the subprocess() method.

    Reason: subporcess() always returns bytecode unless you give it an argument 'universal_newlines=True'.

    So, eg the function display_volume()


    is now:

    def display_volume():

      volume = subprocess.check_output("mpc status | grep volume", shell=True, stderr=subprocess.STDOUT)

      volume = volume[7:volume.find("%")+1]

     

      cad.lcd.set_cursor(12, 1)

      cad.lcd.write(volume)

     

    and it should be:

    def display_volume():

      volume = subprocess.check_output("mpc status | grep volume", shell=True, stderr=subprocess.STDOUT, universal_newlines=True)

      volume = volume[7:volume.find("%")+1]

     

      cad.lcd.set_cursor(12, 1)

      cad.lcd.write(volume)

     

    Add the argument in all occurences of your code and you'll be fine..

     

    ERwin

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • mcb1
    mcb1 over 11 years ago in reply to fvan

    There are some notes here.

    http://www.raspberrypi.org/documentation/configuration/device-tree.md

     

    and discussions here

    http://www.raspberrypi.org/forums/viewtopic.php?f=28&t=97314

     

    It seems that the new distribution has caused some unexpected side effects.

    I'm sure they are being ironed out ... but how long before the fix is applied is ???

     

    Mark

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • fvan
    fvan over 11 years ago in reply to rudibarani

    Hi Phillip,

     

    that's a good question. I'm not familiar with "device tree" and what the impact might be on my code. I'll have to do some searching around to figure out how to solve this issue image

    Let us know should you find something as well. It's already a great step forward that you managed to figure out the problem is introduced when enabling device tree.

     

    Frederick

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • rudibarani
    rudibarani over 11 years ago

    Hi Frederick,

    I had this great script running for some time as our internet radio on a raspberry pi + piface. Since a recent update of the raspberry pi introduced device tree, I can only use it if I disable the device tree using raspi-config. Took me some time to figure this out.

    As disabling the device tree is mentioned to be a temporary feature - what do I have to change to keep it running with device tree enabled? I don't know much about programming for raspi pi yet - but I am willing learn it.

    Thank you very much!

    Phillip

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • e14 Contributor
    e14 Contributor over 12 years ago

    If I wanted to modify the code so that the first line of text reflected the station information and he second scrolled the name of the song, h

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
<>
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2026 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube