Devices & Components
40 colored male-female jumper wires
Prototype PCB, 6cm x 8cm
TP4056 Micro USB 5V 1A Li - Ion Battery Charger Module (AZDelivery)
0.91" I2C OLED 128x32
PLA Filament
Push Button
Heat Shrink Tubing, Assorted Sizes
3.7V 1100mAh Lithium Rechargable Battery
plywood sheet
ESP32
Fader Potentiometer knob
micro switch
PAM8403 + Volume Control
3.5 Audio Jack
VS1053 DSP
Hardware & Tools
Crimp Tool (generic)
Soldering Station
Solder wire
Tinkerine Ditto Pro 3D Printer
Trotec Speedy 100 Laser and Engraver
Hot glue gun (generic)
Software & Tools
Autodesk Inventor
AutoCAD
Tinkerine Suite 3 (No longer supported; Use TInkerine Cloud)
Arduino IDE
Project description
Code
Esp32_Internet_Radio
cpp
Inspired by the code from educ8s.tv
1#include <WiFi.h> // Include WiFi library for ESP32's WiFi functionality 2#include <VS1053.h> // Include library to control the VS1053 MP3 decoder 3#include <U8g2lib.h> // Include library for controlling the OLED display 4 5// Define the VS1053 MP3 decoder pins 6#define VS1053_CS 32 // Chip Select for VS1053 7#define VS1053_DCS 33 // Data Command Select for VS1053 8#define VS1053_DREQ 35 // Data Request pin for VS1053 9 10// Button pins to switch between radio stations 11#define BUTTON_NEXT 13 // Pin for the 'next station' button 12#define BUTTON_PREV 12 // Pin for the 'previous station' button 13 14// OLED Display setup with I2C communication 15U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE); // Create OLED display object 16 17// WiFi settings: replace with your own network credentials 18const char *ssid = "Your SSID"; // Your WiFi network name 19const char *password = "Your Wifi Password"; // Your WiFi network password 20 21// Radio station details 22const char* stationNames[] = {"ERT Kosmos", "FFH Lounge", "FFH Summer"}; // Array of station names 23const char* stationHosts[] = {"radiostreaming.ert.gr", "mp3.ffh.de", "mp3.ffh.de"}; // Host URLs for the stations 24const char* stationPaths[] = {"/ert-kosmos", "/ffhchannels/hqlounge.mp3", "/ffhchannels/hqsummerfeeling.mp3"}; // Paths to the radio streams 25int currentStation = 0; // Index of the currently playing station 26const int totalStations = sizeof(stationNames) / sizeof(stationNames[0]); // Calculate the number of available stations 27 28// VS1053 MP3 player object 29VS1053 player(VS1053_CS, VS1053_DCS, VS1053_DREQ); // Create VS1053 object to control MP3 playback 30WiFiClient client; // WiFi client object to connect to the radio stream 31 32// Variables for scrolling text on the OLED display 33int textPosition = 128; // Initial text position for scrolling 34unsigned long previousMillis = 0; // Store the last time the display was updated 35const long interval = 50; // Time interval for updating the display (50 ms) 36 37void setup() { 38 Serial.begin(115200); // Start the serial monitor for debugging 39 40 // Wait for VS1053 and PAM8403 amplifier to power up 41 delay(3000); 42 43 u8g2.begin(); // Initialize the OLED display 44 u8g2.setFlipMode(1); // Flip the display 180 degrees 45 u8g2.setFont(u8g2_font_ncenB08_tr); // Set font for OLED display 46 47 // Display startup messages on OLED 48 u8g2.clearBuffer(); 49 u8g2.drawStr(0, 16, "Starting Radio..."); // Initial message 50 u8g2.sendBuffer(); 51 delay(2000); 52 53 u8g2.clearBuffer(); 54 u8g2.drawStr(0, 16, "Starting Engine..."); // Second message 55 u8g2.sendBuffer(); 56 delay(2000); 57 58 u8g2.clearBuffer(); 59 u8g2.drawStr(0, 16, "Connecting to WiFi..."); // WiFi connection message 60 u8g2.sendBuffer(); 61 62 Serial.println("\n\nSimple Radio Node WiFi Radio"); // Debug message in the serial monitor 63 64 SPI.begin(); // Initialize SPI communication for VS1053 65 66 player.begin(); // Start the VS1053 decoder 67 if (player.getChipVersion() == 4) { // Check for correct version of VS1053 68 player.loadDefaultVs1053Patches(); // Load patches for MP3 decoding if needed 69 } 70 player.switchToMp3Mode(); // Switch VS1053 to MP3 decoding mode 71 player.setVolume(100); // Set the volume (range: 0-100) 72 73 Serial.print("Connecting to SSID "); 74 Serial.println(ssid); // Debug message: attempting WiFi connection 75 WiFi.begin(ssid, password); // Start WiFi connection 76 77 // Disable WiFi power saving mode for a more stable connection 78 WiFi.setSleep(false); 79 80 // Attempt to connect to WiFi with retries 81 int attempts = 0; 82 while (WiFi.status() != WL_CONNECTED && attempts < 20) { 83 delay(500); 84 Serial.print("."); // Print dots to indicate connection progress 85 attempts++; 86 } 87 88 // Check if WiFi connection is successful 89 if (WiFi.status() == WL_CONNECTED) { 90 Serial.println("WiFi connected"); 91 Serial.println("IP address: "); 92 Serial.println(WiFi.localIP()); // Print the assigned IP address 93 94 // Display success message on OLED 95 u8g2.clearBuffer(); 96 u8g2.drawStr(0, 16, "Connected Yay!"); 97 u8g2.sendBuffer(); 98 delay(2000); 99 } else { 100 // Display failure message on OLED if WiFi connection fails 101 Serial.println("WiFi not connected"); 102 u8g2.clearBuffer(); 103 u8g2.drawStr(0, 16, "Not Connected"); 104 u8g2.sendBuffer(); 105 delay(2000); 106 } 107 108 // Initialize button pins with pull-up resistors 109 pinMode(BUTTON_NEXT, INPUT_PULLUP); 110 pinMode(BUTTON_PREV, INPUT_PULLUP); 111 112 // Set font for displaying station names 113 u8g2.setFont(u8g2_font_profont17_mr); 114 115 displayStation(); // Display the initial station name on the OLED 116 connectToHost(); // Connect to the radio station stream 117} 118 119void loop() { 120 // Reconnect if the WiFi client is disconnected 121 if (!client.connected()) { 122 Serial.println("Reconnecting..."); 123 connectToHost(); // Attempt to reconnect to the stream 124 } 125 126 // Read data from the radio stream and send it to the VS1053 decoder for playback 127 if (client.available() > 0) { 128 uint8_t buffer[32]; 129 size_t bytesRead = client.readBytes(buffer, sizeof(buffer)); // Read data from stream 130 player.playChunk(buffer, bytesRead); // Play the received audio data 131 } 132 133 handleButtons(); // Check if buttons are pressed and switch stations accordingly 134 scrollText(); // Scroll the station name on the OLED display 135} 136 137void connectToHost() { 138 // Connect to the current radio station's server 139 Serial.print("Connecting to "); 140 Serial.println(stationHosts[currentStation]); 141 142 if (!client.connect(stationHosts[currentStation], 80)) { 143 Serial.println("Connection failed"); // Display error if connection fails 144 return; 145 } 146 147 // Send HTTP request to the server to get the radio stream 148 Serial.print("Requesting stream: "); 149 Serial.println(stationPaths[currentStation]); 150 151 client.print(String("GET ") + stationPaths[currentStation] + " HTTP/1.1\r\n" + 152 "Host: " + stationHosts[currentStation] + "\r\n" + 153 "Connection: close\r\n\r\n"); 154 155 // Skip the HTTP headers in the response 156 while (client.connected()) { 157 String line = client.readStringUntil('\n'); 158 if (line == "\r") { 159 break; // End of headers 160 } 161 } 162 163 Serial.println("Headers received"); // Debug message: headers successfully received 164} 165 166void handleButtons() { 167 static bool lastButtonNextState = HIGH; // Track the previous state of the 'next' button 168 static bool lastButtonPrevState = HIGH; // Track the previous state of the 'previous' button 169 170 bool currentButtonNextState = digitalRead(BUTTON_NEXT); // Read current state of 'next' button 171 bool currentButtonPrevState = digitalRead(BUTTON_PREV); // Read current state of 'previous' button 172 173 // If 'next' button is pressed (LOW), switch to the next station 174 if (lastButtonNextState == HIGH && currentButtonNextState == LOW) { 175 nextStation(); 176 } 177 // If 'previous' button is pressed (LOW), switch to the previous station 178 if (lastButtonPrevState == HIGH && currentButtonPrevState == LOW) { 179 previousStation(); 180 } 181 182 lastButtonNextState = currentButtonNextState; // Update the last state for the 'next' button 183 lastButtonPrevState = currentButtonPrevState; // Update the last state for the 'previous' button 184} 185 186void nextStation() { 187 currentStation = (currentStation + 1) % totalStations; // Move to the next station (wrap around) 188 displayStation(); // Update the OLED display with the new station name 189 connectToHost(); // Connect to the new station 190} 191 192 193void nextStation() { 194 currentStation = (currentStation + 1) % totalStations; 195 displayStation(); 196 connectToHost(); 197} 198 199void previousStation() { 200 currentStation = (currentStation - 1 + totalStations) % totalStations; 201 displayStation(); 202 connectToHost(); 203} 204 205void displayStation() { 206 textPosition = 128; // Reset text position to start from the right 207 u8g2.clearBuffer(); 208 u8g2.drawLine(0, 0, 127, 0); 209 u8g2.drawLine(0, 31, 127, 31); 210 u8g2.setCursor(textPosition, 22); 211 u8g2.print(stationNames[currentStation]); 212 u8g2.sendBuffer(); 213} 214 215void scrollText() { 216 unsigned long currentMillis = millis(); 217 218 if (currentMillis - previousMillis >= interval) { 219 previousMillis = currentMillis; 220 textPosition--; // Move text to the left 221 if (textPosition < -u8g2.getUTF8Width(stationNames[currentStation])) { 222 textPosition = 128; // Reset position to start from the right again 223 } 224 225 u8g2.clearBuffer(); 226 u8g2.drawLine(0, 0, 127, 0); 227 u8g2.drawLine(0, 31, 127, 31); 228 u8g2.setCursor(textPosition, 22); 229 u8g2.print(stationNames[currentStation]); 230 u8g2.sendBuffer(); 231 } 232}
Downloadable files
KeyCap_for_Button
feel free to create a better one.
ButtonKeyCap.stl
Navigate to the dwg file for the wooden enclosure.
can't upload the enclosure here, here's my GitHub
https://github.com/ZETRO2/Esp32-Internet-Radio
Documentation
Schematic
.
Esp32 internet Radio schematic.png

Button_Enclosure
Picture of how to install button enclosure
Button_Inclosure_back.png

Button_Enclosure_Front
Another picture of how to install button enclosure
Button_Inclosure_front.png

soldering Esp32 to decoder
How to solder the Esp32 to the MP3 decoder
Esp32_soldered_with_Decoder.png

Breadboard stage
remember to test everything on a breadboard first
BreadBoard_Stage.png

Pins on the Decoder
how to solder the pins on the Mp3 Decoder
How_to_solder_Decoder_2.png

Solder Decoder
how to solder the pins on the Mp3 Decoder
How_to_solder_Decoder.png

Project Structure
How the project works (from educ8s.tv)
Project_Structure.png

RadioBack
Back view of Radio
RadioBack.png

Radio Front
Front view of Radio
RadioFrontSide.png

Inside Radio
Inside View of Radio
RadioInside.png

Radio Left
Left side view of Radio
RadioLeft.png

Right Radio
Right side view of Radio
RadioRight.png

Radio Opened
left and Right side view of Radio when opened
RadioOpened.png

Stripped Audio Jack
I needed to strip an audio jack for it to fit
Stripped_AudioJack.png

Comments
Only logged in users can leave comments