if (Model.NotificationsEnabled) { }
Maker.io main logo

Raspberry Pi Retrofits Vintage Radio for Streaming

2025-03-14 | By Travis Foss

License: See Original Project Amplifiers Barrel Audio Connectors Raspberry Pi SBC

Last summer I purchased an antique radio from a local auction sale for only a few dollars. The ‎radio is a Stewart Warner Model 205CK that I believe was made around 1941. After bringing home ‎the radio and evaluating its restoration potential, I had an idea: what if I retrofit it with a Raspberry ‎Pi to turn it into an internet radio? I had a few different Raspberry Pis sitting around unused, so I ‎thought this might be an interesting project. ‎

antique_1

The first idea I had was to carefully remove the internal electronics from the original build and ‎then see about placing the new electronics into the case. Prior to doing this, however, I ‎remembered I had a small amplifier board, 1738-DFR0675-EN-ND, that I could pull from another ‎project to do some testing. The original speaker in the cabinet had an interesting set of ‎connections that I hadn’t seen before, I believe they are just referred to as spring clips.‎

clips_2

These made it easy to evaluate to see if a small amplifier like this would provide enough power for ‎the speaker. After plugging in the amplifier and powering it with a 12V battery, the sound was ‎pretty good, just not as loud as I thought it would be. To further investigate the project, I used my ‎multimeter to measure the speaker's impedance. I found that it was reading approximately 7 ‎ohms. While it may not be a perfect match for the amp, I believe it will likely work, as the amp has ‎specifications for both 4-ohm and 8-ohm speaker configurations. During the amplifier test, I ‎noticed how great the speaker sounded. The music, while not overly loud, filled the room with a ‎warm and pleasant tone that was enjoyable to listen to. I was truly impressed by this.‎

amplifier_3

Now that I had the initial testing out of the way, I decided the next step was to figure out which ‎Raspberry Pi I wanted to use. I first started to think about the Raspberry Pi Zero 2 W that I hadn’t ‎used in a project yet. I decided to create some test code to see if I could make it work.‎

While I’ve done some programming with a Raspberry Pi, I thought this project would be an ‎interesting test case to see what using ChatGPT and Claude could do to help me speed up my ‎coding time. I should state that I did use the free version of each of these LLM’s to create this ‎project. ‎

To start, I went to Claude’s website and posted the following Prompt.‎

You are an experienced Python programmer that rarely makes mistakes. I am working on creating an antique radio into an internet radio using a Raspberry Pi zero 2w, an ‎Pimoroni Audio DAC, and a Hi-Fi Bluetooth radio receiver from DFRobot. Can you help me with the ‎code to get this up and running? I would like for it to be an internet radio along with an Airplay ‎receiver as well.

In my time looking at various prompt engineering videos, I’ve heard from several people that if you ‎give a role to the LLM, it will provide a better, more accurate output.‎

For the initial test of the code, I decided to try to run the sound through my Bluetooth headphones ‎connected to the Pi instead of the speaker. I figured this would be an easy way to test the code ‎prior to setting up all the hardware. ‎

After connecting my headphones to the Pi with Bluetooth, I copied and pasted the first batch of ‎code that Claude sent over. ‎

Copy Code
import subprocess

import os

import signal

import time

from threading import Thread

import vlc

class VintageRadio:‎

‎ def init(self):‎

‎ # Initialize audio components‎

‎ self.current_source = None

‎ self.player = None

‎ self.airplay_process = None

‎ self.radio_stations = {‎

‎ '1': 'http://media-ice.musicradio.com/ClassicFMMP3',‎

‎ '2': 'http://icecast.vrtcdn.be/radio1-high.mp3',‎

‎ '3': 'http://stream.live.vc.bbcmedia.co.uk/bbc_radio_two'‎

‎ }‎

‎ ‎

‎ # Set up audio output to Pimoroni DAC

‎ os.environ['ALSA_CARD'] = 'sndrPihifiberry'‎

‎ ‎

‎ def start_airplay(self):‎

‎ """Start Shairport-sync for AirPlay receiving"""‎

‎ if self.airplay_process is None:‎

‎ try:‎

‎ self.stop_radio()‎

‎ self.airplay_process = subprocess.Popen(‎

‎ ['shairport-sync', '-o', 'alsa', '--name', 'Vintage Radio'],‎

‎ stdout=subprocess.PIPE,‎

‎ stderr=subprocess.PIPE

‎ )‎

‎ self.current_source = 'airplay'‎

‎ print("AirPlay receiver started")‎

‎ except Exception as e:‎

‎ print(f"Error starting AirPlay: {e}")‎

‎ ‎

‎ def stop_airplay(self):‎

‎ """Stop AirPlay receiver"""‎

‎ if self.airplay_process:‎

‎ self.airplay_process.terminate()‎

‎ self.airplay_process = None

‎ self.current_source = None

‎ ‎

‎ def play_radio(self, station_number):‎

‎ """Play internet radio station"""‎

‎ if station_number in self.radio_stations:‎

‎ try:‎

‎ self.stop_airplay()‎

‎ if self.player:‎

‎ self.player.stop()‎

‎ ‎

‎ # Create a new VLC instance‎

‎ instance = vlc.Instance('--aout=alsa')‎

‎ self.player = instance.media_player_new()‎

‎ media = instance.media_new(self.radio_stations[station_number])‎

‎ self.player.set_media(media)‎

‎ self.player.play()‎

‎ self.current_source = 'radio'‎

‎ print(f"Playing radio station {station_number}")‎

‎ except Exception as e:‎

‎ print(f"Error playing radio: {e}")‎

‎ ‎

‎ def stop_radio(self):‎

‎ """Stop radio playback"""‎

‎ if self.player:‎

‎ self.player.stop()‎

‎ self.player = None

‎ self.current_source = None

‎ ‎

‎ def setup_bluetooth(self):‎

‎ """Initialize Bluetooth receiver"""‎

‎ try:‎

‎ # Enable Bluetooth audio sink‎

‎ subprocess.run(['sudo', 'bluetoothctl', 'discoverable', 'on'])‎

‎ subprocess.run(['sudo', 'bluetoothctl', 'pairable', 'on'])‎

‎ subprocess.run(['sudo', 'bluetoothctl', 'agent', 'NoInputNoOutput'])‎

‎ print("Bluetooth receiver ready")‎

‎ except Exception as e:‎

‎ print(f"Error setting up Bluetooth: {e}")‎

‎ ‎

‎ def cleanup(self):‎

‎ """Clean up all audio processes"""‎

‎ self.stop_radio()‎

‎ self.stop_airplay()‎

‎ ‎

def main():‎

‎ radio = VintageRadio()‎

‎ radio.setup_bluetooth()‎

‎ ‎

‎ while True:‎

‎ print("\nVintage Radio Control")‎

‎ print("1. Play Radio Station 1 (Classic FM)")‎

‎ print("2. Play Radio Station 2 (Radio 1)")‎

‎ print("3. Play Radio Station 3 (BBC Radio 2)")‎

‎ print("4. Start AirPlay Receiver")‎

‎ print("5. Stop All")‎

‎ print("6. Exit")‎

‎ ‎

‎ choice = input("Select an option: ")‎

‎ ‎

‎ if choice in ['1', '2', '3']:‎

‎ radio.play_radio(choice)‎

‎ elif choice == '4':‎

‎ radio.start_airplay()‎

‎ elif choice == '5':‎

‎ radio.cleanup()‎

‎ elif choice == '6':‎

‎ radio.cleanup()‎

‎ break

‎ ‎

if name == "__main__":‎

‎ main()‎

Prior to running the code, Claude also mentioned that I needed to update the Pi as well as install ‎some other packages that weren’t included. ‎

These are the commands that it suggested

Copy Code
sudo apt-get update

sudo apt-get install python3-vlc shairport-sync bluetooth bluez-tools
Copy Code
‎# Add this to /boot/config.txt‎
dtoverlay=hifiberry-dac
Copy Code
# Edit /etc/bluetooth/main.conf‎# Add or modify:‎
Class = 0x200414‎
Enable = Source,Sink,Media,Socket
Copy Code
chmod +x radio_script.py

After implementing all these changes, I tried testing out the code by running the Python script. It ‎seemed like it was working correctly, however, I was unable to get any sound to play through my ‎headphones. ‎

The next prompt I sent to Claude was:‎

I haven’t integrated the DFRobot Bluetooth amp or the Pimoroni DAC, could you rewrite the code ‎so that I can test the radio over Bluetooth to some headphones.

After a few short moments, Claude gave me the next batch of code. I saved the new code and ‎then ran it again only to find out I was still having issues with the sound working. At that point, I ‎decided to do some testing on the Pi itself. I hooked up a screen and a keyboard and mouse to the ‎Pi, however at this point I’m not exactly sure what I did but the Pi would no longer power up. After ‎trying several things, I resorted to changing to a Pi 4B instead of the Zero 2 W. I figured this would ‎help in the long run as I would need fewer extra parts to get the radio up and running. The Pi 4B ‎had an Aux output on it, so I could directly connect between the Pi and the Bluetooth amp that I ‎was looking at using.‎

After setting up the new PI, I first tried connecting my headphones via Bluetooth and tried playing ‎some YouTube videos. The sound came through the headphones loud and clear. ‎

Being that had worked, I went back to Claude and entered the following prompt:‎

Can you remove all of the Bluetooth things from the code? In testing the Bluetooth portion of the Pi ‎is working correctly already without modification.

Also, can you change the radio station dictionary to this '1': {'name': 'Lofi 1', 'url': ‎‎'http://192.95.39.65:5607'}, '2': {'name': 'Lofi 2', 'url': 'https://cast.magicstreams.gr:9125'}, '3': ‎‎{'name': 'Lofi 3', 'url': 'http://5.39.82.157:8054'}‎

Claude gave me another rendition of the code.‎

This new code worked perfectly. I was able to switch between stations as well as stop and restart ‎the radio by entering the numbers for each option in the terminal. ‎

After getting this part of the code working, I attempted to get an airplay function set up as well. ‎Also, at this point, I had to switch from Claude to ChatGPT as I had hit my daily limit for requests. ‎I copied the code into ChatGPT and then asked if it could add the airplay receiver portion to the ‎code. After much frustration and effort in trying to get it to work, I decided to stop working on that ‎portion of the code and try to get some other ideas working.‎

The next idea I had for this build was to add a sound effect like an old-time radio tuning between ‎stations each time the station was changed. I asked ChatGPT if it was possible to add some sort ‎of sound effect between stations playing and it said that indeed it should be. It then instructed me ‎to search the web for a royalty-free sound effect of “radio tuning noise” or “AM radio static”. After ‎searching the web, I was able to come across an MP3 that sounded very close to what I originally ‎had in mind. ‎

The next step that was given was to install pygame on the Pi by running this command

Copy Code
Pip install pygame

After downloading the .mp3 file onto the Pi, I then asked how I could go about adding a random 5-‎second clip of the .mp3 after a station had been selected. It then updated the code for me, and I ‎saved it to the Pi. The first few renditions of the code were close to what I was expecting but not ‎quite right. The first kept playing the full one-minute plus .mp3 and the second rendition did play ‎for 5 seconds as I wanted, however, it didn’t fade in/out like I was hoping. I then asked if it would ‎be able to add a fade in/out sequence to the code. It added the correct fade out and in, but there ‎was a half-second dead spot between the two. I then asked if it was able to overlap the sound clip ‎and the radio station a little bit so that it was more of a smooth transition. Once this prompt was ‎sent, I received the code that would ultimately end up in the final build. It did everything I needed ‎it to and faded in and out exactly like I wanted. After getting the code, I updated and added some ‎new stations to the station dictionary. ‎

Copy Code
import pygame

import time

import random

import vlc

import subprocess

import logging

from threading import Thread

from tyPing import Optional, Dict

‎# Set up logging with more detailed format‎

logging.basicConfig(‎

‎ level=logging.DEBUG,‎

‎ format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'‎

‎)‎

logger = logging.getLogger(__name__)‎

class InternetRadio:‎

‎ def init(self):‎

‎ # Initialize pygame mixer with higher quality settings‎

‎ pygame.mixer.init(frequency=44100, size=-16, channels=2, buffer=4096)‎

‎ self.player: Optional[vlc.MediaPlayer] = Noneself.airplay_process: Optional[subprocess.Popen] = Noneself.current_source: Optional[str] = Noneself.current_station: Optional[str] = Noneself.vlc_volume = 0 # Track VLC player volume

‎ # Enhanced radio stations dictionary with metadata‎

