Published on August 11, 2023 by

Webradio mit ESP32, OLED-Display und wireless update (OTA)

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

Schaltplan

Schaltpläne des Webradios mit 5-12 VDC Input. Rot: 5 V, Orange: 3,3 V, Schwarz: Masse.

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

Download STL

Download Sketches

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.

10 Kommentare

    1. 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!

  1. 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

  2. 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

    1. Hi Jens, du kannst versuchen die entsprechende Library manuell einzubinden:
      https://github.com/espressif/arduino-esp32/blob/master/libraries/Preferences/src/Preferences.h

  3. 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.

    1. 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

  4. 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.

    1. 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

Kommentar hinterlassen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert