Although the CP2102 serial adapters are both affordable and easily available, there is only one problem: their serial number is fixed at “0001″ (at least the ones I bought myself). If you want to use more than one of these devices simultaneously on a Linux PC (eg Raspberry) you will have difficulties to create the udev roles to uniquely distinguish each adapter. Fortunately, the remedy is to re-assign each device a unique serial number. This is feasible using a program provided by the same manufacturer of the chip CP2102 (SiLabs). The package can be downloaded from the addresses at the end of this post. Inside the zipped downloaded file you will find the Windows\CP21xxCustomizationUtility folder which must be decompressed on your hard-disk (the package also includes versions for Linux and Mac users). Run the file CP21xxCustomizationUtility.exe, enter the new serial number into the “Serial” field, then click over “Program Device” to program the device (wait until the process is done and the data are verified). For my own purposes I also modified the Product Description (in this case it was shortened to “CP2102″). Simple and useful tool!
Making some modifications to some nice Python examples found on the Internet (Fuzzy Logic Robots, python-mpd documentation, raspi-hd44780 by Irvick) I was able to make a very basic, but fully working, standalone RPI Web Radio receiver.
Here is the complete wiring sketch:
In the above sketch, pin 1 of the LCD is the leftmost one. The rightmost 2 pins (15 and 16) are for the backlight connections. The LCD works at 5V. A 2 lines x 40 characters display was employed, because the titles and the station-ID are generally long. If a smaller display is being used (e.g. 16/20 characters), some modifications to the LCD program are necessary. Adjust the small 10 kOhm variable resistor to get the best LCD characters contrast.
S1 and S2 are used to move up and down through the channels, S3 and S4 to adjust the volume level. The pull-up resistors are all connected to the 3.3V power source. Idea: the four pushbuttons may be connected to a simple remote control circuit.
Take care not to short out each-other the 5V and the 3.3V outputs coming from the RPI and double-check the wiring before powering-up the RPI.
For simplicity, two independent programs have been made: one starts mpc and handles the four pushbuttons, while the other one handles the LCD (updated every 3 seconds). Both programs run in background.
The name of the playlist used by mpc is embedded into the program. The playlist is named “mymy” (see below).
MPD/MPC must be already be installed as described in Part 1.
1. download the python programs and change the file permissions:
mkdir /home/pi/rpi_web_radio cd /home/pi/rpi_web_radio wget http://www.gmpa.it/resources/rpiwebradio/radio.btn.py wget http://www.gmpa.it/resources/rpiwebradio/radio.lcd.py sudo chmod +x radio*
2. download the sample playlist “mymy” then check/change the file permissions and the owner:
sudo cd /var/lib/mpd/playlists/mymy.m3u sudo wget http://www.gmpa.it/resources/rpiwebradio/mymy.m3u sudo chown mpd:audio /var/lib/mpd/playlists/mymy.m3u sudo chmod 644 /var/lib/mpd/playlists/mymy.m3u
3. download the following programs into /etc/init.d/ then change the files permissions:
sudo wget -O /etc/init.d/radio_btn http://www.gmpa.it/resources/rpiwebradio/radio_btn sudo wget -O /etc/init.d/radio_lcd http://www.gmpa.it/resources/rpiwebradio/radio_lcd sudo chmod +x /etc/init.d/radio_btn sudo chmod +x /etc/init.d/radio_lcd
4. make the programs run automatically at boot:
sudo update-rc.d radio_btn defaults sudo update-rc.d radio_lcd defaults
If needed, the two control programs can be manually stopped/started:
sudo /etc/init.d/radio_btn stop sudo /etc/init.d/radio_btn start
sudo /etc/init.d/radio_lcd stop sudo /etc/init.d/radio_lcd start
To stop the automatic program execution at boot:
sudo update-rc.d -f radio_btn remove sudo update-rc.d -f radio_lcd remove
The Raspberry, wired to the network (ethernet or wifi), should automatically start playing and the LCD should show the song title and the station name at every reboot.
Along with their conventional RF transmitters, nearly all major radio stations now broadcast their programs through the Internet (Streaming Media). Also, many web-radios are exclusively Internet-based.
Being cheap and small, transforming the Raspberry PI into an Internet radio player was really tempting. Adding a wireless adapter, plus a handful of cheap components, the RPI may easily be transformed into a standalone “receiver”.
This first article deals with the installation of some command-line programs: MPD, Music Player Daemon, MPC (Music Daemon control-program) and python-mpd. These programs can easily interact with any user-written programs.
The following setup was tested under a fresh installation of the latest Raspbian distro (do sudo apt-get update and sudo apt-get upgrade before starting).
Download and install the required packages from the repository:
sudo apt-get install mpd mpc python-mpd
The setup is done, so let’s test the “receiver” and make it play. Execute MPC:
it should reply:
volume: 80% repeat: off random: off single: off consume: off
Good, it should work.
MPC holds the list of “stations” on a playlist. It’s time to add the first “radio” to the playlist, so enter:
sudo mpc add http://mp2.somafm.com:2666
Inside the playlist, each station is identified by a number, starting from 1 and increasing as we enter the radios one after another. Having only one station, make it play entering:
sudo mpc play 1
MPC should reply with:
[playing] #1/1 0:00/0:00 (0%)
volume: 80% repeat: off random: off single: off consume: off
and… if an headphone or the speakers are plugged into the RPI’s audio socket, we should now hear the radio playing.
Deleting an entry from the playlist, the list is shifted backwards (so, if the 4th was deleted, the 5th will become the 4th, the 6th will become the 5th, an so on).
The volume can be adjusted with the following command:
sudo mpc volume (followed by any number from 0 to 100)
and again MPC will reply with some useful informations:
Space Station Soma: Tune in, turn on, space out. Ambient and mid-tempo electronica. [SomaFM]: I:cube – Untitled 3
[playing] #1/1 2:41/0:00 (0%)
volume:100% repeat: off random: off single: off consume: off
Let’s now add another nice station, then query the status of MPC:
sudo mpc add http://scfire-a03.websys.aol.com sudo mpc
The reply should be something similar to:
Absolutely Smooth Jazz – SKY.FM – the world’s smoothest jazz 24 hours a day: LIVE NOW FROM LONDON! JIMI KING WITH VIDEO! November 4-2012
[playing] #2/2 0:45/0:00 (0%)
volume:100% repeat: off random: off single: off consume: off
Now we can save our playlist entering:
sudo mpc save mylist
The list, named “mylist” in the above example, is saved under /var/lib/mpd/playlists/ and the full-name is mylist.m3u. More than one list can be created and loaded when needed.
If the playlist exists, it must be deleted before saving it, using:
sudo mpc rm mylist
Among the many MPC commands, the most useful ones are:
sudo mpc load mylist sudo mpc lsplaylists (show the available .m3u playlists) sudo mpc playlist (show the playlist content) sudo mpc clear (to empty the playlist)
To stop the player enter:
sudo mpc stop
Here is a very short and simple Python program that gets the Station Name and the Song Title from MPD and prints these informations on the command-line:
#!/usr/bin/python import mpd client = mpd.MPDClient() client.connect("localhost", 6600) cs = client.currentsong() if 'title' in cs: SongTitle = cs['title'] elif 'file' in cs: SongTitle = cs['file'] print ('Song Title: ' + SongTitle) print ('Station Name: ' + cs['name'])
Download and run the above program:
wget http://www.gmpa.it/resources/py_mpd.py chmod +x py_mpd.py ./py_mpd.py
The program works only when MPD is tuned-in and playing (through mpc play).
Looks quite simple and promising, isn’t it ?
Python is a very popular interpreted programming language, largely used among the Raspberry users community (and not only). Many example programs and other useful resources can be easily found on the internet. It is a good alternative to more efficient but more complicated languages, like C. Python 2.7 seems to be more popular than the latest version 3.3.
An appropriate Python module, named pyserial, must be installed on the RPI to enable Python to access the UART.
How to install pyserial:
1. download the software into /tmp:
sudo wget http://pypi.python.org/packages/source/p/pyserial/pyserial-2.6.tar.gz
2. extract the installation package:
sudo tar zxvf pyserial-2.6.tar.gz
3. install it:
sudo cd pyserial-2.6
sudo python setup.py install
Python is now ready.
In the above picture, the 5V and 3.3V pins can be used to supply low power devices (with care).
Here is a very simple Python program to test the SWiTh Gateway:
#!/usr/bin/python import serial import time # Raspberry Pi serial port port = "/dev/ttyAMA0" # Open the serial port myser = serial.Serial(port, 9600, timeout=1, bytesize=8, parity='N', stopbits=1, xonxoff=False, rtscts=False, dsrdtr=False) # Give the serial port some time to settle time.sleep(0.5) # If the serial port is open then proceed if myser.isOpen(): x = myser.write("@0VER\r") serial_received = myser.readline() myser.close() print (serial_received) else: print("Error opening " + port)
From the Raspberry command-line, download the above program:
Make it executable:
chmod 774 swith_test.py
Launch te program:
If everything goes right, SWiTh should reply:
By default, under Raspbian, the RPI’s UART is used as a serial console. Although very useful, this feature must be disabled to allow user programs to use it.
How to disable the RPI serial console:
1. edit /etc/inittab:
sudo nano /etc/inittab
2. comment-out last line (adding a ‘#’ as first character) like in the example:
#T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100
3. save the file
4. mount the SD-CARD into the file-system:
sudo mount /dev/mmcblk0p1 /mnt
5. edit /mnt/cmdline.txt:
sudo nano /mnt/cmdline.txt
6. delete the following text:
7. the final result is the following string:
dwc_otg.lpm_enable=0 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait
8. save the file and umount the SD-CARD:
sudo umount /dev/mmcblk0p1
9. add the users pi and root to the dialout group:
sudo adduser root dialout
sudo adduser pi dialout
10. reboot the RPI
sudo shutdown -r now
The serial port is now free and its device name is /dev/ttyAMA0
To interface SWiTh to other electronic devices (apart small LEDs, switches and other basic components), some form of interfacing is needed. This is necessary when we are coupling SWiTh to devices working at different voltage levels or when driving high-power loads (e.g. lamps, relays, etc.).
For safety, an optocoupled interface is mandatory if we need to drive loads connected to the 230V mains.
A series of simple, practical examples follows. These should cover the most common situations and can be used with any similar systems.
Example 1: this circuit allows SWiTh to drive a low-power relay. Very few components are needed. The input resistor insures a stable logic L when the input is floating (the input impedance of the MOSFET is very high). The diode protects the MOSFET against the voltage spikes generated across the relay coil when this latter is powered on and off.
Example 2: a common NPN transistor is used instead of a MOSFET (see Ex. 1).
Both circuits turn on the relay when a high level (5V) is applied to the input.
Example 3: a PNP transistor drives a relay.
This circuit is useful when an inverted logic is needed: the relay is OFF when a 5V voltage is applied to the input and ON when the input is floating or logic zero.
Example 4: a circuit using a very useful and popular IC, the ULN2003.
This ICs can drive different loads of various types: relays, lamps, motors, even at high voltages and currents.
Each channel is rated at 500mA, that can be paralleled for higher demands.
Each driver has its own suppression diode for driving inductive loads. A very handy IC !
Example 5: a digital input circuit using an optocoupler,
useful when the electrical separation of two interconnected circuits is needed for safety reasons.
For an effective isolation the two devices must not share any signal/voltage (including ground).
Example 6: an optocoupled digital output circuit.
This circuit can be used to drive low-voltage devices.
This circuit is inverting: the output goes low when the input goes high.
If the interfacing circuit has its own pull-up resistor just remove the 4.7 kΩ collector resistor.
Do not share any signal or voltage between the left and the right circuits.
Example 7: this circuit can be used to drive devices connected to the mains or high-current switching (using a suitable relay).
At the cost of a little more complex circuit you get an interface that can safely drive high-voltage devices.
A medium- or high-power relay may need the use of a medium power NPN transistor.
Each Satellite has 15 digital I/O pins and 4 analog inputs. 13 digital I/O pins are usable on the Gateway. The maximum number of Satellites is 26: this means a total of 390 bidirectional I/O ports and 104 analog inputs (plus the ports on the Gateway).
Only four pins of the RPI’s GPIO port P1 are used: two for the serial port and two for the power supply.
The dialogue between the Raspberry and the Gateway is based on human-friendly ASCII strings. This very simple protocol allows the users to write their own applications in virtually any programming language.
Some of the available I/O pins can be dedicated to special functions: a pulse-counter input (for use with an energy-meter), a serial output (on the Satellites only) and 2 PWM outputs. SWiTh is also ready for temperature and relative-humidity measurements using a SHT11 or SHT15 sensor. These extra functions can be disabled, if not needed.
The Gatewy offers 13 digital I/O pins and 4 analog inputs.
Two on-board LEDs can be used to monitor the wireless communications. SWiTh can be upgraded using the built-in ICSP port.
SWiTh is a personal project. It is not open-source.
A user-guide is available upon request (mail to email@example.com).
Any inquiries are welcome and any suggestions will be appreciated.
SWiTh can be used with any ordinary PC.