‎ self.radio_stations: Dict[str, dict] = {‎

‎ '1': {‎

‎ 'name': 'Lofi 1',‎

‎ 'url': 'http://192.95.39.65:5607',‎'description': 'Relaxing lofi beats'‎

‎ },‎

‎ '2': {‎

‎ 'name': 'MPR News',‎

‎ 'url': 'https://nis.stream.publicradio.org/nis.mp3',‎'description': 'Minnesota Public Radio News'‎

‎ },‎

‎ '3': {‎

‎ 'name': 'Lofi 3',‎

‎ 'url': 'http://5.39.82.157:8054',‎'description': 'Study beats and ambient sounds'‎

‎ },‎

‎ '4': {‎

‎ 'name': 'Minnesota Jazz Tracks',‎

‎ 'url': 'http://kbem-live.streamguys1.com/jazztracks_mp3',‎'description': 'The Jazz of 10,000 Lakes'‎

‎ },‎

‎ '5': {‎

‎ 'name': 'Swing Street Radio',‎

‎ 'url': 'http://s6.voscast.com:11312',‎'description': 'Swing Music'‎

‎ },‎

‎ '6': {‎

‎ 'name': 'Swing City Radio',‎

‎ 'url': 'http://bluford.torontocast.com:8006/stream',‎'description': 'Catch your favorites of the 20s 30s and 40s'‎

‎ },‎

‎ '7': {‎

‎ 'name': 'Yesterday USA - Blue',‎

‎ 'url': 'https://media.classicairwaves.com:8018/stream',‎'description': 'Welcome to Yesterday USA, where Old Time Radio Programs rule the day. ‎For more than 37 years we have been playing classic old time radio shows hosted by volunteers ‎who are no>‎

‎ },‎

‎ }‎

‎ def list_stations(self) -> None:‎

‎ """Display all available radio stations with their descriptions"""‎

‎ print("\n=== Available Radio Stations ===")‎

‎ for number, station in self.radio_stations.items():‎

‎ print(f"{number}. {station['name']} - {station['description']}")‎

‎ print("=" * 30 + "\n")‎

‎ def play_radio(self, station_number: str) -> None:‎

‎ """‎

‎ Play internet radio station with smooth transition effects

‎ """‎

‎ if station_number not in self.radio_stations:‎

‎ logger.error(f"Invalid station number: {station_number}")‎

‎ print("Invalid station number. Please try again.")‎

‎ returntry:‎

‎ self.stop_airplay()‎

‎ self.current_station = station_number

‎ # Create new VLC instance with initial volume at 0‎

‎ instance = vlc.Instance('--verbose=2')‎

‎ if self.player:‎

‎ self.player.stop()‎

‎ self.player = instance.media_player_new()‎

‎ url = self.radio_stations[station_number]['url']‎

‎ media = instance.media_new(url)‎

‎ self.player.set_media(media)‎

‎ # Start radio playback at 0 volume‎

‎ self.player.audio_set_volume(0)‎

‎ self.player.play()‎

‎ # Start transition effect in a separate thread‎

‎ Thread(target=self._transition_audio).start()‎

‎ except Exception as e:‎

‎ logger.error(f"Error playing radio: {e}")‎

‎ print(f"Error playing radio station. Please try again.")‎

‎ def transitionaudio(self) -> None:‎

‎ """‎

‎ Handle the smooth transition between tuning noise and radio station

‎ """‎

‎ try:‎

‎ # Play tuning noise‎

‎ pygame.mixer.music.load('radio_tuning.mp3')‎

‎ pygame.mixer.music.play()‎

‎ pygame.mixer.music.set_volume(1.0)‎

‎ # Wait for a moment with full tuning noise‎

‎ time.sleep(1.5)‎

‎ # Crossfade between tuning noise and radio‎

‎ steps = 50 # More steps for smoother transition

‎ fade_duration = 3.0 # Longer fade for more vintage feel

‎ step_time = fade_duration / steps

‎ for i in range(steps + 1):‎

‎ # Calculate volumes using sine wave for smooth transition‎

‎ tuning_volume = cos_volume = (steps - i) / steps

‎ radio_volume = sin_volume = i / steps

‎ # Update volumes‎

‎ pygame.mixer.music.set_volume(tuning_volume)‎

‎ self.player.audio_set_volume(int(radio_volume * 100))‎

‎ time.sleep(step_time)‎

‎ # Ensure tuning noise is fully stopped‎

‎ pygame.mixer.music.stop()‎

‎ except Exception as e:‎

‎ logger.error(f"Error during audio transition: {e}")‎

‎ def start_airplay(self) -> None:‎

‎ """Start Shairport-sync for AirPlay receiving"""‎

‎ if self.airplay_process is None:‎

‎ try:‎

‎ self.stop_radio()‎

‎ self.airplay_process = subprocess.Popen(‎

‎ ['shairport-sync', '-o', 'alsa', '--name', 'Vintage Radio'],‎

‎ stdout=subprocess.PIPE,‎

‎ stderr=subprocess.PIPE,‎

‎ text=True

‎ )‎

‎ self.current_source = 'airplay'‎

‎ logger.info("AirPlay receiver started successfully")‎

‎ print("AirPlay receiver is now active")‎

‎ except Exception as e:‎

‎ logger.error(f"Error starting AirPlay: {e}")‎

‎ print("Failed to start AirPlay receiver. Please check if shairport-sync is installed.")‎

‎ def stop_airplay(self) -> None:‎

‎ """Stop AirPlay receiver"""‎

‎ if self.airplay_process:‎

‎ self.airplay_process.terminate()‎

‎ self.airplay_process = Noneself.current_source = None

‎ logger.info("AirPlay receiver stopped")‎

‎ print("AirPlay receiver stopped.")‎

‎ def stop_radio(self) -> None:‎

‎ """Stop radio playback with fade out effect"""‎

‎ if self.player:‎

‎ # Fade out radio‎

‎ current_volume = self.player.audio_get_volume()‎

‎ steps = 20‎

‎ for i in range(steps):‎

‎ volume = int(current_volume * (steps - i) / steps)‎

‎ self.player.audio_set_volume(volume)‎

‎ time.sleep(0.05)‎

‎ self.player.stop()‎

‎ self.player = Noneself.current_station = None

‎ logger.info("Radio playback stopped")‎

‎ print("Radio playback stopped.")‎

‎ def get_status(self) -> str:‎

‎ """Get detailed current status of the radio"""‎

‎ status = "\n=== Radio Status ===\n"‎

‎ if self.current_source == 'airplay':‎

‎ status += "Current mode: AirPlay\n"‎

‎ elif self.current_station:‎

‎ station = self.radio_stations[self.current_station]‎

‎ status += f"Current mode: Radio\n"‎

‎ status += f"Playing: {station['name']} - {station['description']}\n"‎

‎ else:‎

‎ status += "Current mode: Idle\n"‎

‎ return status + "=" * 20 + "\n"‎

def main():‎

‎ radio = InternetRadio()‎

‎ while True:‎

‎ print("\n=== Vintage Internet Radio Control ===")‎

‎ print("1. List Radio Stations")‎

‎ print("2. Play Radio Station")‎

‎ print("3. Start AirPlay Receiver")‎

‎ print("4. Stop Playback")‎

‎ print("5. Show Status")‎

‎ print("6. Exit")‎

‎ print("=" * 35)‎

‎ try:‎

‎ choice = input("\nSelect an option (1-6): ").strip()‎

‎ if choice == '1':‎

‎ radio.list_stations()‎

‎ elif choice == '2':‎

‎ radio.list_stations()‎

‎ station = input("Enter station number to play: ").strip()‎

‎ radio.play_radio(station)‎

‎ elif choice == '3':‎

‎ radio.start_airplay()‎

‎ elif choice == '4':‎

‎ radio.stop_radio()‎

‎ radio.stop_airplay()‎

‎ elif choice == '5':‎

‎ print(radio.get_status())‎

‎ elif choice == '6':‎

‎ print("\nStopPing all playback...")‎

‎ radio.stop_radio()‎

‎ radio.stop_airplay()‎

‎ print("Goodbye!")‎

‎ breakelse:‎

‎ print("Invalid option, please enter a number between 1 and 6.")‎

‎ except KeyboardInterrupt:‎

‎ print("\nShutting down gracefully...")‎

‎ radio.stop_radio()‎

‎ radio.stop_airplay()‎

‎ break

‎ except Exception as e:‎

‎ logger.error(f"Unexpected error: {e}")‎

‎ print("An error occurred. Please try again.")‎

if name == "__main__":‎

‎ main()‎

