

Ziel des Projekts

Ein ESP32 soll zusammen mit einem mp3-Decoder als Internetradio funktionieren. Mit Tastern oder mit einer Fernbedienung kann der Sender gewechselt und der Ton leiser oder lauter eingestellt werden.
Die Taster haben jeweils mehrere Funktionen:
- Taster für die Senderwahl (gelb)
ein Klick: nächster Sender
Doppelklick: vorheriger Sender
langer Druck: erster Sender der Liste starten - Taster für die Lautstärkeregelung (rot)
ein Klick: Lautstärke +5
Doppelklick: Lautstärke -5
langer Druck: Ton ausschalten
erneuter langer Druck: Ton einschalten
Die Tasten der Fernbedienung:
- Pfeil nach rechts: nächster Sender
- Pfeil nach links: vorheriger Sender
- Pfeil nach unten: leiser
- Pfeil nach oben: lauter
- #: Ton aus, erneute Betätigung: Ton an
Auf dem LCD wird der Sender, die Lautstärke und ein Teil der vom Sender übermittelten Informationen dargestellt.
Benötigte Bauteile
- mp3-Decoder VS1053
- ⇒LCD
- Leitungsdrähte
- zwei (verschiedenfarbige) Taster
- oder ⇒Keyes Fernbedienung
Der Schaltplan
Mit zwei Tastern

Mit Fernbedienung

Konfiguration des Mikrocontrollers
Das Programm
Benötigte Bibliotheken
Bibliothek ESP_VS1053_Library
Bibliothek ESP32_VS1053_Stream
Beide Bibliotheken müssen als zip-Datei herunter geladen und mit
Sketch -> zip-Bibliothek hinzufügen
installiert werden.


Für die Taster

Für die Fernbedienung

