I used to love playing around with my Dad's big 1940's Zenith radio, tuning in to stations across America and around the world. The charm of that old Zenith stuck with me across the years: that beautiful dial, the tactile connection to those tuning knobs. Zenith was the king of "User Interfaces" back then. These days, I like to follow others who have vintage radio projects (BIG shout out to Tinkernut, here and youtube) and longed to make a retro radio just for me - to recreate those good old times.
So here it is - now, in an adorably convenient size.
I researched quite a few old radios. Many, like "Cathedral" radios, were very cool looking, but could be hard to model in 3D, print and assemble. Finally, I settled on the classic Zenith "Cube" 5R216 model. I wasn't trying to faithfully replicate the 5R216. I just wanted something that would suggest the look and feel of it.
Advanced - 3D printing, soldering, code installs.
There's a significant amount of soldering to this project, some a little challenging. The real work begins when assembling the components into the 3D printed case. The case is less than 5 inches/120mm square (if you dont scale the 3D print up). If you have large hands you may have a struggle. If you have a larger build-platform 3D printer, I strongly recommend you scale up the box and face - but you'll have to keep the other dimensions the same.
CostAround $100 USD
Build Time2 days, not counting 3D print. 3D print done in two main pieces, 6.5 hours and 11.5 hours, along with 2x 1 hour prints.
AcknowledgementThis project would not have been possible without the contributions and support of the Open Source/Maker Community. I have noted "key contributors" in the Team section of this article. For the sake of brevity and clarity, I will present a short version of their work. I will leave links to the original source material. Please take a few moments to explore and support their great work.
OverviewWhen you're finished with this project, you'll have a working internet streaming radio that's powered by the popular Logitech Media Server(LMS). The client for LMS, SqueezeLite, is installed on the same Raspberry Pi, making a complete stand-alone music system. You'll be able to tune in 5 (or many more, with some minor code tweaks) of your favorite Pandora channels, internet radio stations, or playlists, using the tuning knob. You can also use a supplied web page to control the music, or use IOS/Android Apps. The PI TFT display will simulate a radio dial that works with the tuning knob. The tuning knob will also let you select different screens: an art deco clock, or cover art for Now Playing. A tune button press will toggle pause/play, cycle through display screens and restart the SqueezLite player. The other knob will turn the device on and off, and control volume.
If you want to use Pandora, you must have a paid account.
How it WorksThe pi3d graphical software draws the radio dial and needle, as well as an art deco clock and Now Playing art. When the tune knob turns the needle, its location (based on degrees of a circle) is looked up in a dictionary. The pylms software is a python wrapper for LMS commands. If a Favorite is in the dictionary at a pre-mapped location, pylms sends a play request to Logitech Media Server (LMS). LMS then sends a request to the SqueezeLite player to play the Favorite.
The tuning knob is also a push button. A short press toggles pause/play through pylms. A long press triggers a screen change to the clock or Now Playing art, or back to the radio dial. Pi3d displays the clock. The Now Playing art and track title is passed from LMS to pi3d to draw. Turning the volume knob up/down sends a request through pyLMS. The volume knob has a push button, too. It can trigger a safe shutdown/power-on/reset. See the Operations section below for more details.
About pi3d:
If you haven't seen this powerful software in action, check out the intro on YouTube. The miniz project uses only a trivial amount of its capabilities. Pi3d can draw detailed, immersive, moving 3D landscapes. And, because it uses the Raspberry Pi GPU, it even works on the PI zero.
ProcessTest the hardware/software modules while building to make sure everything is working properly, Here's the workflow:
- Download/configure/test the required software
- Solder the components and test. Back to software. Repeat as needed.
- Print the 3D parts. Post-process to taste
- Test the completed hardware before final assembly into the case
- Assemble hardware in the 3D case
- Finally - great joy listening to radio station K-YOU (W-YOU East of the Mississippi)
Step 1: Raspbian Stretch Lite
- Download Debian Stretch Lite
- Install to micro sd card. This is a good set of instructions.
- Two files need to be added to the /boot directory on the new sd image card.
On Windows, create an empty file called ssh and a file named wpa_supplicant.conf with the contents shown (second box) below
For Linux/Mac:
sudo touch ssh
sudo nano wpa_supplicant.conf
And for Windows/Linux/Mac, enter and save the following, changing ssid and psk to your router's ssid and password:
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
country=US
network={
ssid="Your network SSID"
psk="Your WPA/WPA2 security key"
key_mgmt=WPA-PSK
}
After getting Raspbian configured, run headless (no monitor/keyboard/mouse) - insert the SD card into your pi and power up. Allow a couple of minutes for the pi to fully start up. If you are running Windows, download the putty terminal emulator to connect to the pi with SSH. You should be able to find the IP address from your router's web page. And, to SSH in from a Mac/Linux terminal:
ssh "192.168.0.xxx" -l pi
Where "192.168.0.xxx" = your pi's IP address (without quotes). The default password is raspberry. Be sure to change it on first login. You should also configure other settings, as gerrelt recommends, via:
sudo raspi-config
- Network Options/Hostname (I named my host miniz)
- Localisation Options
- Advanced Options - Expand Filesystem and Memory Split
- For Memory Split, change the value to 128 (needed for pi3d, later)
After completing the config, reboot. When you sign back in, update packages and set up git:
sudo apt-get update
sudo apt-get upgrade # This step takes a long time!
sudo apt-get install git-core
git clone http://github.com/thisoldgeek/miniz
Cloning this github repository will create a new directory under /home/pi/miniz. This miniz directory contains all the assets needed for this project, including setup scripts and documents.
Step 2: Prepare Initial HardwareSolder the raspberry pi stacking header to the pi zero. This will connect the mono amp and speakers, via a breadboard, to the pi for sound installation testing. Be careful of orientation. The pi Zero header pins will be inserted into the back of the piTFT. So, all the pins on the pi are upside-down and backwards! This is confusing and can cause errors hooking things up.
This diagram should help. Turn the pi so the back of the pi is facing up, with the large silk-screen of the raspberry facing you:
Insert the stacking headers so the female headers are pointed up, facing you. Fasten the headers down with blue painter's tape or blue tack. Make sure they are fully inserted and 90 degrees to the board. Turn the pi over to solder.
I found soldering the stacking headers difficult. I had to re-do several bridged solder pins and some that had poor joints. My suggestion is to go slowly and carefully, first soldering the inside pins, then the outside. Work in a single direction, finishing one row of pins at a time.
Next, set up the mono amplifier, a quick soldering job. Adafruit has a complete write-up on the amp at learn.adafruit.com. Follow along in that tutorial and complete all the sections from Overview through Raspberry Pi Test, but Raspberry Pi Setup is essential. To complete the test, you must have your speaker soldered up with two lengths of wire at least 3 inches/80mm long. Heat shrink applied over the joints offers good strain relief. Remember that you have to run the setup script twice!
When the mono amp is attached to a breadboard, you may experience some crackling noises. That's because the jumpers may be loose in the breadboard. Try pushing/holding the breadboard wires and you may get cleaner sound. This will be fixed when you have proper solder connections to the bonnet. Also, note that the Adafruit tutorial says to "Solder in both pins with plenty of solder!" on the amp speaker connections.
I chose the GRS 3FR-4 speaker from parts-express because it had mounting holes and good sound frequency range. It mounts directly to the 3D case with screws and nuts, to keep the vintage look. Won't be confused with audiophile quality, but enjoyable to listen to.
Check the alsa sound controller:
sudo alsamixer
It should look like this:
To get the rotary encoders to fit properly into the case, cut the side mounting tabs and carefully bend the solder pins parallel to the base:
Wire up the rotary encoders, using 2 black wires (GND) and 3 different colored wires for the other pins on each encoder. The different colors will help you tell which encoder connects where, when the encoders are mounted out of sight below the piTFT. Cut the wires about 7 inches/18 cm long. Tin both the pins and the wires with a good amount of solder. For each wire, press the wire into the pin with your soldering iron until solder flows. Remove the iron and continue holding down the wire with your other hand until solder cools. Helping Hands are your friends.
I used heat shrink for strain relief. Gently bend the wires up at a 90 degree angle away from the encoder shaft to fit into the case. Keep your thumb on the pins to prevent the pins from breaking while you make the bend.
Be careful handling the encoder wires after bending! I broke a pin off from rough handling and had to re-do an encoder.
Your finished encoders should look something like this:
There's a test program included in the miniz directory, test_rotary_switches.py. Connect the encoders to the pi female headers according to the pinouts in that program (TUNE and VOLUME).
To test:
cd ~/miniz
python3 test_rotary_switches.py
Step 3: Setup Music SoftwareThe original source for the following scripts is poster gerrelt. Gerrelt has written excellent posts on installing Logitech Media Server (LMS) and Squeezlite.
Gerrelt said Spotify was a possibility on this setup. Alas, Spotify support for LMS ceased on July 19, 2017.
Use the scripts in the /home/pi/miniz/scripts directory (created by the git clone) for LMS and SqueezeLite installs (run these one by one):
cd ~/miniz/scripts
chmod +x *.sh
./LMS_install.sh
./squeeze_install.sh
The miniz uses a different sound device from the gerrelts tutorial. The Adafruit install software will set up the mono amplifier as an audio source, specifically dtoverlay=hifiberry-dac in the /boot/config.txt.
The default hifiberry-dac works without the changes gerrelt needed. HOWEVER: You need to comment out a line in one of the gerrelts scripts to get squeezelite to run. Also, UNcomment the line for SB Server as shown below. Make these changes for the LMS/SqueezeLite to run properly:
sudo nano /usr/local/bin/squeezelite_settings.sh
##but make sure this line is COMMENTED out like so:
#SL_SOUNDCARD="sysdefault:CARD=ALSA"
# Be sure to UNcomment this line and add your pi IP address, keep the quotes!
SB_SERVER_IP="192.168.0.xxx"
#Then restart the service with:
sudo systemctl restart squeezelite
Before configuring Logitech Media Server, you need to create a directory to store your music. You will be asked which directory to use when you enter the web page. I simply created one called 'music' at the root level, on the miniz:
cd /
sudo mkdir music
Copy some music to this directory to test out the interface in the next steps. Filezilla can copy files, with clients for Windows/Mac/Linux. for playlists:
cd /music
sudo mkdir playlists
To add music from a remote share, such as a NAS unit or a Windows Share:
cd /music
sudo mkdir /music/NAS
sudo chmod 777 /music/NAS
sudo mount -t cifs //192.168.0.xx/music /music/NAS -o user=username,pass=userpassword
where 192.168.0.xx is the address of the remote server/share if you would like this as a permanent share, remaining after reboot:
sudo nano /etc/fstab
# add the line below at end of fstab
//192.168.0.xx/music /media/windowsshare cifs guest,uid=1000,iocharset=utf8 0 0
Step 4: Configure Logitech Media ServerLMS serves an html page for configuration and control. Connect to it from your favorite browser. Use the IP address of your raspberry pi, followed by :9000, eg. - http://192.168.0.xxx:9000
On first run, LMS will prompt for a mysqueezebox.com email and password. Apps like Pandora, TuneInRadio (free streaming radio stations), SOMA and Podcasts require you to create an account on mysqueezebox.com. More on that later. For now, click "skip" at the bottom of the page.
On the next page, navigate to /music (directory created above) and press "Next". Choose a folder for playlists - we created playlists. Click "Next" and then "Finish".
Choose a player from the pull-down in the upper right corner. It's the hostname of your new pi. This should show up automatically if it is your only Squeeze player.
On the left pane, navigate to My Music/Music folder, and hover your mouse over a song or album you want to play. Still in the left pane, but on the right side, three icons will appear. Click on the Play icon to start.
Hey, look at you! You're playing music.
Step 5: AppsIf you'd like to use Pandora or the other Apps I mentioned earlier, you need to sign into mysqueezebox.com and click on "Create an Account". Save your account information - you need to enter it into LMS after your apps are set up. Once you create an account and login, click on "App Gallery" at the top of the page. Pick an app from the list and click the blue "Install App" button at the top right. After that, click Configure.
- For Pandora, enter the username and password you use for Pandora.
- Click on Player Settings. Your player name should appear in the list.
- Set Status to Enabled and set Home to "Display on home menu".
- Don't forget to click on the blue "Save Changes" button at the bottom of the screen.
Logoff from mysqueezebox.com and go back to the LMS web page. At the lower right pane of LMS, click Settings. Click the mysqueezebox.com tab on the next page and fill in the username and password you used to create your mysqueezebox account. When done, click Apply, then Close in the lower right of the screen.
Almost done! Click on Settings again, then the tab for Plugins. Scroll down and make sure there is a check mark next to the Pandora app (or whatever app you set up). Click Apply. As an added check, in the "Author" column for Pandora to the right, there should be a link to Logitech. If you click on that, and you are properly set up, the link will open mysqueezebox.com again in the configuration dialog for Pandora. You can close that and click on Close for the plugin page.
Go back to the LMS Home Page; click on My Apps. You should see Pandora, or other newly-added apps under My Apps. If you don't see it, try refreshing the web page. If that doesn't work, try restarting the logitech media service:
sudo systemctl restart logitechmediaserver
Setting up FavoritesThe radio dial will automatically start playing Favorites if they are linked in a favs dictionary in the miniz.py program.
# format below is degrees:fav_number
# see separate guide to LMS for setting up favorites in https://github.com/thisoldgeek/miniz
favs = {82:0,57:1,30:2,8:3,352:4,333:5}
Favorites can also be played from the LMS web page.
Here's an example for TuneIn Radio Favorites. The TuneIn App in LMS will guide you to selecting a radio station by several criteria. This example uses:
Home > Browse > By Location > North America > United States > California > San Francisco > By Genre > Classical Music
To create the Favorite, hover your mouse over the heart icon at the right side of the left pane, and click it to save as a Favorite.
Go back to the LMS Home page (you can just click on "Home" seen in the image above). You should see the new item added at the end of your list of Favorites.
Note: A Favorite for "on mysqueezebox.com" is always added in this list. The list is zero-indexed based. So, the new Favorite created here is number 6.
Setup the 3.5 inch piTFT for OpenGL using the Adafruit tutorial. Although this is written for Raspbian Jessie, it works for Stretch.
cd
curl -O https://raw.githubusercontent.com/adafruit/Raspberry-Pi-Installer-Scripts/master/pitft-fbcp.sh
sudo bash pitft-fbcp.sh
When the pitft-fbcp.sh starts, choose "4. Configure options manually", and input the following values at the prompts:
Do the piTFT 3.5inch setup using the manual config operation, with HDMI Rotation option 4 and TFT rotation 2, 90 degrees. This will orient the pi zero, when attached to the piTFT, so its power connector is at the lower right.
To suppress text messages on the screen before the miniz service starts, do:
sudo nano /boot/cmdline.txt
And add:
quiet splash loglevel=0 logo.nologo
To the end of the existing text. Also change:
console=tty1
To:
console=tty3
Step 6: Setup Python LibrariesRun this to setup all the libraries:
cd ~/miniz/scripts
./py_libs_install.sh
This is what the script is doing - a lot! Will take awhile.
#!/bin/sh
# run installs with sudo!
sudo apt-get update
sudo apt-get upgrade
cp .distutils.cfg /home/pi/.distutils.cfg
sudo apt-get install python3-pip
sudo pip3 install pi3d
sudo apt-get install python3-pil
sudo apt-get install python3-setuptools
sudo pip3 install pylms
sudo cp player.py /usr/local/lib/python3.5/dist-packages/pylms/player.py
sudo apt-get install python3-numpy
sudo pip3 install RPi.GPIO
There's a documented problem in the pylms player.py module. The line in the script above:
sudo cp player.py /usr/local/lib/python3.5/dist-packages/pylms/player.py
Should fix the problem. Tinkernut recommended the solution gilyes had to the pi "clean shutdown" problem. It's very elegant. Set it up to work with the volume button:
cd ~/miniz/scripts
sudo ./pishutdown.sh
Finally, to get the main UI/radio dial installed:
cd ~/miniz/scripts
sudo ./zdial.sh
sudo systemctl restart zdial
Step 7: Preparing the CaseMy 3D printer is the small/slow/cheap Monoprice Mini Select. I split the body of the case into two parts - face and case - due to the long print times involved. Here are Cura simulations of the face/case prints and also optional custom knob (2 required).
The blue areas are support structures, necessary for speaker grille holes.
There are Cura print settings included in the miniz/docs directory, as well as the STL files.
Finishing the case:
- Remove the support material
- Sand the edges to be attached for face and case
- Use blue painter's tape to hold them together
- Glue in 4x M2.5 standoffs in the mounts provided on the inside of the face. Apply superglue to the threads and the bottom of the standoffs, sparingly. Be careful you don't get superglue into the standoff, will plug it. A little masking tape over the standoff screw hole can help.
- Hot glue the inside - use a steady bead of glue for a neater seam
- Option: Finish with XTC3D
- Option: Print custom Z-logo knobs and bezel
I found removing the grille support challenging. What worked for me: start by pressing down firmly on the entire length of a single grille support to separate it from the case. Then, alternately press/pull the center of the support strip, gradually increasing your force. At times, I thought I was using so much force I might crack the case. Eventually the grille work pulls off in a large chunk. Clean nubs on edges with a diagonal cutter and a thin nail file. The side grille support on the case took about 20 minutes to remove.
Gluing the face to the case:
The case is ready to assemble at this point. I did a little extra, coating the case with one application of XTC3D, and two coats for the face. This is a good product, and the results can be nice - but there are issues:
- Clean your model with dishwashing liquid and make sure it is absolutely dry
- Use in a very well-ventilated area; has an odd odor
- Use nitrile gloves, eye protection and protective clothing like long sleeves
- Working time about 10 minutes
- XTC3D is somewhat self-leveling, but that means it can flow in places you didn't expect - try to keep your coated model horizontal, or vertical over a catch tray, and watch your hand movements!
- XTC3D can flow to edges and curved surfaces. During the working time, I used a toothpick to keep the XTC3D from building up in rounded grille edges
- The results were nice - shiny and smooth. But there were some tiny bubbles and dust inclusions
- Curing time is usually 2 hours. I touched the model when I thought it was cured and left a fingerprint in the case.
Spray paint the optional knobs black. For the Z logos, dab water-based gold metallic acrylic paint on with a very fine brush or a pointed toothpick. The paint will flow just a bit, so watch the edges. Water-based acrylic paint cleans up with a damp rag if applied quickly. I spray painted the bezel with gold metallic and sanded, two applications each. Finally, I applied XTC3D on the knobs and bezel. That really made the gold POP!
Adafruit has produced another great perma-proto board in the bonnet. However, due to the layout of the raspberry pi, pins may be in an awkward location for your particular application/use. Connecting the mono amp, for example, requires pin 18 on one end of the board and pins 19 and 21 on the other. Some thoughtful routing is required!
There's a pin mapping document in miniz/docs for reference.
Split female header into (2) 3-pin pieces and (1) 4-pin piece. There are tips on how to do this on the Adafruit product page.
Solder the wires in this order:
- Double 20 pin male header, short end soldered on "TOP" in diagram
- Female Headers inserted on "TOP" side from diagram
- GND/5V jumpers on "TOP"; the jumpers for #19 and #21 will cover the solder joints for these
- "BOTTOM" wires
The finished board should look something like this:
At this point, it's a good idea to do a final check on the hardware components, before stuffing everything into that tiny case.
- Mount the pi to the piTFT display
- Plug the bonnet into the pi
- Insert the rotary encoder wires into the female headers
- Screw the speaker wires into the mono amp
Should look something like this:
Power UP!
If everything is rosy, you should see this, after about 2 minutes to allow for things to start up:
Okay, you've had your fun. Now take everything apart again so you can put it in the case.
Step 9: Install into the Case- Install rotary encoders first - turn them about a 45 degree angle to the case to allow clearance for the wires around the piTFT
- Route/organize the wires so they won't block mounting the piTFT or the speaker. The tune knob wires will run underneath the piTFT and the speaker
- The Adafruit encoder knobs work fine. The custom knobs need a tiny bit of blue tack in the shaft to give enough travel to the push button. Works.
- Screw the piTFT into the mounts with M2.5 screws
- Insert steel 4/40 screws into the speaker holes, screw heads on inside of case. I used small (12mm D) Neodymium magnets to hold the lower screws in place until I could mount a nut on the outside. To remove the magnet, hold a finger firmly on it and slide around the speaker frame until free.
- From the outside of the case, tighten 4 brass 4/40 acorn nuts to the screws
- Attach the LEFT angle USB Micro cable to the pi. No space to connect this power cable after the pi is installed
- Mount the pi to the piTFT. Strong light is helpful. Tilt the pi slightly away from the case wall, enough to see the alignment on pins. Make sure the pins are aligned properly and press down slowly.
- Mount the bonnet on the pi, same technique as the pi to the piTFT
- Screw in the speaker wires to the amp
- Insert the encoder wires to their pins and ground
Ready to Rock...
Operations- Play/pause: hold down tune knob for slow count of 1-2, but first move the needle away from a Favorite. Otherwise, auto-play will keep overriding pause
- Toggle screens: press tune knob down for slow count of 1-2-3-4-5. Will cycle from dial, to clock, to Now Playing and back to dial again
- Restart SqueezeLite: press tune knob down for over a count of 10. SqueezeLite produces distorted audio after 6-8 hours of play, reboots fairly quickly. I leave mine on all the time and fix the audio this way....
- Volume: Up/Clockwise; Down/Counter(Anti-) Clockwise
- Power: Volume button press > 3 secs triggers safe shutdown. When off, shorter (<3 secs) press turns pi on. When ON, < 3 secs press does a REBOOT
- Now Playing Art: Pandora supplies this automatically. For local music, copy an album cover image named folder.jpg or cover.jpg into the album directory, followed by a rescan (Settings/Basic Settings/Look for new and changed media files). If a local album is missing art, a default image will display.
- The screen, viewed straight on, is colorful and detailed enough. But the display doesn't have a wide viewing angle, so can look washed out from other angles
- Now Playing presents rectangular cover art in a round porthole. Square peg, meet round hole...
- Without the bezel, you can see the edges of the screen
- Shutting down the pi does not kill power to the display - the screen will be dark but you can see light bleed around the edges as seen from the back of the case
- The PWM pin (#18) for piTFT backlight control is used by the mono amp
UPDATE 2018/01/13:
Added piTFT to Things/Parts List. Thanks for the catch, ChromeBlue!
UPDATE 2018/07/28:
Recommended that you assign a static IP address instead of letting your router assign a DHCP address. The IP address is hard-coded in two scripts:
- miniz.py - executed by the service zdial
- SB_SERVER_IP in /usr/local/bin/squeezelite_settings.sh
It's possible that your router will assign a different DHCP address if the miniz is off for some time.
Debugging:
If you get a blank display:
- sudo systemctl stop zdial
- cd ~/miniz
Will take awhile to start up. Check for errors that may appear.
UPDATE 2018/07/29:
Fellow hackster Danny Martin sent pictures of his own miniz build. Looks great!
Thanks, Danny!
ALSO ADDED:
On github, a script named miniz_dial_positions.py
Degrees of a circle are used to play Favorites. There are already favorites mapped to frequencies in the "favs" dictionary in the miniz.py script., for dial frequencies 175, 200, 250, 300, 350 and 400.
Use this script to map additional frequencies to degrees of a circle.
Usage
Stop the zdial service. Run the program, tune to a desired radio frequency on the dial. The degrees of circle for that frequency appears below the center of the dial in white letters. Associate that degree with the favorite you wish to play at that frequency in the "favs:" dictionary.
Comments