At this point, I had saved 8 different renditions of the code to the pi, so that I could revert to older ‎ones if I ran into issues. After getting the main controls working, the next task I asked ChatGPT ‎was if it could set up a local webpage that I would be able to control the Pi from. It then set off ‎creating a Flask page that would handle the controls. Prior to this build, I had never heard of Flask, ‎so I had to do a bit of research to learn more about it. Luckily, we already have a few projects on ‎Maker.io related to Flask. After a short time, ChatGPT gave me the following bit of code.‎

Copy Code
from flask import Flask, render_template, request, jsonify

import threading

from radio8_setup import InternetRadio # Ensure your existing script is named properly

app = Flask(__name__)‎

radio = InternetRadio()‎

@app.route('/')‎

def index():‎

‎ return render_template('index.html', stations=radio.radio_stations)‎

@app.route('/play/<station_number>', methods=['POST'])‎

def play_station(station_number):‎

‎ threading.Thread(target=radio.play_radio, args=(station_number,)).start()‎

‎ return jsonify({"status": "playing", "station": station_number})‎

@app.route('/stop', methods=['POST'])‎

def stop_radio():‎

‎ radio.stop_radio()‎

‎ return jsonify({"status": "stopped"})‎

@app.route('/volume', methods=['POST'])‎

def set_volume():‎

‎ volume = int(request.form['volume'])‎

‎ if radio.player:‎

‎ radio.player.audio_set_volume(volume)‎

‎ return jsonify({"status": "volume_set", "volume": volume})‎

if name == '__main__':‎

‎ app.run(host='0.0.0.0', port=5000, debug=True)

‎For the Flask program to work, I also needed to have an index.html file put together. After ‎prompting ChatGPT, here is the code that it gave me. I updated the background image to one I ‎found online.‎

Copy Code
<!DOCTYPE html>‎

‎<html lang="en">‎

‎<head>‎

‎ <meta charset="UTF-8">‎

‎ <meta name="viewport" content="width=device-width, initial-scale=1.0">‎

‎ <title>Antique Radio Controller</title>‎

‎ <style>‎

‎ body {‎

‎ background-image: url('https://wallpapercave.com/wp/wp8461192.jpg');‎

‎ background-size: cover;‎

‎ text-align: center;‎

‎ font-family: Arial, sans-serif;‎

‎ color: white;‎

‎ }‎

‎ .button {‎

‎ display: block;‎

‎ width: 200px;‎

‎ margin: 10px auto;‎

‎ padding: 10px;‎

‎ background-color: brown;‎

‎ color: white;‎

‎ border: none;‎

‎ cursor: pointer;‎

‎ }‎

‎ .slider {‎

‎ width: 50%;‎

‎ margin: 20px auto;‎

‎ }‎

‎ </style>‎

‎</head>‎

‎<body>‎

‎ <h1>Antique Radio Controller</h1>‎

‎ {% for key, station in stations.items() %}‎

‎ <button class="button" onclick="playStation('{{ key }}')">{{ station.name }}</button>‎

‎ {% endfor %}‎

‎ <br>‎

‎ <input type="range" min="0" max="100" class="slider" oninput="setVolume(this.value)">‎

‎ <br>‎

‎ <button class="button" onclick="stopRadio()">Stop</button>‎

‎ <script>‎

‎ function playStation(station) {‎

‎ fetch(`/play/${station}`, { method: 'POST' });‎

‎ }‎

‎ function stopRadio() {‎

‎ fetch('/stop', { method: 'POST' });‎

‎ }‎

‎ function setVolume(volume) {‎

‎ fetch('/volume', {‎

‎ method: 'POST',‎

‎ headers: {'Content-Type': 'application/x-www-form-urlencoded'},‎

‎ body: volume=${volume}‎

‎ });‎

‎ }‎

‎ </script>‎

‎</body>‎

‎</html>

‎Now that the Flask page was set up and the Python script was completed, the last task I had was ‎to find out which parts I wanted to use in the final build. I started looking at the DigiKey website for ‎another audio amp that would be rather low-cost and possibly have a couple of different options ‎for how the media is delivered. I discovered a HiFi Bluetooth amplifier from DFRobot, part 1738-‎DFR0803-ND, which had everything I was hoping to find. It had options for both Bluetooth and ‎auxiliary inputs. This gave me the ability to connect to the radio over Bluetooth instead of Airplay ‎or via the internet radio that I was building via the aux input. This was the perfect choice for this ‎build. ‎

