Zusammenfassung
Radioempfang über Frequenzmodulation hat seine Tücken. Nicht immer lassen sich alle Sender der Wahl empfangen, die zudem auch lokal begrent sind. Rauschfreiheit ist im Analogempfang ebenso nicht immer gewährleistet und schränkt die Wiedergabequalität teils deutlich ein. Mittles eines ESP32 Mikrokontrollers,eines 128×64 OLED-displays und einem Encoder wurde ein simples Webradio gebaut, das kabellos programmiert werden kann und zum Anschluss an einen Audioverstärker geeignet ist.
Einleitung
Zum linearen Radioempfang gibt es heutzutage – ergänzend zur klassischen Frequenzmodulation – einige Möglichkeiten. Neben der aktuellsten Erfindung der Digitalradios, die eine perfekte Audiowiedergabe ohne störendes Rauschen und lokale Senderbegrenzungen versprechen, existieren von den meisten Radiostationen Webstreams, die bei vorhandener Internetverbindung auf einer Vielzahl von Endgeräten abgespielt werden können. Denn auch bei Digitalradios kann es, ähnlich wie beim analogen Audioempfang, zum auftreten von Funklöchern kommen, sodass auch mit modernster Technik kein Hörgenuss entstehen kann.
Das Webradio eigenet sich in diesem Fall als verlässliche Rückfallebene. Der Stream wird aufgrund Zwischenspeicherung (Buffering) i.d.R. nicht in Echtzeit wiedergegeben, sondern kann einige Sekunden bis Minuten hinterherhängen. Für wen dies kein Problem darstellt eigenet sich die Wiedergabe von Audio-Streams als ideale Alternative, falls sowohl Analog-, als auch Digitalradio versagen.
In diesem Beitrag wurde auf Basis eines ESP32-Mikrocontrollers ein Internetradio entworfen und mittels 3D gedrucktem Gehäuse gebaut. Es lassen sich beliebige Online-Streams von Radiosendern einbinden. Die Programmierung erfolgt unkompliziert über ein Webinterface und W-LAN-Verbindung zum Modul.
Materialien & Methoden
Alle Gehäuseteile wurden mit PLA-Filament auf einem 3D-Drucker gedruckt, andere Materialien sind auch möglich. Als Steckverbindungen wurden gecrimpte Dupont-Stecker mit 2,64 mm Durchmesser (auch als “Arduino-Kabel” bekannt) verwendet. Der Quellcode wurde initial über die Micro-USB-Schnittstelle auf den Mikroprozessor geflasht. Inspiriert wurde das Projekt vom Blogeintrag auf AZ-Delivery.
Komponenten
- ESP32 Entwicklerboard (nicht gelötet!)
- Encoder KY-040
- Hohlstecker-Buchse 5.5×2.1
- OLED-Display 128×64 (SSD_1306)
- Klinkenbuchsen PJ320A
- Schalter KCD11
- Netzteil 5 VDC 2000 mAh
- M3 Muttern (3 Stück)
- M3x8 Senkkopfschrauben (3 Stück)
- Widerstand 10 kOhm (1 Stück)
- Kondensator
Schaltplan

Software
- Autodesk Inventor Professional 2023 (Build: 158, Release: 2023 (03/07/2022))
- Fritzing beta (Ver. 0.9.4 )
- Arduino IDE 1.8.13 (Board: ESP32 Dev Module, Upload Speed: 115200, CPU Frequency: 240 Mhz, Flash Frequency: 80 Mhz, Flash Mode: QIO, Flash Size: 4 MB (32 Mb), Partition Scheme: Default 4 MB with spiffs, Core Debug Level: None, PSRAM: Disabled)
Boardverwaltung
Esp32 von Espressif Systems – Version 2.0.9
https://github.com/iotechbugs/esp32-arduino/blob/master/docs/arduino-ide/boards_manager.md
Bibliothekenverwaltung
Es ist absolut notwendig, die hier angegeben Versionen der Bibliotheken zu verwenden.
- ESP8266audio – Version 1.9.7
- LiquidCrystal_I2C.h – Version 1.1.2
- AiEsp32RotaryEncoder.h – Version 1.4.0
- AsyncTCP – Version 1.1.1
- Adafruit SSD1306 – Version 2.5.7
- Adafruit GFX Library – Version 1.11.5
- Adafruit BusIo – Version 1.14.1
Sketche
- audio.ino – streaming and decoding audio data
- lcdisplay.ino – show station data an LCD
- rotary.ino – initialize and handle choosing senders
- senderlist.ino – senderlist by flash-values – or, if not present, by defaults
- senderconfig.ino – asynchronus webinterface to store sendernames und -urls
- senderconf.h – html-template for above
- wlanconfig.ino – seperate program to get WLAN-config per webinterface
- wlanconf.h – html-template for above
Code
#include <Preferences.h>
//structure for stationlist
typedef struct {
char url[100]; //stream url
char name[100]; //stations name
} Station;
#define STATIONS 13 //number of available stations
//station list (stations can now be modified by webinterface)
Station stationlist[STATIONS];
//instances of prefernces
Preferences pref;
Preferences sender;
//global variables
uint8_t curStation = 0; //index for current selected station in stationlist
uint8_t actStation = 0; //index for current station in station list used for streaming
uint32_t lastchange = 0; //time of last selection change
char title[64];
bool newTitle = false;
//setup
void setup()
{
Serial.begin(115200);
delay(1000);
// -------------------
setup_senderList();
setup_audio();
setup_rotary();
setup_lcdisplay();
//init WiFi
Serial.println("Connecting to WiFi");
while (!makeWLAN())
{
Serial.println("Cannot connect :(");
delay(1000);
}
Serial.println("Connected");
setup_senderConfig();
// -------------------
//set current station to 0
curStation = 0;
//start preferences instance
pref.begin("radio", false);
//set current station to saved value if available
if (pref.isKey("station")) curStation = pref.getUShort("station");
//set active station to current station
actStation = curStation;
//show on display and start streaming
showStation();
startUrl();
}
// main loop
void loop() {
if (newTitle==true)
{
stopscrolling();
displayTitle();
newTitle = false;
}
//check if stream has ended normally not on ICY streams
if (!loop_audio())
{
Serial.printf("MP3 done\n");
// Restart ESP when streaming is done or errored
delay(10000);
ESP.restart();
}
//read events from rotary encoder
rotary_loop();
}
Ergebnisse
Hardware
Das mittels CAD entworfene Konzept wurde 3d-gedruckt und entsprechend des Schaltplans verkabelt. Zur Befestigung des flachen Dreh-Drückrades musste der Schaft des Encoders gekürzt werden. Mit der Verwendung eines Standardknopfs oder eines tieferen Bedienelements entfällt dieser Schritt. Das Display und die 3,5 mm Klinkebuchse wurden mit Heißkleber befestigt. Der Deckel wurde mit M3 Senkkopf-Schrauben befestigt.











Die Zusammenlegung von Klinkenbuchse und Hohlstecker für die Stromversorgung auf der Geräterückseite zeigt sich als optimale Lösung. Der zugängliche USB-Port zum ESP32-Modul erlaubt Codeanpassungen ohne das Modul öffnen zu müssen. Das Dreh-Drückrad des Encoders erlaubt eine benutzerfreundliche Bediunung des Moduls. Das 128×64 OLED-Display integriert sich passend ins Konzept und funktioniert ohne Probleme. Das Webradio eignet sich optimal, um es direkt an einen Verstärker anzuschließen. Es ist kein Audio-Verstärker verbaut.
Software
Bei erstmaligem Anschalten gibt das Display die Anweisung, sich per Wifi mit dem Radio zu verbinden und die WLAN-Einstellungen einzugeben. Danach ist das Radio mit dem Netzwerk verbunden.
Wird der Encoder vom Benutzer gedreht, wechselt die Anzeige der Kopfzeile im OLED-Display von “Es läuft:” zu “Senderwechsel”. In der Displaymitte wird die Bezeichnung des nächsten Senders eingeblendet und kann mit einem Druck auf den Encoder übernommen werden. Erfolgt im Modus des Senderwechsels 5 Sekunden keine Benutzereingabe wird dieser abgebrochen und der Inhalt der Kopfzeile wechselt zurück zu “Es läuft:”.
Aktuell wird nicht der Titel des aktuellen Songs im Display angezeigt. Das Problem ist hierbei, dass es zu einem hörbaren Knacken kommt, sobald sich der Text aktualisiert. Eine Deaktivierung der Funktion des Textwechsels empfiehlt sich. Stattdessen wird die aktuelle IP-Adresse des Radios im Netzwerk angezeigt. Über die Eingabe dieser Adresse im Browser lassen sich Sender hinzufügen und entfernen. Es sind aktuell 13 Senderplätze verfügbar (die Anzahl lässt sich im Sketch beliebig anpassen). Diese können über die Weboberfläche überschrieben werden.