Der Programmcode
Wenn du die Senderliste erweitern willst, musst du die Stream-Adresse des neuen Senders an beliebiger Position im Array Sender hinzufügen. Die Liste mit den Beschreibungen musst du mit dem Namen des neuen Senders erweitern.
Mit zwei Tastern
#include "Arduino.h"
#include "WiFi.h"
#include "VS1053.h"
#include "ESP32_VS1053_Stream.h"
#include "LCDIC2.h"
// 4-zeiliges LCD
LCDIC2 lcd(0x27, 20, 4);
#include "OneButton.h"
// Pins des VS1053
#define VS1053_CS 5
#define VS1053_DCS 16
#define VS1053_DREQ 4
// Pins Taster
int TasterLautstaerke = 12;
int TasterSender = 14;
// Taster der Bibliothek OneButton zuordnen
OneButton SenderWahl(TasterSender, true);
OneButton LautstaerkeEinstellen(TasterLautstaerke, true);
// Variablen Sender
int SenderIndex = 0;
int AnzahlSender = 0;
int Lautstaerke = 80;
int GesicherteLautstaerke = Lautstaerke;
ESP32_VS1053_Stream stream;
// WiFi-Daten
char Router[] = "Router_SSID";
char Passwort[] = "xxxxxxxx";
// Streamadressen der Sender als Array
const char* Sender[] =
{
"http://wdr-1live-live.icecast.wdr.de/wdr/1live/live/mp3/128/stream.mp3", // 1Live
"http://wdr-wdr2-bergischesland.icecast.wdr.de/wdr/wdr2/bergischesland/mp3/128/stream.mp3", // WDR2
"http://wdr-wdr4-live.icecast.wdr.de/wdr/wdr4/live/mp3/128/stream.mp3", // WDR4
"http://liveradio.swr.de/sw282p3/swr3/play.mp3", // SWR3
"http://dispatcher.rndfnk.com/swr/swr4/ko/mp3/128/stream.mp3", // SWR4
"http://avw.mdr.de/streams/284321-1_mp3_high.m3u", // MDR JUMP Rock channel
"http://dispatcher.rndfnk.com/hr/hr1/rheinmain/high", // HR1
"http://www.ndr.de/resources/metadaten/audio/m3u/ndr2_hh.m3u", // NDR Hamburg
"http://dispatcher.rndfnk.com/rbb/rbb888/live/mp3/mid", // RBB 88,8
"http://liveradio.sr.de/sr/sr3/mp3/128/stream.mp3", // SR 3
"http://icecast.ndr.de/ndr/njoy/live/mp3/128/stream.mp3", // N-Joy
"http://st01.sslstream.dlf.de/dlf/01/128/mp3/stream.mp3?aggregator=web", // Deutschlandfunk
"http://stream.lokalradio.nrw/444z6rq", // Radio Berg
"http://orf-live.ors-shoutcast.at/oe3-q2a", // Ö3
"http://antennebrandenburg.de/livemp3", // Antenne Brandenburg
"http://stream.antenne.de/antenne/stream/mp3", // Antenne Bayern live
"http://stream.antenne.de/antenne-bayern-70er-rock/stream/mp3", // Antenne Bayern 70er Rock
"http://stream.antenne.de/classic-rock-live/stream/mp3", // Antenne Bayern Classic Rock
"http://stream.antenne.de/antenne-bayern-80er-rock/stream/mp3", // Antenne Bayern 80er Rock
"http://classicrock.radioarabella.de/arabella-classicrock.mp3", // Radio Arabella
"http://www.charivari.de/webradio/r8082.m3u", // Radio Charivari München
};
const char *Beschreibung[]
{
"1Live", "WDR 2", "WDR 4", "SWR 3", "SWR 4", "MDR JUMP", "HR 1", "NDR 2", "RBB 88,8",
"SR 3", "N-Joy", "Deutschlandfunk","Radio Berg", "\xEF 3", "Antenne Brandenburg", "Antenne Bayern live",
"Antenme Bayern 70er", "Antenne Bayern Rock", "Antenne Bayern 80er",
"Radio Arabella", "Radio Charivari"
};
void setup()
{
Serial.begin(9600);
// LCD starten
lcd.begin();
// Cursor "verstecken"
lcd.setCursor(false);
/*
Aktionen dem Modus der Tasters zuordnen
setPressTicks(500);
setClickTicks(200);
setDebounceTicks(50);
*/
SenderWahl.attachClick(SenderVor);
SenderWahl.attachDoubleClick(SenderZurueck);
SenderWahl.attachLongPressStop(ErsterSender);
LautstaerkeEinstellen.attachClick(Leiser);
LautstaerkeEinstellen.attachDoubleClick(Lauter);
LautstaerkeEinstellen.attachLongPressStop(TonAus);
// pinModes definieren
pinMode(TasterSender, INPUT_PULLUP);
pinMode(TasterLautstaerke, INPUT_PULLUP);
// auf Seriellen Monitor warten
while (!Serial)
{
delay(10);
}
// WiFi starten
WiFi.mode(WIFI_STA);
WiFi.begin(Router, Passwort);
Serial.println("------------------------");
while (WiFi.status() != WL_CONNECTED)
{
delay(200);
Serial.print(".");
}
Serial.println();
Serial.print("Verbunden mit ");
Serial.println(WiFi.SSID());
Serial.print("IP über DHCP: ");
Serial.println(WiFi.localIP());
// Start SPI bus
SPI.setHwCs(true);
SPI.begin();
// Decoder starten
if (!stream.startDecoder(VS1053_CS, VS1053_DCS, VS1053_DREQ) || !stream.isChipConnected())
{
Serial.println("Decoder konnte nicht gestartet werden ..");
Serial.println("Programm angehalten!");
while (1);
}
Serial.println("MP3-Decoder gestartet ...");
// Sender verbinden
stream.connecttohost(Sender[SenderIndex]);
// wenn der Stream nicht mehr läuft ...
if (!stream.isRunning())
{
Serial.println("Radio wird neu gestartet ...");
stream.stopSong();
stream.connecttohost(Sender[SenderIndex]);
}
Serial.print("Codec: ");
Serial.println(stream.currentCodec());
Serial.print("Bitrate: ");
Serial.print(stream.bitrate());
Serial.println(" kbps");
stream.setVolume(Lautstaerke);
// Anzahl der Sender im Array feststellen
AnzahlSender = sizeof(Sender) / sizeof(Sender[0]);
Serial.println("Anzahl der Sender:" + String(AnzahlSender));
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(Beschreibung[SenderIndex]);
lcd.setCursor(0, 1);
lcd.print("Lautst\xe1rke: " + String(Lautstaerke) + " ");
}
void loop()
{
SenderWahl.tick();
delay(10);
LautstaerkeEinstellen.tick();
delay(10);
// wenn Stream gestoppt -> neu verbinden
if (!stream.isRunning())
{
// stream.stopSong();
stream.connecttohost(Sender[SenderIndex]);
}
// Stream abspielen
stream.loop();
delay(5);
}
// Sender im Seriellen Monitor anzeigen
void audio_showstation(const char* info)
{
Serial.printf("Station: %s\n", info);
}
// Titel anzeigen
void audio_showstreamtitle(const char* info)
{
String Titel = String(info);
Titel.replace(" - ", " ");
Titel.replace(" / ", " ");
Titel.replace(" von ", " ");
if (Titel.length() > 20) Titel = Titel.substring(0, 20);
lcd.setCursor(0,2);
lcd.print(Titel);
Serial.printf("Titel: %s\n", info);
}
void audio_eof_stream(const char* info)
{
Serial.printf("Ende: %s\n", info);
}
void SenderVor()
{
// wenn der letzte Sender -> zurück auf 0
if (SenderIndex >= AnzahlSender - 1) SenderIndex = 0;
else SenderIndex++;
Serial.println(SenderIndex);
stream.stopSong();
stream.connecttohost(Sender[SenderIndex]);
// Sender/Lautstärke auf dem LCD anzeigen
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(Beschreibung[SenderIndex]);
lcd.setCursor(0, 1);
lcd.print("Lautst\xe1rke: " + String(Lautstaerke) + " ");
}
void SenderZurueck()
{
// wenn der letzte Sender -> zurück auf 0
if (SenderIndex == 0) SenderIndex = AnzahlSender - 1;
else SenderIndex--;
Serial.println(SenderIndex);
stream.stopSong();
stream.connecttohost(Sender[SenderIndex]);
// Sender/Lautstärke auf dem LCD anzeigen
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(Beschreibung[SenderIndex]);
lcd.setCursor(0, 1);
lcd.print("Lautst\xe1rke: " + String(Lautstaerke) + " ");
}
void Leiser()
{
if (Lautstaerke > 5) Lautstaerke -= 5;
// if (Lautstaerke == 0) Lautstaerke += 5;
GesicherteLautstaerke = Lautstaerke;
stream.setVolume(Lautstaerke);
Serial.println("Lautstärke: " + String(Lautstaerke));
lcd.setCursor(0, 1);
lcd.print("Lautst\xe1rke: " + String(Lautstaerke) + " ");
}
void Lauter()
{
if (Lautstaerke < 95) Lautstaerke += 5;
GesicherteLautstaerke = Lautstaerke;
stream.setVolume(Lautstaerke);
Serial.println("Lautstärke: " + String(Lautstaerke));
lcd.setCursor(0, 1);
lcd.print("Lautst\xe1rke: " + String(Lautstaerke) + " ");
}
void TonAus()
{
if (Lautstaerke == 0)
{
stream.setVolume(GesicherteLautstaerke);
lcd.setCursor(0, 1);
lcd.print("Ton ein ");
Lautstaerke = GesicherteLautstaerke;
}
else
{
Lautstaerke = 0;
stream.setVolume(Lautstaerke);
Serial.println("Lautstärke: " + String(Lautstaerke));
lcd.setCursor(0, 1);
lcd.print("Ton aus ");
}
}
void ErsterSender()
{
SenderIndex = 0;
Serial.println(SenderIndex);
stream.stopSong();
stream.connecttohost(Sender[SenderIndex]);
// Sender/Lautstärke auf dem LCD anzeigen
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(Beschreibung[SenderIndex]);
lcd.setCursor(0, 1);
lcd.print("Lautst\xe1rke: " + String(Lautstaerke) + " ");
}Mit Fernbedienung
Beim Kompilieren kommt es zu zwei Warnmeldungen für die Plattform ESP32, das Programm kann aber ohne Probleme hochgeladen werden.
Wenn du diese Meldungen vermeiden willst, musst du in der Datei /Arduino/libraries/IRremote/src/IRremote.hpp in den Zeilen 152 und 245 ein // vor die Zeile setzen. So sehen die Zeilen nach der Änderung aus:
152: // #warning INFO: For ESP32, RP2040, mbed and particle boards SEND_PWM_BY_TIMER is enabled by default, since we have the resources
245: // #warning INFO: No definition for LED_BUILTIN found -> default LED feedback is disabled.#include "Arduino.h"
#include "WiFi.h"
#include "VS1053.h"
#include "ESP32_VS1053_Stream.h"
#include "LCDIC2.h"
#include "IRremote.hpp"
int EmpfaengerPin = 13;
// 4-zeiliges LCD
LCDIC2 lcd(0x27, 20, 4);
// Pins des VS1053
#define VS1053_CS 5
#define VS1053_DCS 16
#define VS1053_DREQ 4
// Variablen Sender
int SenderIndex = 0;
int AnzahlSender = 0;
int Lautstaerke = 80;
int GesicherteLautstaerke = Lautstaerke;
ESP32_VS1053_Stream stream;
// WiFi-Daten
char Router[] = "Router_SSID";
char Passwort[] = "xxxxxxxx";
const char* Sender[] =
{
"http://wdr-1live-live.icecast.wdr.de/wdr/1live/live/mp3/128/stream.mp3", // 1Live
"http://wdr-wdr2-bergischesland.icecast.wdr.de/wdr/wdr2/bergischesland/mp3/128/stream.mp3", // WDR2
"http://wdr-wdr4-live.icecast.wdr.de/wdr/wdr4/live/mp3/128/stream.mp3", // WDR4
"http://liveradio.swr.de/sw282p3/swr3/play.mp3", // SWR3
"http://dispatcher.rndfnk.com/swr/swr4/ko/mp3/128/stream.mp3", // SWR4
"http://avw.mdr.de/streams/284321-1_mp3_high.m3u", // MDR JUMP Rock channel
"http://dispatcher.rndfnk.com/hr/hr1/rheinmain/high", // HR1
"http://www.ndr.de/resources/metadaten/audio/m3u/ndr2_hh.m3u", // NDR Hamburg
"http://dispatcher.rndfnk.com/rbb/rbb888/live/mp3/mid", // RBB 88,8
"http://liveradio.sr.de/sr/sr3/mp3/128/stream.mp3", // SR 3
"http://icecast.ndr.de/ndr/njoy/live/mp3/128/stream.mp3", // N-Joy
"http://st01.sslstream.dlf.de/dlf/01/128/mp3/stream.mp3?aggregator=web", // Deutschlandfunk
"http://stream.lokalradio.nrw/444z6rq", // Radio Berg
"http://orf-live.ors-shoutcast.at/oe3-q2a", // Ö3
"http://antennebrandenburg.de/livemp3", // Antenne Brandenburg
"http://stream.antenne.de/antenne/stream/mp3", // Antenne Bayern live
"http://stream.antenne.de/antenne-bayern-70er-rock/stream/mp3", // Antenne Bayern 70er Rock
"http://stream.antenne.de/classic-rock-live/stream/mp3", // Antenne Bayern Classic Rock
"http://stream.antenne.de/antenne-bayern-80er-rock/stream/mp3", // Antenne Bayern 80er Rock
"http://classicrock.radioarabella.de/arabella-classicrock.mp3", // Radio Arabella
"http://www.charivari.de/webradio/r8082.m3u", // Radio Charivari München
};
const char *Beschreibung[]
{
"1Live", "WDR 2", "WDR 4", "SWR 3", "SWR 4", "MDR JUMP", "HR 1", "NDR 2", "RBB 88,8",
"SR 3", "N-Joy", "Deutschlandfunk","Radio Berg", "\xEF 3", "Antenne Brandenburg", "Antenne Bayern live",
"Antenme Bayern 70er", "Antenne Bayern Rock", "Antenne Bayern 80er",
"Radio Arabella", "Radio Charivari"
};
void setup()
{
Serial.begin(9600);
// LCD starten
lcd.begin();
// Cursor "verstecken"
lcd.setCursor(false);
// Infrarot-Empfänger starten
IrReceiver.begin(EmpfaengerPin);
// auf Seriellen Monitor warten
while (!Serial)
{
delay(10);
}
// WiFi starten
WiFi.mode(WIFI_STA);
WiFi.begin(Router, Passwort);
Serial.println("------------------------");
while (WiFi.status() != WL_CONNECTED)
{
delay(200);
Serial.print(".");
}
Serial.println();
Serial.print("Verbunden mit ");
Serial.println(WiFi.SSID());
Serial.print("IP über DHCP: ");
Serial.println(WiFi.localIP());
// Start SPI bus
SPI.setHwCs(true);
SPI.begin();
// Decoder starten
if (!stream.startDecoder(VS1053_CS, VS1053_DCS, VS1053_DREQ) || !stream.isChipConnected())
{
Serial.println("Decoder konnte nicht gestartet werden ..");
Serial.println("Programm angehalten!");
while (1);
}
Serial.println("MP3-Decoder gestartet ...");
// Sender verbinden
stream.connecttohost(Sender[SenderIndex]);
// wenn der Stream nicht mehr läuft ...
if (!stream.isRunning())
{
Serial.println("Radio wird neu gestartet ...");
stream.stopSong();
stream.connecttohost(Sender[SenderIndex]);
}
Serial.print("Codec: ");
Serial.println(stream.currentCodec());
Serial.print("Bitrate: ");
Serial.print(stream.bitrate());
Serial.println(" kbps");
stream.setVolume(Lautstaerke);
// Anzahl der Sender im Array feststellen
AnzahlSender = sizeof(Sender) / sizeof(Sender[0]);
Serial.println("Anzahl der Sender:" + String(AnzahlSender));
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(Beschreibung[SenderIndex]);
lcd.setCursor(0, 1);
lcd.print("Lautst\xe1rke: " + String(Lautstaerke) + " ");
}
void loop()
{
// decode() -> Daten lesen
if (IrReceiver.decode())
{
// kurzes delay, damit nur ein Tastendruck gelesen wird
delay(200);
// resume -> nächsten Wert lesen
IrReceiver.resume();
if (IrReceiver.decodedIRData.command > 0 && IrReceiver.decodedIRData.command < 95)
{
// Werte abfragen
if (IrReceiver.decodedIRData.command == 22) ErsterSender();
if (IrReceiver.decodedIRData.command == 74) TonAus();
if (IrReceiver.decodedIRData.command == 68) SenderZurueck();
if (IrReceiver.decodedIRData.command == 67) SenderVor();
if (IrReceiver.decodedIRData.command == 70) Lauter();
if (IrReceiver.decodedIRData.command == 21) Leiser();
if (IrReceiver.decodedIRData.command == 64) Serial.println("OK");
}
}
// wenn Stream gestoppt -> neu verbinden
if (!stream.isRunning())
{
// stream.stopSong();
stream.connecttohost(Sender[SenderIndex]);
}
// Stream abspielen
stream.loop();
delay(5);
}
// Sender im Seriellen Monitor anzeigen
void audio_showstation(const char* info)
{
Serial.printf("Station: %s\n", info);
}
// Titel anzeigen
void audio_showstreamtitle(const char* info)
{
String Titel = String(info);
Titel.replace(" - ", " ");
Titel.replace(" / ", " ");
Titel.replace(" von ", " ");
if (Titel.length() > 20) Titel = Titel.substring(0, 20);
lcd.setCursor(0,2);
lcd.print(Titel);
Serial.printf("Titel: %s\n", info);
}
void audio_eof_stream(const char* info)
{
Serial.printf("Ende: %s\n", info);
}
void SenderVor()
{
// wenn der letzte Sender -> zurück auf 0
if (SenderIndex >= AnzahlSender - 1) SenderIndex = 0;
else SenderIndex++;
Serial.println(SenderIndex);
stream.stopSong();
stream.connecttohost(Sender[SenderIndex]);
// Sender/Lautstärke auf dem LCD anzeigen
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(Beschreibung[SenderIndex]);
lcd.setCursor(0, 1);
lcd.print("Lautst\xe1rke: " + String(Lautstaerke) + " ");
}
void SenderZurueck()
{
// wenn der letzte Sender -> zurück auf 0
if (SenderIndex == 0) SenderIndex = AnzahlSender - 1;
else SenderIndex--;
Serial.println(SenderIndex);
stream.stopSong();
stream.connecttohost(Sender[SenderIndex]);
// Sender/Lautstärke auf dem LCD anzeigen
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(Beschreibung[SenderIndex]);
lcd.setCursor(0, 1);
lcd.print("Lautst\xe1rke: " + String(Lautstaerke) + " ");
}
void Leiser()
{
if (Lautstaerke > 5) Lautstaerke -= 5;
// if (Lautstaerke == 0) Lautstaerke += 5;
GesicherteLautstaerke = Lautstaerke;
stream.setVolume(Lautstaerke);
Serial.println("Lautstärke: " + String(Lautstaerke));
lcd.setCursor(0, 1);
lcd.print("Lautst\xe1rke: " + String(Lautstaerke) + " ");
}
void Lauter()
{
if (Lautstaerke < 95) Lautstaerke += 5;
GesicherteLautstaerke = Lautstaerke;
stream.setVolume(Lautstaerke);
Serial.println("Lautstärke: " + String(Lautstaerke));
lcd.setCursor(0, 1);
lcd.print("Lautst\xe1rke: " + String(Lautstaerke) + " ");
}
void TonAus()
{
if (Lautstaerke == 0)
{
stream.setVolume(GesicherteLautstaerke);
lcd.setCursor(0, 1);
lcd.print("Ton ein ");
Lautstaerke = GesicherteLautstaerke;
}
else
{
Lautstaerke = 0;
stream.setVolume(Lautstaerke);
Serial.println("Lautstärke: " + String(Lautstaerke));
lcd.setCursor(0, 1);
lcd.print("Ton aus ");
}
}
void ErsterSender()
{
SenderIndex = 0;
Serial.println(SenderIndex);
stream.stopSong();
stream.connecttohost(Sender[SenderIndex]);
// Sender/Lautstärke auf dem LCD anzeigen
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(Beschreibung[SenderIndex]);
lcd.setCursor(0, 1);
lcd.print("Lautst\xe1rke: " + String(Lautstaerke) + " ");
}Erfahrungen im Betrieb
- je nach Auslastung der Server kann es zu seltenen kurzzeitigen Unterbrechungen des Streams kommen, zumeist stabilisiert sich das Signal im Laufe der Zeit
- Alle Sender bieten ihre Streams auch in einer SSL-Variante an. Im Programm verwende ich die Version ohne SSL.
Du kannst beide Varianten testen, grundsätzlich würde ich die SSL-Variante bevorzugen, die aber leider nicht immer störungsfrei läuft. - in seltenen Fällen kommt es auch zum Abbruch des Streams, der Stream wird aber sofort neu gestartet
- beim Start kann möglicherweise der Codec des Streams nicht ermittelt werden (Codec STOPPED)
das Programm muss neu gestartet werden
Sender in der SSL-Variante
"https://wdr-1live-live.icecastssl.wdr.de/wdr/1live/live/mp3/128/stream.mp3", // 1Live mit SSL
"https://wdr-wdr2-bergischesland.icecastssl.wdr.de/wdr/wdr2/bergischesland/mp3/128/stream.mp3", // WDR2
"https://wdr-wdr4-live.icecastssl.wdr.de/wdr/wdr4/live/mp3/128/stream.mp3", // WDR4
"https://liveradio.swr.de/sw282p3/swr3/play.mp3", // SWR3
"https://dispatcher.rndfnk.com/swr/swr4/ko/mp3/128/stream.mp3", // SWR4
"https://avw.mdr.de/streams/284321-1_mp3_high.m3u", // MDR JUMP Rock channel
"https://dispatcher.rndfnk.com/hr/hr1/rheinmain/high", // HR1
"https://www.ndr.de/resources/metadaten/audio/m3u/ndr2_hh.m3u", // NDR Hamburg
"https://dispatcher.rndfnk.com/rbb/rbb888/live/mp3/mid", // RBB 88,8
"https://liveradio.sr.de/sr/sr3/mp3/128/stream.mp3", // SR 3
"https://st01.sslstream.dlf.de/dlf/01/128/mp3/stream.mp3?aggregator=web", // Deutschlandfunk
"https://stream.lokalradio.nrw/444z6rq", // Radio Berg
"https://antennebrandenburg.de/livemp3", // Antenne Brandenburg
"https://stream.antenne.de/antenne/stream/mp3", // Antenne Bayern live
"https://stream.antenne.de/antenne-bayern-70er-rock/stream/mp3", // Antenne Bayern 70er Rock
"https://stream.antenne.de/classic-rock-live/stream/mp3", // Antenne Bayern Classic Rock
"https://stream.antenne.de/antenne-bayern-80er-rock/stream/mp3", // Antenne Bayern 80er Rock
"https://classicrock.radioarabella.de/arabella-classicrock.mp3", // Radio Arabella
"https://www.charivari.de/webradio/r8082.m3u", // Radio Charivari MünchenQuellen
- Radiostreams suchen
- Bibliothek ESP_VS1053_Library
- Bibliothek ESP32_VS1053_Stream
- ESP32-WiFi API
Verwandte Anleitung
Letzte Aktualisierung: