ESP32-S3 Internet Radio: Circuit, Code, and Web Interface
ESP32-S3 N16R8 with UDA1334 DAC lets you build a minimal internet radio in an evening. The project uses I2S for audio output, SSD1306 OLED display for status, and a web interface for station management. It supports switching preset streams and entering custom URLs.
Components and Wiring
Required components:
- ESP32-S3 N16R8
- UDA1334 DAC for MP3 decoding
- Amplifier with speakers (soundbar)
- Dupont wires
Optional: 0.96" I2C SSD1306 OLED.
Wiring UDA1334 to ESP32-S3:
| ESP32-S3 | UDA1334 |
|----------|---------|
| GPIO41 | BCLK |
| GPIO42 | WSEL |
| GPIO45 | DIN |
| GND | GND |
| 3V3 | 3V3 |
Wiring OLED SSD1306:
| ESP32-S3 | SSD1306 |
|----------|---------|
| GPIO21 | SDA |
| GPIO20 | SCL |
| GND | GND |
| 3V3 | 3V3 |
Power: USB splitter from a 100W power supply. ESP32 and amplifier are powered in parallel.
Main Project Code
Full code in a single .ino file. Libraries: WiFi, HTTPClient, Audio, Adafruit_GFX, Adafruit_SSD1306.
#include <WiFi.h>
#include <HTTPClient.h>
#include <WebServer.h>
#include "driver/i2s.h"
#include "Audio.h"
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
// WiFi settings
const char* ssid = "ssid";
const char* password = "password";
// I2S pins
#define I2S_BCLK 41
#define I2S_LRC 42
#define I2S_DOUT 45
// I2C for OLED
#define I2C_SDA 21
#define I2C_SCL 20
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
#define SCREEN_ADDRESS 0x3C
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
struct RadioStation {
const char* name;
const char* url;
};
const RadioStation radioStations[] = {
{"RSJ", "http://stream.srg-ssr.ch/m/rsj/mp3_128"},
{"Revma", "https://stream.revma.ihrhls.com/zc238"},
{"Jazz Stream", "http://jazz.streamr.ru/jazz-128.mp3"},
{"Paris Jazz", "http://parisjazz.ice.infomaniak.ch/parisjazz-high.mp3"},
{"Smooth Jazz", "http://smoothjazz.cdnstream1.com/2619_128.mp3"},
{"Jazz WR06", "http://jazz-wr06.ice.infomaniak.ch/jazz-wr06-128.mp3"},
{"Jazz WR07", "http://jazz-wr07.ice.infomaniak.ch/jazz-wr07-128.mp3"},
{"Jazz WR10", "http://jazz-wr10.ice.infomaniak.ch/jazz-wr10-128.mp3"}
};
const int radioStationsCount = sizeof(radioStations) / sizeof(RadioStation);
int currentStationIndex = 0;
Audio audio;
int currentVolume = 18;
I2S is initialized for UDA1334. The display shows WiFi status, station name with scrolling text, and a volume indicator.
Web Management Interface
Server on port 80 serves an HTML page with:
- List of preset stations (click to switch)
- Volume slider (0-21)
- Fields for custom station (name + URL)
- Status of current station and IP address
Key endpoints:
/change?station=N— switch station/volume?value=N— set volume/custom?name=NAME&url=URL— custom station
HTML is generated dynamically with CSS styles and JavaScript for AJAX requests.
OLED Display Output
Display updates every 100ms:
- Top line: ONLINE/OFFLINE
- Scrolling station name (scrolls if overflow)
- Volume as number and bar
void updateDisplay() {
display.clearDisplay();
// WiFi status
bool wifiConnected = (WiFi.status() == WL_CONNECTED);
display.setTextSize(1);
display.setCursor(0, 0);
display.println(wifiConnected ? "ONLINE" : "OFFLINE");
// ... remaining logic
display.display();
}
Key Points
- Minimalism: One .ino file, ready-to-use Audio and Adafruit libraries
- I2S + UDA1334: Full MP3 decoder without overhead
- Web Control: Management without extra hardware, IP displayed on screen
- Custom Streams: Arbitrary URLs via form
- Stability: Runs on 100W USB power without resets
Enhancement Recommendations
- Optimize power: separate regulators for ESP32 (3.3V/1A) and amplifier
- Add GPIO buttons for local control
- Implement state saving in NVS (last station, volume)
- Support FLAC/OPUS via Audio library update
- Enclosure with soundbar mounting
Project is suitable for prototyping. Scaling requires code refactoring and PCB design.
— Editorial Team
No comments yet.