After selecting the amplifier, I wanted to use, I looked for a short audio plug-to-plug (aux cable) to ‎connect the Raspberry Pi to the amplifier. I found part number TL1621-ND, which is 1 foot long.‎

After getting these parts, I then dove into the build itself. My original thought was to take out the ‎original internals to the radio, but after seeing what I would need to get this to work, I decided that ‎I would keep the radio as original as possible with the internals intact. I figured that way if ‎someone later wanted to restore the radio, everything was still in its original place.‎

To start the hardware installation, I first looked for a Raspberry Pi 4 case suitable for a VESA mount ‎on Printables and began 3D printing it. Next, I found a case for the amplifier, which was listed as ‎the Wuzhi ZK-502C case, also on Printables. I then took that file and added a few mounting tabs in ‎the slicer software I was using. My plan was to mount the case to the bottom of the shelf below ‎the Raspberry Pi, as I thought this would be the simplest solution. After getting both pieces ‎printed, I dove into the assembly. There was already a passthrough hole drilled into the wooden ‎shelf at the back of the radio, so I decided to screw the Raspberry Pi case into the shelf next to ‎this hole. Directly beneath it, I mounted the Hi-Fi amplifier close enough for the short aux cable I ‎found to reach. From there I ran the speaker wire from the amp down to the speaker and ‎connected both positive and negative wires to their respective terminals. Lastly, I ran the power ‎supplies for both the amp and the Pi down to the bottom of the cabinet. From there I attached ‎both power supplies to a dual connection extension cord so that I would only have to plug the one ‎cord into the wall to power both devices. ‎

At this stage, the complete build was assembled and sounded fantastic. However, I felt that ‎something was still missing from the front. While the project looked impressive overall, the ‎display seemed to lack adequate backlighting. Initially, I considered using an LED strip for the ‎backlighting, but after assessing the limited space available, I decided to explore other options. I ‎remembered that Adafruit had flexible LED filaments that they refer to NOODS. I found part 1528-‎‎5504-ND which I thought would look pretty good. I connected the setup to my benchtop power ‎supply to determine the appropriate resistor size for achieving the desired level of backlighting. ‎After conducting a series of tests, including positioning the filament within the radio below the ‎display, I discovered that a 4.5-ohm resistor provided the perfect color I was aiming for at 3.3V. ‎The reason I wanted to adjust it for that voltage is so I could directly connect it to the 3.3V pin on ‎the Raspberry Pi for power. After getting the LED filament wired and put into place, I realized I ‎needed something to hold it there. Instead of using glue to adhere it, I resorted to 3D printing a ‎long rectangular piece that would just wedge it in place. That way it could be easily removed if ‎needed.‎

radio_4

I should mention that I downloaded an app called Wuzhi Audio on my phone. This app allows me ‎to easily switch between Bluetooth and Aux input for the amplifier. This feature makes it even ‎easier than I imagined to play songs from my phone on the radio.‎

Here is the reveal of the final product and how it turned out.‎

final_5

interface_6

This is how the web control interface looks:‎

controller_7

And here is a short video of it in action:‎

 

Overall, this build was a lot of fun, and I was able to test the viability of using LLM’s to help with ‎my coding. I would say that looking back on this project, LLM’s are great at getting the groundwork ‎of a project. It helped get the project 80% of the way completed and it needed guidance along the ‎way to get it there, but it for sure helped speed up my coding.

制造商零件编号 DFR0675-EN
STEREOBLUETOOTHAMPLIFIERBOARD
DFRobot
制造商零件编号 DFR0803
HIFI DIGITAL BLUETOOTH AMPLIFIER
DFRobot
制造商零件编号 P312-001
ADAPT 3.5MM PLUG TO 3.5MM PLUG
Eaton Tripp Lite
制造商零件编号 5504
LED MOD WARM WHT LINEAR STRIP
Adafruit Industries LLC
制造商零件编号 SC1176
SBC 1.0GHZ 4 CORE 512MB RAM
Raspberry Pi
制造商零件编号 SC0194(9)
RASPBERRY PI 4 B 4GB
Raspberry Pi
Add all DigiKey Parts to Cart
Have questions or comments? Continue the conversation on TechForum, DigiKey's online community and technical resource.