Ausblick
Die verzögerte Einschaltzeit wird sich aufgrund technischer Gegebenheiten nicht signifikant reduzieren lassen. Eine Lösung zur Unterdrückung des als störend empfundenen Knackens bei Textwechsel ließ sich nur durch die Deaktivierung der Funktion erreichen. Es ließen sich alle gewünschten Streams rauschfrei wiedergeben, das Ändern des Radiospeichers über das Webinterface funktioniert reibungslos. Die Wifi-Verbindung ist konstant.
Die Stromversorgung läuft über den USB-Anschluss deutlich zuverlässiger, als über das Netzteil. Daher wird empfohlen noch einen Kondensator vor den ESP zu bauen, falls der Betrieb mit Schalter und Hohlstecker erfolgen soll.
Interesant
Leider funktioniert der Software Download nicht.
Es wird die gepackte Datei im Brauser angezeigt.
Gruß Alois
Hi Alois,
danke für das Feedback. Mit Mozilla kann ich das Verhalten leider nicht reproduzieren – hier funktioniert alles, wie es soll. Was du aber machen kannst, falls der Fehler weiterhin bei dir auftaucht: Rechtsklick auf den Downloadlink –> “Ziel speichern unter”. Ich hoffe, es funktioniert nun. Liebe Grüße!
Ich bekomme diese Fehlermeldung nachdem die WiFi- Verbindung steht und der Loop mit dem ersten Sender losgeht. Ich komme einfach nicht weiter
Guru Meditation Error: Core 1 panic’ed (LoadProhibited). Exception was unhandled.
17:19:54.550 ->
17:19:54.550 -> Core 1 register dump:
17:19:54.550 -> PC : 0x4008b3ad PS : 0x00060930 A0 : 0x801587a4 A1 : 0x3ffb1b60
17:19:54.550 -> A2 : 0x00000000 A3 : 0xfffffffc A4 : 0x000000ff A5 : 0x0000ff00
17:19:54.583 -> A6 : 0x00ff0000 A7 : 0xff000000 A8 : 0x00000000 A9 : 0x3ffb1f60
17:19:54.583 -> A10 : 0x3ffc5644 A11 : 0x0000059c A12 : 0x0000001c A13 : 0x00000002
17:19:54.583 -> A14 : 0x00000000 A15 : 0x00000000 SAR : 0x00000018 EXCCAUSE: 0x0000001c
17:19:54.583 -> EXCVADDR: 0x00000000 LBEG : 0x4008b3ad LEND : 0x4008b3bd LCOUNT : 0xffffffff
Hi Peter S.,
ich versuche die Software zu verwenden, aber die Arduino IDE (1.8.57.0) kann die Datei
#include
nicht finden. Wie kann ich das beheben?
Danke. Viele Grüße
Hi,
ich meinte die Datei: Preferences.h
Viele Grüße
Hi Jens, du kannst versuchen die entsprechende Library manuell einzubinden:
https://github.com/espressif/arduino-esp32/blob/master/libraries/Preferences/src/Preferences.h
Hallo, hab’s fast auf Anhieb zum Laufen bekommen. Danke!
Allerdings ist mir nicht klar, wie über das Web-Interface neue Sender hinzugefügt werden können. Geht das überhaupt?
Danke und viele Grüße
A.
Hi Andreas, ja das geht. Aktuell bietet das Interface 13 Speicherplätze. Der Sender kann entsprechend ausgetauscht werden und ist nach einem Klick auf Speichern im Radio verfügbar.
Grüße
Peter
Das Editieren der Senderliste funktioniert bei mir leider nicht wie gewünscht. Ein Mal hat es geklappt. Ansonsten wird als Folge der Eingabe eines neuen Senders die bestehende Liste durcheinander gebracht. Vorhandene Sender erscheinen doppelt und dreifach, nur der neue Eintrag erscheint nicht.
Eine sehr schön gemachte Publikation, vielen Dank, genau das was ich gesucht habe nachdem ich mit der Adafruit Publikation nicht klar gekommen bin. Die hat zu unerklärlichen Abstürzen des ESP32 gefüht, vielleicht der Effekt des zu neuen BSP für den ESP32 der das irgendwo erwähnt wird. Ich hoffe mal es funktioniert jetzt mit Deinen Sketches. Ein Tipp, ich glaube Du hast bei den Libraries die ESP Async WebServer vergessen. Ohne diese bricht der Compile gleich ab. Ich habe jetzt die Version 3.6.0 installiert, das scheint das Problem zu lösen.
Hallo Herbert,
Die ESPAsyncWebServer.h ist erforderlich. In diesem Beitrag sind nur die Libraries gelistet, bei denen man die ganz bestimmten Versionen benötigt, insgesamt sind noch weitere Libraries eingebunden. Das geht dann aus den Sketches hervor und der Compiler meldet sich im Normalfall, wenn man noch etwas einbinden muss. Weiterhin viel Spaß mit dem Projekt.
Grüße
Peter
Hallo Peter,
tolles Projekt, vielen Dank für die Veröffentlichung !!
Bitte die ESPAsyncWebServer mit der Version 2.10.8 verwenden !!
Alle Versionen mit 3.X.X brimgen beim kompilieren einen Fehler:
exit status 1
call of overloaded ‘getParam(int)’ is ambiguous
Grüße aus Portugal
Rainer
Servus Peter,
hab schon manche Sketches auf Arduino und ESP32 gelasht, aber Dein Projekt übersteigt mein NOOB-Wissen.
Schade hätte mir gefallen.
WARNUNG: Bibliothek LiquidCrystal I2C behauptet auf avr Architektur(en) ausgeführt werden zu können und ist möglicherweise inkompatibel mit Ihrer derzeitigen Platine, welche auf esp32 Architektur(en) ausgeführt wird.
In file included from C:\Users\WAGNER Rudolf\Documents\Arduino\ESPwebRadio\ESPwebRadio.ino:23:
c:\Users\WAGNER Rudolf\Documents\Arduino\libraries\ESP_Async_WebServer\src/ESPAsyncWebServer.h: In member function ‘tcp_state AsyncWebServer::state() const’:
c:\Users\WAGNER Rudolf\Documents\Arduino\libraries\ESP_Async_WebServer\src/ESPAsyncWebServer.h:1124:50: error: passing ‘const AsyncServer’ as ‘this’ argument discards qualifiers [-fpermissive]
return static_cast(_server.status());
^
In file included from c:\Users\WAGNER Rudolf\Documents\Arduino\libraries\ESP_Async_WebServer\src/ESPAsyncWebServer.h:19,
from C:\Users\WAGNER Rudolf\Documents\Arduino\ESPwebRadio\ESPwebRadio.ino:23:
c:\Users\WAGNER Rudolf\Documents\Arduino\libraries\AsyncTCP\src/AsyncTCP.h:198:13: note: in call to ‘uint8_t AsyncServer::status()’
uint8_t status();
^~~~~~
C:\Users\WAGNER Rudolf\Documents\Arduino\ESPwebRadio\senderconfig.ino: In lambda function:
C:\Users\WAGNER Rudolf\Documents\Arduino\ESPwebRadio\senderconfig.ino:29:48: error: invalid conversion from ‘const AsyncWebParameter*’ to ‘AsyncWebParameter*’ [-fpermissive]
AsyncWebParameter* p2 = request->getParam(0);
~~~~~~~~~~~~~~~~~^~~
C:\Users\WAGNER Rudolf\Documents\Arduino\ESPwebRadio\senderconfig.ino:53:47: error: invalid conversion from ‘const AsyncWebParameter*’ to ‘AsyncWebParameter*’ [-fpermissive]
AsyncWebParameter* p = request->getParam(i); // read parameter
~~~~~~~~~~~~~~~~~^~~
C:\Users\WAGNER Rudolf\Documents\Arduino\ESPwebRadio\wlanconfig.ino: In lambda function:
C:\Users\WAGNER Rudolf\Documents\Arduino\ESPwebRadio\wlanconfig.ino:135:47: error: invalid conversion from ‘const AsyncWebParameter*’ to ‘AsyncWebParameter*’ [-fpermissive]
AsyncWebParameter* p = request->getParam(i);
~~~~~~~~~~~~~~~~~^~~
Mehrere Bibliotheken wurden für “SD.h” gefunden
Benutzt: C:\Users\WAGNER Rudolf\AppData\Local\Arduino15\packages\esp32\hardware\esp32\2.0.9\libraries\SD
Nicht benutzt: C:\Users\WAGNER Rudolf\AppData\Local\Arduino15\libraries\SD
exit status 1
Compilation error: invalid conversion from ‘const AsyncWebParameter*’ to ‘AsyncWebParameter*’ [-fpermissive]
Habe “alles” in den Vesionen von Deiner Anleitung installiert.
Gruß Rudi
Hallo
habe das problem das bei mir das Display dunkel bleibt, habe das Display mit anderen Sketch getestet und es geht, hat jemand eine idee ?
alles ander klappt bei mir.