element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • Members
    Members
    • Benefits of Membership
    • Achievement Levels
    • Members Area
    • Personal Blogs
    • Feedback and Support
    • What's New on element14
  • Learn
    Learn
    • Learning Center
    • eBooks
    • 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
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Dev Tools
    • Manufacturers
    • Raspberry Pi
    • RoadTests & Reviews
    • Avnet Boards Community
    • Product Groups
  • 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
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • 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
Raspberry Pi Projects
  • Products
  • 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
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
Raspberry Pi Projects requires membership for participation - click to join
Blog Post Actions
  • Subscribe by email
  • More
  • Cancel
  • Share
  • Subscribe by email
  • More
  • Cancel
Group Actions
  • Group RSS
  • More
  • Cancel
Engagement
  • Author Author: fvan
  • Date Created: 18 Jan 2014 4:18 PM Date Created
  • Views 2385 views
  • Likes 7 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

Top Comments

  • fvan
    fvan over 8 years ago in reply to dragonstyne +1
    There might be a better alternative by now (maybe internet radio distros ??), but back in January, this is how I tackled it Frederick
  • mcb1
    mcb1 over 7 years ago in reply to fvan +1
    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…
  • Former Member
    Former Member over 7 years ago +1
    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…
  • fvan
    fvan over 6 years ago in reply to Former Member

    The script was written for piface control & display 1.

     

    It seems to fail at loading the module, which probably has a different name.

    You'll have to update the script to use the module for the piface 2 instead of the piface 1.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • Former Member
    Former Member over 6 years ago

    I have got a piface display 2, when I try to run the script I have an error

     

    Traceback (most recent call last):

      File "/python/radio.py", line 131, in <module>

        cad = pifacecad.pifacecad()

    AttributeError: 'module' object has no attribute 'pifacecad'

     

    I have the same problem as Jaroslaw

     

    Please Help

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • Former Member
    Former Member over 6 years ago

    I have got a piface display 2, when I try to run the script I have an error

     

    Traceback (most recent call last):

      File "/python/radio.py", line 131, in <module>

        cad = pifacecad.pifacecad()

    AttributeError: 'module' object has no attribute 'pifacecad'

     

    How to do this right, how to write the script?

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • Former Member
    Former Member over 7 years ago in reply to fvan

    You can find the explanation here: https://docs.python.org/3/library/subprocess.html#frequently-used-arguments

     

    subprocess.check_output(args, *, input=None, stdin=None, stderr=None, shell=False, universal_newlines=False, timeout=None)

    By default, this function  will return the data as encoded bytes. The actual encoding of the output data may depend on the command being invoked, so the decoding to text will often need to be handled at the application level.

    This behaviour may be overridden by setting universal_newlines to True as described below in Frequently Used Arguments.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • fvan
    fvan over 7 years ago in reply to Former Member

    Thanks Erwin! I updated the Gist, this should now be reflected in the blog post as well.

    • 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 © 2023 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.

ICP 备案号 10220084.

Follow element14

  • Facebook
  • Twitter
  • linkedin
  • YouTube