2. Advent: Neues Internetradio mit ESP32 und MAX 98357A - AZ-Delivery

Nachdem der Blog-Beitrag Internet-Radio mit dem ESP32 ein großes Echo hervorrief, stellen wir hier jetzt eine zweite Variante vor, die zahlreiche Verbesserungen und Erweiterungen erhielt. Wesentlichste Änderung ist die Verwendung des I2S Digital Verstärkers MAX98357A an Stelle des Analogverstärkers. Das Display wurde auf 4 Zeilen mit 20 Zeichen vergrößert. Neben dem gerade gespielten Sender werden Datum und Uhrzeit, sowie die aktuelle Lautstärke angezeigt. In den beiden unteren Zeilen werden Informationen zum laufenden Programm angezeigt, die mit dem Audiostream mitgeschickt werden. Die Lautstärkeregelung erfolgt ebenso, wie die Senderwahl über einen Rotary-Encoder. Die Konfiguration kann, wie bei der verbesserten Version von Herrn Schröder (siehe Update im alten Beitrag), über einen Browser erfolgen. Über diesen Weg kann auch die Senderliste verändert und erweitert werden. Da manche URLs nicht abspielbar sind, kann eine URL über die Browserkonfiguration jetzt getestet werden, ehe sie gespeichert wird. Die Versorgung über Akku wurde weggelassen, da der Stromverbrauch zu hoch war. Zusätzlich kann ein Firmwareupdate über WLAN (Over The Air = OTA) erfolgen.

 

Benötigte Hardware

Anzahl Bauteil Anmerkung

1

ESP32 Development Board

 

2

I2S Digitalverstärker mit MAX98357A

 

1

Lautsprecher 2er Set

 

1

Widerstand 470 kOhm

 

1

Widerstand 10 kOhm

 

1

Elko 1000uF / 10V

 

1

DC-Einbaubuchse

 

2

Drehgeber Encoder

 

1

Lochrasterplatte 50x70

 

2

Federleisten 19-polig

 

2

Federleisten 7-polig

 

1

Stiftleiste 3-polig

 

1

Stiftleiste 4-polig

 

2

Stiftleiste 5-polig

 

2

Drehknöpfe für 6mm Achse

 

Mehrere

Jumperkabel weiblich zu weiblich

 

1

Bultgehäuse aus dem 3D-Drucker

 

1

Gehäuseboden aus dem 3D-Drucker

 

 

Schaltung

 

Die folgende Tabelle zeigt die Verwendung der Pins des ESP32

Gerät

Bezeichnung

ESP32

Verstärker links

LRC

25

BCLK

26

DIN

27

 

GAIN

GND

 

SD

+5V

 

GND

GND

VIN

+5V

Verstärker rechts

LRC

25

BCLK

26

 

DIN

27

 

GAIN

GND

 

SD

+5V über 470kΩ

 

GND

GND

 

VIN

+5V

LCD-Display

GND

GND

 

VCC

+5V

 

SDA

21

 

SCL

22

Encoder Lautstärke

CLK

14

 

DT

13

 

SW

 

 

+

+3.3V

 

GND

GND

Encoder Senderwahl

CLK

33

 

DT

32

 

SW

35 3.3V über10kΩ

 

+

+3.3V

 

GND

GND

Versorgung

+5V

VIN

 

GND

GND

 

Der ESP32 wird mit den Widerständen und Stiftleisten für die Peripherie auf einer 50x70 mm großen Lochrasterplatte aufgebaut. Für die beiden Verstärker-Module werden 7-polige Federleisten verwendet.


Die Abbildung zeigt die Bestückung und die Verdrahtung auf der Unterseite


Die Abbildung zeigt die Realisierung auf einer Lochrasterplatine 50 x 70 mm

Die Verdrahtung könnte auch über eine einseitig gedruckte Schaltung erfolgen. Lediglich die rot eingezeichnete Verbindung muss über eine freie Verbindung realisiert werden. Für den I2S Bus werden drei Drahtbrücken verwendet.
In die beiden 7-poligen Federleisten werden die zwei Verstärkermodule eingesteckt. Die beiden Rotary-Encoder und das Display werden mit Jumper Wire Kabel F2F mit den entsprechenden Stiftleisten auf der Lochrasterplatte verbunden. Die Lautsprecher werden an den Schraubklemmen der Verstärkermodule angeschlossen.


 

Software

Der Sketch wurde aus Gründen der Übersichtlichkeit in mehrere Teile zerlegt. Dazu wird eine Funktion genutzt, die die Arduino IDE zur Verfügung stellt. Gibt es neben dem Hauptsketch, der denselben Namen wie der Ordner hat, noch weitere „.ino“ oder „.h“ Dateien im selben Ordner, so werden diese vom Compiler in alphabetischer Reihenfolge an den Hauptsketch angehängt.
Da der gesamte Code sehr umfangreich geworden ist, gibt es diesen nur zum Herunterladen.

Sketch zum Herunterladen

Die ZIP-Datei enthält den Ordner mit allen zugehörigen Dateien. Sie muss in das Arbeitsverzeichnis der Arduino IDE (meist Dokumente\Arduino\) entpackt werden. Im Folgenden werden die einzelnen Teile kurz beschrieben. Eine detaillierte Beschreibung finden Sie als Kommentare im Code.

  • Webradio_MAX.ino: Das ist der Hauptsketch. Es werden globale Variablen und Datenstrukturen definiert.
    • setup() nach dem Initialisieren der seriellen Schnittstelle werden die Konfigurationsdaten aus den Präferenzen gelesen. Dann werden die Setupfunktionen der einzelnen Programmteile, mit Ausnahme von Webservers und OTA aufgerufen. Es folgt der Verbindungsaufbau zum lokalen WLAN. War die Verbindung nicht erfolgreich, werden auf dem Display Informationen zur Konfiguration angezeigt. Bei erfolgreicher Verbindung wird die Echtzeituhr initialisiert und die Wiedergabe der zuletzt gehörten Station gestartet. Nun kann auch das Setup für Webserver und OTA aufgerufen werden.
    • loop() prüft zuerst, ob OTA-Anfragen vorliegen und dann, ob es Anfragen für den Webserver gibt. Es wird überprüft, ob die Verbindung zum WLAN noch besteht. Wenn die Verbindung besteht, werden der Audiostream und die beiden Encoder auf Ereignisse geprüft. Einmal pro Minute wird die Anzeige der Uhrzeit aktualisiert. War die Verbindung mehr als 5 Minuten unterbrochen, wird der ESP32 neu gestartet.
  • audio.ino: In diesem Teil werden alle Funktionen im Zusammenhang mit den Audiostreams implementiert.
    • setup_audio() bereitet das System vor. Buffer und Stream-Ausgang werden initialisiert.
    • audio_loop() überprüft den Status des Audio-Streams.
    • MDCallback(void *cbData, const char *type, bool isUnicode, const char *string)
      wird immer dann aufgerufen, wenn im empfangenen Stream neue Metadaten verfügbar sind. Metadaten vom Typ „Title“ werden auf dem Display angezeigt.
    • stopPlaying() beendet das Abspielen des Streams und gibt die zugehörigen Ressourcen frei.
    • bool startUrl(String url) Startet das Abspielen eines Streams von einer gegebenen URL. Ist der Start nicht erfolgreich, wird false zurückgegeben.
    • setGain() setzt die Lautstärke auf den Wert der globalen Variablen currentGain.
  • display.ino: Enthält Funktionen zum Ansteuern des Displays und die Definition von Sonderzeichen wie Lautsprecher und deutsche Umlaute.
    • setup_display() initialisiert das Display und erzeugt die Sonderzeichen im Display-RAM.
    • String extraChar(String text) ersetzt im übergebenen UTF8-Text die deutschen Umlaute durch den entsprechenden Sonderzeichen-Code.
    • showStation() zeigt den Namen der aktuellen Radiostation in der zweiten Zeile des Displays an. Die Anzeige beginnt an der Position 2 und wird auf 18 Zeichen beschnitten. Ist die aktuelle Station auch die aktive Station so wird auf Position 0 das Lautsprechersymbol angezeigt.
    • displayMessage2(uint8_t line, String msg) der übergebene String wird ab der angegebenen Zeile in zwei Zeilen angezeigt. Beide Zeilen werden vorher gelöscht. Hat der String mehr als 20 Zeichen, erfolgt ein Zeilenumbruch. Die zweite Zeile wird nach 20 Zeichen abgeschnitten.
    • displayDateTime() In der ersten Zeile wird Datum und Uhrzeit angezeigt. In der äußerst rechten Position wird die aktuelle Lautstärke in Prozent angezeigt.
    • displayMessage(uint8_t line, String msg) der übergebene String wird in der angegebenen Zeile angezeigt. Die Zeile wird vorher gelöscht. Der String wird auf maximal 20 Zeichen beschnitten.
    • displayClear() löscht alle vier Zeilen.
    • clearLine(uint8_t line) löscht die angegebene Zeile
  • gain.ino: Steuert die Lautstärkeregelung mit einem Rotary-Encoder
    • gain_loop() prüft ob sich der Wert des Rotary-Encoders geändert hat. Ist das der Fall, wird der neue Lautstärkewert gespeichert und eingestellt.
    • IRAM_ATTR readGainISR() Interrupt-Behandlung für den Encoder
    • setup_gain() startet den Encoder, registriert die Interrupt-Routine, setzt die Grenzwerte und den aktuellen Wert als Voreinstellung.
  • index.h: Enthält die HTML-Seiten für den Webserver. Mit der Befehlsfolge
    const char MAIN_page[] PROGMEM = R"=====(
    beliebiger Text………
    )=====";

    kann ein beliebiger Text direkt als Konstante in den Programmspeicher eingebaut werden. Das ist für HTML-Seiten sehr praktisch, da diese dann außerhalb der IDE entworfen und getestet werden können. Die vorliegenden Seiten nutzen jQuery, Ajax und JavaScript. Der Vorteil von Ajax für interaktive Seiten liegt darin, dass bei Änderungen nur der veränderte Teil der Seite aktualisiert wird.  Es werden drei HTML-Konstanten definiert.
    • OPTION_entry ein Template für Einträge in der Auswahlliste für die Radiostationen
    • MAIN_page die Hauptseite mit Konfiguration und Wartung der Senderliste
    • CONFIG_page Seite zur Eingabe der Zugangsdaten, wenn der ESP32 zur Erstkonfiguration im Accesspoint Modus ist.
  • ota.ino: Hier sind die Funktionen zum Update der Firmware über WLAN zu finden.
    • setup_ota() es wird der Hostname und das Passwort festgelegt. Anschließend werden Callback-Funktionen registriert.
    • ota_onStart() wird beim Start eines OTA-Uploads aufgerufen. Das Display wird gelöscht und in der ersten Zeile eine entsprechende Meldung angezeigt
    • ota_onEnd() wird nach dem Beenden des Uploads aufgerufen. Eine entsprechende Meldung wird in der dritten Zeile angezeigt.
    • ota_onProgress(unsigned int progress, unsigned int total) wird während des Uploads in regelmäßigen Abständen aufgerufen und liefert Informationen über den Fortgang. In der zweiten Zeile des Displays wird der Fortgang in Prozent angezeigt.
    • ota_onError(ota_error_t error) wird aufgerufen wenn ein Fehler auftritt. Die Fehlermeldung wird dann in der vierten Zeile angezeigt.
  • rotary.ino steuert die Senderwahl mit einem Rotary-Encoder
    • rotary_loop() prüft, ob sich der Wert des Rotary-Encoders geändert hat. Ist das der Fall, wird die nächste Station aus der Senderliste angezeigt. Wird innerhalb von 10 Sekunden der Knopf am Encoder gedrückt, so wird auf die neue Station umgeschaltet. Wird der Knopf nicht gedrückt, erfolgt kein Wechsel und die aktuelle Station wird wieder angezeigt.
    • IRAM_ATTR readRotaryISR() Interrupt-Behandlung für den Encoder
    • setup_rotary() startet den Encoder, registriert die Interrupt-Routine, setzt die Grenzwerte und den aktuellen Wert als Voreinstellung.
  • stations.ino: definiert eine Programmspeicherkonstante mit der Default-Senderliste.
    • setup_senderliste() füllt die Senderliste im RAM mit der Senderliste aus den Preferences. Gibt es dort keine Senderliste, so wird die Default-Senderliste verwendet.
  • webserver.ino: Enthält das Setup und die Funktionen, um auf http-Anfragen zu reagieren.
    • setup_webserver(): Es werden die einzelnen Funktionen zum Behandeln der http-Anfragen registriert und der Server auf Port 80 gestartet.
    • webserver_loop() es wird geprüft, ob neue Anfragen vorliegen.
    • handleRoot() bearbeitet eine Anfrage für die Hauptseite. Liegt eine Verbindung ins lokale WLAN vor, wird die Hauptseite an den Client gesendet. Ist der ESP32 für die Grundkonfiguration im Accesspoint Modus, wird die Konfigurationsseite übertragen. Zusätzlich müssen in diesem Fall noch eventuell vorhandene Parameter verarbeitet werden, um die Zugangsdaten zu speichern, oder einen Neustart auszulösen.
    • sendStations() reagiert auf das Ajax-Kommando mit der URL /cmd/stations. Sendet die Liste der Stationen als HTML-Optionlist. Diese Liste wird dann über Javascript im Client in das Dropdownelement eingebaut.
    • setAccessData() reagiert auf das Ajax-Kommando mit der URL /cmd/setaccess. Die Konfigurationsdaten SSID, PKEY und NTP-Server werden in den Präferenzen gespeichert.
    • getAccessData() reagiert auf das Ajax-Kommando mit der URL /cmd/getaccess. Die Konfigurationsdaten SSID, PKEY und NTP-Server werden als Antwort gesendet. Als Trennzeichen wird das Zeilenende verwendet.
    • getStationData() reagiert auf das Ajax-Kommando mit der URL /cmd/getstation. Die ID der gewünschten Station wird als Argument erwartet. Es wird der Name, die URL und das Enable-Flag der angegebenen Station als Antwort gesendet. Als Trennzeichen wird das Zeilenende verwendet.
    • setStationData() reagiert auf das Ajax-Kommando mit der URL /cmd/setstation. Die ID der gewünschten Station wird als Argument erwartet. Ist die ID gültig, werden die als Argument übergebenen Daten für den Namen, die URL und das Enable-Flag in der Senderliste gespeichert.
    • testStation() reagiert auf das Ajax-Kommando mit der URL /cmd/teststation. Die URL, die getestet werden soll, wird als Argument erwartet. Es wird versucht, die Wiedergabe der angegebenen URL zu starten. Ist der Versuch nicht erfolgreich, so wird wieder auf die aktuelle Station zurückgeschaltet und mit „ERROR“ geantwortet.
    • endTest() reagiert auf das Ajax-Kommando mit der URL /cmd/endtest. Der Test wird beendet, indem die Wiedergabe der aktuellen Station gestartet wird.
    • restart() reagiert auf das Ajax-Kommando mit der URL /cmd/restart. Der ESP32 wird neu gestartet.
  • wlan.ino: Enthält die Funktion zum Herstellen einer Verbindung mit dem lokalen WLAN oder zur Bereitstellung eines Accesspoints, wenn eine Verbindung nicht möglich ist.
    • boolean initWiFi(String ssid, String pkey) versucht mit den angegebenen Zugangsdaten eine Verbindung zum lokalen WLAN herzustellen. Wenn keine SSID angegeben wurde, oder der Verbindungsversuch nicht gelingt, wird ein Accesspoint gestartet. Über diesen Accesspunkt kann dann von einem Browser unter der Adresse 192.168.4.1 die Konfigurationsseite aufgerufen werden.

Damit der Sketch kompiliert werden kann, muss die Arduino IDE entsprechend vorbereitet werden. Die Arduino IDE unterstützt standardmäßig eine große Anzahl von Boards mit unterschiedlichen Mikrocontrollern, nicht aber den ESP32. Damit man Programme für diese Controller erstellen und hochladen kann, muss daher ein Softwarepaket für die Unterstützung installiert werden.

Zuerst müssen Sie der Arduino IDE mitteilen, wo sie die zusätzlich benötigten Daten findet. Dazu öffnen Sie im Menü Datei den Punkt Voreinstellungen. Im Voreinstellungs-Fenster gibt es das Eingabefeld mit der Bezeichnung „Zusätzliche Boardverwalter URLs“. Wenn Sie auf das Icon rechts neben dem Eingabefeld klicken, öffnet sich ein Fenster, in dem Sie die URL https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json eingeben können.

Nun wählen Sie in der Arduino IDE unter Werkzeug → Board die Boardverwaltung.

Es öffnet sich ein Fenster, in dem alle zur Verfügung stehenden Pakete aufgelistet werden. Um die Liste einzugrenzen, gibt man im Suchfeld „esp32“ ein. Dann erhält man nur noch einen Eintrag in der Liste. Installieren Sie das Paket „esp32“. Falls das Paket schon installiert war, prüfen Sie bitte, ob Sie die neueste Version haben.

 

Für das Display benötigen Sie eine Bibliothek, die über die Arduino Bibliotheksverwaltung installiert werden kann. Das ist die Bibliothek „LiquidCrystal I2C“ von Marco Schwartz in der Version 1.1.2.

 

Eine weitere Bibliothek wird für den Rotary-Encoder benötigt. Ihr Name ist „AiEsp32RotaryEncoder“ von Igor Antolic in der Version 1.4.0.

Kernstück dieses Projekts ist aber die Bibliothek „ESP8266Audio“ von Earle F. Philhower in der Version 1.9.7.

Diese Bibliothek ermöglicht es, verschiedene digitale Audiostreams zu lesen, zu dekodieren und über verschiedene Ausgangskanäle wiederzugeben. Als Eingang, kann der Programmspeicher, der interne RAM´, ein Filesystem, eine SD-Karte, ein HTTP-Stream, oder ein ICY-Stream genutzt werden. Der ICY-Stream wird typisch von Internet-Radios genutzt.
Dekodiert werden können WAV, MOD, MIDI, FLAC, AAC und MP3 Dateien. Für das Webradio wird MP3 benötigt. Die Ausgabe kann schließlich in Speicher, Files oder I2S erfolgen.

Wenn alle Bibliotheken installiert sind, kann der Sketch kompiliert und auf die Hardware hochgeladen werden.

Achtung! Da sich der Sketch aus zahlreichen Teilen zusammensetzt, kann das Kompilieren, insbesondere beim ersten Mal, lange dauern. In den Voreinstellungen sollte „Compiler Warnungen“ auf „keine“ gestellt werden, da die LCD-Bibliothek fälschlicherweise eine Warnung ausgibt

Inbetriebnahme

Bei der ersten Inbetriebnahme sind noch keine Präferenzen vorhanden. Es kann daher keine Verbindung zum lokalen WLAN hergestellt werden. Ein Accesspunkt mit der SSID „webradioconf“ ohne Passwort wird gestartet. Mit z.B. einem Smartphone kann nun eine Verbindung zu diesem Accesspoint hergestellt werden. Danach kann in einem Browser über die Adresse 192.168.4.1 die Konfigurationsseite aufgerufen werden.

Nach dem Neustart sollte die Verbindung zum lokalen WLAN erfolgreich hergestellt werden können. Die Wiedergabe der Station 0 aus der Default Liste (NDR2) sollte mit einer Lautstärke von 50% starten. Mit dem Encoder für die Lautstärke kann die Verstärkung eingestellt werden. Änderungen werden in den Präferenzen gespeichert, sodass beim nächsten Einschalten dieselbe Lautstärke eingestellt wird. Mit dem anderen Encoder kann ein Sender aus der Liste gewählt werden. Beim Drehen des Encoders wird in der zweiten Zeile des Displays der Name der Station angezeigt. Durch Drücken des Kopfes am Encoder wird die gerade angezeigte Station zur aktuellen Station und die Wiedergabe wird gestartet. Auch dieser Wert wird in den Präferenzen gespeichert. Beim nächsten Start wird automatisch die zuletzt gewählte Station wiedergegeben. Wird der Knopf am Encoder innerhalb von 10 Sekunden nicht gedrückt, springt die Anzeige auf die aktuelle Station zurück.

Konfiguration und Bearbeitung der Senderliste

Über die URL http://webradio/ sollte die Konfigurationsseite abrufbar sein. Im oberen Teil können die Zugangsdaten und der NTP-Server geändert werden. Die Änderungen werden erst dann wirksam, wenn der Knopf „Speichern“ geklickt wurde.
Mit dem Knopf „Neustart“ kann ein Neustart ausgelöst werden.

Die Dropdown-Liste enthält alle Sender der Senderliste. Auswählbare Sender haben vor dem Namen einen schwarzen Punkt. Im Formular darunter werden die Daten zur ausgewählten Station angezeigt und können geändert werden. Ist das Häkchen bei „Verwenden“ nicht gesetzt, kann die Station im Gerät nicht ausgewählt werden. Da manche URLs nicht funktionieren, sollte eine neue URL mit dem Knopf „Testen“ getestet werden. Ein Klicken auf diesen Knopf startet die Wiedergabe der URL am Gerät. Sollte die Wiedergabe nicht funktionieren, wird sofort wieder auf den aktuellen Sender zurückgeschaltet und eine Meldung angezeigt. Ist die Wiedergabe möglich, wird eine Box mit einem Knopf angezeigt. Klicken auf diesen Knopf schließt die Box und beendet den Test. Es wird wieder die aktuelle Station wiedergegeben.  Mit dem Knopf „Ändern“ können die Änderungen für die ausgewählte Station dauerhaft geändert werden.

Firmware Update über OTA

Um das Programm zu aktualisieren ist es nicht notwendig, das Gerät zu öffnen und eine USB-Verbindung herzustellen. In der Arduino IDE sollten Sie bei den Ports den folgenden Eintrag sehen.

Über diesen Port können Sie nun einen Sketch hochladen. Zum Schutz muss nach Aufforderung das Passwort „radioupdate“ eingegeben werden. Da die Serielle Schnittstelle nicht genutzt werden kann, werden Meldungen am Display angezeigt.

Hinweise

Der ESP32 hat eine CPU mit zwei Kernen. Beim Internet Radio muss der Web-Datenstrom vom Internet über das http-Protokoll gelesen werden. Das geschieht im System-Thread, der auf dem Kern 0 läuft. Die Anwendung muss den empfangenen Stream dekodieren und in den Buffer schreiben, aus dem dann die Daten über DMA ohne Zutun der CPU ausgegeben werden. Das Dekodieren erfolgt im Anwendungs-Thread, der auf Kern 1 läuft. Wenn nun zusätzlich CPU-Zeit für Display und Encoder verwendet werden, kommt es zu kurzen Unterbrechungen, die beim Drehen der Encoder akustisch zu hören sind.

Eine Stromversorgung über den USB-Bus des ESP32 Moduls ist möglich. Die Versorgung über den externen Eingang ist nur eine Empfehlung.

Das 3D-Objekt zum Pultgehäuse ist so angeordnet, dass ein 3D-Druck ohne Stützstrukturen möglich ist. Den Link zu den Druckdateien finden Sie in der Bauteileliste am Anfang des Beitrages.

Viel Spaß mit dem Radio!

Beitrag als PDF

UPDATE

Herr Andreas Kühn hat das vierzeilige Display durch ein farbiges TFT-Display ersetzt. Er hat uns dankenswerter Weise erlaubt, seine Version hier zu veröffentlichen.

Die Funktionen für das Display mussten natürlich ersetzt werden. Auch zwei zusätzliche Bibliotheken sind erforderlich.
"U8g2" von Oliver in der Version 2.27.6 und
"GFX Library for Arduino" von Moon On Our Nation in Version 1.3.1

Die folgende Tabelle zeigt die Verdrahtung zwischen dem Display und dem ESP32

DISPLAY ESP32
VCC +5V
GND GND
CS GPIO 05
RESET EN
A0 GPIO 17
SDA GPIO 23
SCK GPIO 18
LED 3.3V

 

Sketch zum Herunterladen

DisplaysEsp-32Specials

131 commenti

Gerald Lechner

Gerald Lechner

@Joachim: https:// kann nicht empfangen werden. Aber meist gibt es den selben Stream auch über http:// so auch in Ihrem Fall.
http://st02.sslstream.dlf.de/dlf/02/128/mp3/stream.mp3
funktioniert.

Joachim

Joachim

https://st02.sslstream.dlf.de/dlf/02/128/mp3/stream.mp3

Dies ist die URL von Deutschlandradio Kultur. Der Test unter http://webradio/ schlägt fehl. Was mache ich falsch? Der Sender müsste doch zu empfangen sein – genau wie der Deutschlandfunk, welcher in Ihrer Liste enthalten ist.

Gerald Lechner

Gerald Lechner

ACHTUNG!!!!
In der Schaltung wurden die Anschlüsse des Rotary-Encoders für die Senderwahl vertauscht. Die Zeichnung ist jetzt korrigiert. Die Verbindungsliste unterhalb der Schaltung war immer richtig!

Gerald Lechner

Gerald Lechner

@Eddy: Man könnte Audiobuchsen parallel oder anstelle der Lautsprecher anbringen. Die Spannung dürfte bei ca. 3V liegen ist aber von der eingestellten Lauststärke abhängig.
@Sven Hesse: Freut mich, dass alles funktioniert. Das mit begin() stat init() stimmt für die im Beitrag angegebene Bibliothek nicht. init() startet den I2C Treiber Wire setzt Flags für das Display und ruft dann begin() auf.

Sven Hesse

Sven Hesse

Hallo,

vielen Dank für die Bereitstellung dieser “Webradioerweiterung”.
Bis auf einen kleinen Fehler im Abschnitt “display.ino” ( anstelle von lcd.init(); muss hier stehen lcd.begin();) gab es nix auffälliges.

Da ich kein ESP32 Development Board mehr hatte, habe ich dieses Projekt mit dem ESP32 D1 Mini umgesetzt.
Hierbei musste ich lediglich PIN13 (gain.ino) irgendwie ersetzen. Habe mich dann letztlich für PIN17 entschieden.
Läuft :-).

Rico Nobis

Rico Nobis

Hallo,

Ich benutze die neue Version arduino ide und nach ein Paar Updates, ließ sich der Sketch problemlos kompilieren. Bin gerade noch am Gehäuse Drucken, Oberteil ca. 11 Stunden, Boden ca, 6 Stunden. Habe schon 2 Radios von der ersten Variante gebaut und diese laufen tatellos. Bei dieser Version finde ich das Webinterface klasse, einfach mal so einen Sender neu programmieren.

Wünsche Ihnen und Ihrer Familie ein Frohes Fest und ein Gesundes Neues Jahr.

PS: Bei Fragen, melde ich mich wieder

Eddy

Eddy

Hi,
habe da noch eine Frage, lässt sich die Schaltung zusätzlich mit Chinchbuchsen für einen Audioausgang erweitern ?

Walter Knauer

Walter Knauer

Hallo,

mittlerweile läuft alles soweit. Es gibt aber eine Diskrepanz zwischen der Verdrahtungsliste und der Grafik. In der Grafik sind die Anschlüsse von CLK und SW des Gebers für die Senderwahl vertauscht; deshalb funktionierte diese zunächst nicht, da ich mich nach der Grafik gerichtet hatte.

Gerald Lechner

Gerald Lechner

@Eddy: Die Anzahl der Speicherplätze kann man mit der Definition im Hauptsketch verändern.
#define STATIONS 30 //number of stations in the list
Da im Sketch stations.ino irrtümlich die Anzahl als Konstante gesetzt wurde, muss dort auch eine Änderung vorgenommen werden.
Die Zeile
for (uint8_t i = 0; i<30; i++) {
muss auf
for (uint8_t i = 0; i<STATIONS; i++) {
geändert werden.
Da die Stationenliste im Präferenzenspeicher gespeichert werden steht nur ein begrenzter Platz zur Verfügung. Ein Test mit voller Ausnutzung der Datenstruktur, also 32 Zeichen für den Namen und 150 Zeichen für die URL ergab eine maximale Zahl von 49 Stationen. Da die Namen und URLs meist kürzer sind, könnten sich vielleicht 100 ausgehen. Eine andere Möglichkeit wäre es, das Programm so umzubauen, dass die dauerhafte Speichernung nicht im Präferenzenspeicher sondern im Flash-Filesystem erfolgt.

Reinhard Völler

Reinhard Völler

Tolles Projekt!! Ich habe es erst mal auf einem Breadboard zusammengesteckt,
lief auf Anhieb! Klasse und Frohe Weihnachten!

Eddy

Eddy

Hallo, wie kann man die Speicherplätze erhöhen, zb. auf 100 ?

werner

werner

Hallo Herr Lechner
In der Tat hatte ich den 10k Widerstand vergessen. Den habe ich angeschlossen,aber keine Veränderung. Neu kompilieren ändert auch nichts ebenso wie das anschließen an ein 1A Netzteil. Kein Accesspoint und das Display zeigt auch noch" Connect WLAN" rhytmisch an. Der serielle Monitor zeigt folgendes
Rebooting…
ets Jun 8 2016 00:22:57

rst:0xc (SW_CPU_RESET),boot:0×13 (SPI_FAST_FLASH_BOOT)
configsip:0, SPIWP:0xee
clk_drv:0×00,q_drv:0×00,d_drv:0xoo,cs0,drv:0×00,hd_drv:oxoo,wp_drv0x00
mode:DIO, clock div:1
load:0×3fff0030,len:1184
load:0×40078000,len:13160
load:0×40080400,len:3036
entry 0×400805e4
Load preferences
station 0, gain 50, ssid , ntp de.pool.ntp.org
New volume= 0,50
Connect WiFi
DisconnectSoft AP disconnectedSet WLAN ModeE (27630) task_wdt: Task watchdog got triggered. The following tasks did not reset the watchdog in time:
E (27630) task_wdt: -IDLE (CPU 0)
E (27630) task_wdt: Tasks currently running:
E (27630) task_wdt: CPU 0:wifi
E (27630) task_wdt: Aborting.

abort () was called at PC 0×400f418d on core 0

Backtrace:0×40083ef5:0×3ffbfc7c |<-CORRUPTED

ELF file SHA256: 0000000000000000

MfG Werner

Gerald Lechner

Gerald Lechner

Haben Sie den Pin G33 des ESP32, wie im Beitrag beschrieben über 10kOhm mit 3.3 V verbunden? Wenn nicht, bringen unkontrollierte Interrupts den ESP32 zum Absturz. Es könnte auch sein, dass die Stromversorgung über USB zu schwach für den Stromverbrauch (ca. 200 mA) des ESP32 im WLAN-Betrieb ist. Welche Ausgabe erhalten Sie am seriellen Monitor?

Werner

Werner

Hallo
Das Kompilieren scheint Dank ihrer Hilfe endlich geklappt zu haben. Nun kann ich mich aber nicht mit dem ESP32 verbinden. Das Display zeigt für etwa 10 s Connect WLAN geht dann kurz aus und zeigt wieder das gleiche an. Ich kann weder mit dem Handy noch mit dem Laptop einen Accesspoint finden.
MfG Werner

Gerald Lechner

Gerald Lechner

@werner: Sie haben den Hauptsketch geändert und dabei die Zeile #include vergessen. Ebenso fehlt die Datei Display.ino in Ihrem Projektordner. Sie sollten, wie im Beitrag beschrieben die komplette Ordnerstruktur wie sie im ZIP-File vom Download vorliegt, also Ordner webradio_MAX mit den zugehörigen Dateien in Ihr Arduino Projektverzeichnis kopieren. Wenn Sie dann in der Arduino IDE über das Sketchbook den Sketch webradio_MAX öffnen, erscheinen dann auch alle Teilprogramme in der Tab-Leiste. Wenn Sie nun mit Strg+U den Sketch kompilieren und hochladen, sollte alles fehlerfrei ablaufen.

Walter Knauer

Walter Knauer

Der isKey-Fehler ist behoben. In der Liste der Boards in der IDE gabe es zwei Einträge für das ESP32Dev-Board; ich hatte zunächst das Board mit dem Zusatz “ESP32 Arduino” ausgewählt. Korekt ist aber das Board ohne den Zusatz “Arduino”.

Walter

Walter Knauer

Walter Knauer

Hallo,
ich bekomme beim Kompilieren die Fehlermeldung
Compilation error: ‘class Preferences’ has no member named ‘isKey’

Hier ist die komplette Fehlermeldung:

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\wdkna\appdata\local\arduino15\packages\esp32\tools\xtensa-esp32-elf-gcc\gcc8_4_0-esp-2021r2-patch3\xtensa-esp32-elf\include\c++\8.4.0\xtensa-esp32-elf\no-rtti\bits\gthr.h:151,
from c:\users\wdkna\appdata\local\arduino15\packages\esp32\tools\xtensa-esp32-elf-gcc\gcc8_4_0-esp-2021r2-patch3\xtensa-esp32-elf\include\c++\8.4.0\ext\atomicity.h:35,
from c:\users\wdkna\appdata\local\arduino15\packages\esp32\tools\xtensa-esp32-elf-gcc\gcc8_4_0-esp-2021r2-patch3\xtensa-esp32-elf\include\c++\8.4.0\bits\basic_string.h:39,
from c:\users\wdkna\appdata\local\arduino15\packages\esp32\tools\xtensa-esp32-elf-gcc\gcc8_4_0-esp-2021r2-patch3\xtensa-esp32-elf\include\c++\8.4.0\string:52,
from c:\users\wdkna\appdata\local\arduino15\packages\esp32\tools\xtensa-esp32-elf-gcc\gcc8_4_0-esp-2021r2-patch3\xtensa-esp32-elf\include\c++\8.4.0\stdexcept:39,
from c:\users\wdkna\appdata\local\arduino15\packages\esp32\tools\xtensa-esp32-elf-gcc\gcc8_4_0-esp-2021r2-patch3\xtensa-esp32-elf\include\c++\8.4.0\array:39,
from c:\users\wdkna\appdata\local\arduino15\packages\esp32\tools\xtensa-esp32-elf-gcc\gcc8_4_0-esp-2021r2-patch3\xtensa-esp32-elf\include\c++\8.4.0\tuple:39,
from c:\users\wdkna\appdata\local\arduino15\packages\esp32\tools\xtensa-esp32-elf-gcc\gcc8_4_0-esp-2021r2-patch3\xtensa-esp32-elf\include\c++\8.4.0\functional:54,
from C:\Users\wdkna\Documents\Arduino\hardware\espressif\esp32\libraries\WiFi\src/WiFiGeneric.h:28,
from C:\Users\wdkna\Documents\Arduino\hardware\espressif\esp32\libraries\WiFi\src/WiFiSTA.h:28,
from C:\Users\wdkna\Documents\Arduino\hardware\espressif\esp32\libraries\WiFi\src/WiFi.h:32,
from C:\Users\wdkna\Dropbox\Arduino\webradio_MAX\webradio_MAX.ino:1:
c:\users\wdkna\appdata\local\arduino15\packages\esp32\tools\xtensa-esp32-elf-gcc\gcc8_4_0-esp-2021r2-patch3\xtensa-esp32-elf\include\c++\8.4.0\xtensa-esp32-elf\no-rtti\bits\gthr-default.h: In function ‘int gthread_mutex_timedlock(gthread_mutex_t*, const __gthread_time_t*)’:
c:\users\wdkna\appdata\local\arduino15\packages\esp32\tools\xtensa-esp32-elf-gcc\gcc8_4_0-esp-2021r2-patch3\xtensa-esp32-elf\include\c++\8.4.0\xtensa-esp32-elf\no-rtti\bits\gthr-default.h:781:12: error: ‘pthread_mutex_timedlock’ was not declared in this scope
return gthrw_(pthread_mutex_timedlock) (mutex, __abs_timeout);
^~~~~~~~
c:\users\wdkna\appdata\local\arduino15\packages\esp32\tools\xtensa-esp32-elf-gcc\gcc8_4_0-esp-2021r2-patch3\xtensa-esp32-elf\include\c++\8.4.0\xtensa-esp32-elf\no-rtti\bits\gthr-default.h:781:12: note: suggested alternative: ‘pthread_mutex_trylock’
C:\Users\wdkna\Dropbox\Arduino\webradio_MAX\webradio_MAX.ino: In function ‘void setup()’:
C:\Users\wdkna\Dropbox\Arduino\webradio_MAX\webradio_MAX.ino:45:12: error: ‘class Preferences’ has no member named ‘isKey’
if (pref.isKey(“ssid”)) ssid = pref.getString(“ssid”);
^~~~~
C:\Users\wdkna\Dropbox\Arduino\webradio_MAX\webradio_MAX.ino:46:12: error: ‘class Preferences’ has no member named ‘isKey’
if (pref.isKey(“pkey”)) pkey = pref.getString(“pkey”);
^~~~~
C:\Users\wdkna\Dropbox\Arduino\webradio_MAX\webradio_MAX.ino:47:12: error: ‘class Preferences’ has no member named ‘isKey’
if (pref.isKey(“ntp”)) ntp = pref.getString(“ntp”);
^~~~~
C:\Users\wdkna\Dropbox\Arduino\webradio_MAX\webradio_MAX.ino:49:12: error: ‘class Preferences’ has no member named ‘isKey’
if (pref.isKey(“gain”)) curGain = pref.getUShort(“gain”);
^~~~~
C:\Users\wdkna\Dropbox\Arduino\webradio_MAX\webradio_MAX.ino:52:12: error: ‘class Preferences’ has no member named ‘isKey’
if (pref.isKey(“station”)) curStation = pref.getUShort(“station”);
^~~~~
Mehrere Bibliotheken wurden für “Preferences.h” gefunden
Benutzt: C:\Users\wdkna\Documents\Arduino\hardware\espressif\esp32\libraries\Preferences
Nicht benutzt: C:\Users\wdkna\Documents\Arduino\libraries\Preferences
Mehrere Bibliotheken wurden für “SD.h” gefunden
Benutzt: C:\Users\wdkna\AppData\Local\Arduino15\libraries\SD
Nicht benutzt: C:\Users\wdkna\Documents\Arduino\hardware\espressif\esp32\libraries\SD
exit status 1

Compilation error: ‘class Preferences’ has no member named ‘isKey’

Die Bibliotheken haben die geforderten Versionsnummern (esp32 2.0.5; esp8266audio 1.9.7; Encoder 1.4.0; IDE 2.0.3)

Woran kann’s liegen?

Walter

werner

werner

Hallo liebes az Team
Habe auf dem Breadboard die Schaltung aufgebaut,erstmal ohne Verstärker die bekomme ich erst. Wie schon geschrieben erhalte ich die folgende Fehlermeldung.Arduino: 1.8.19 (Windows 10), Board: “ESP32 Dev Module, Disabled, Default 4MB with spiffs (1.2MB APP/1.5MB SPIFFS), 40MHz (40MHz XTAL), DIO, 80MHz, 4MB (32Mb), 115200, Core 1, Core 1, None, Disabled”

ota:47:18: error: variable or field ‘ota_onError’ declared void

void ota_onError(ota_error_t error) { ^~~~~~~~~~~

ota:47:18: error: ‘ota_error_t’ was not declared in this scope

C:\Users\werne\AppData\Local\Temp\arduino_modified_sketch_467796\ota.ino:47:18: note: suggested alternative: ‘error_t’

void ota_onError(ota_error_t error) { ^~~~~~~~~~~ error_t

C:\Users\werne\AppData\Local\Temp\arduino_modified_sketch_467796\ota.ino: In function ‘void setup_ota()’:

ota:6:3: error: ‘ArduinoOTA’ was not declared in this scope

ArduinoOTA.setHostname(“webradio”); ^~~~~~~~~~

C:\Users\werne\AppData\Local\Temp\arduino_modified_sketch_467796\ota.ino:6:3: note: suggested alternative: ‘Arduino_h’

ArduinoOTA.setHostname(“webradio”); ^~~~~~~~~~ Arduino_h

ota:12:22: error: ‘ota_onError’ was not declared in this scope

ArduinoOTA.onError(ota_onError); ^~~~~~~~~~~

C:\Users\werne\AppData\Local\Temp\arduino_modified_sketch_467796\ota.ino:12:22: note: suggested alternative: ‘ota_onEnd’

ArduinoOTA.onError(ota_onError); ^~~~~~~~~~~ ota_onEnd

C:\Users\werne\AppData\Local\Temp\arduino_modified_sketch_467796\ota.ino: In function ‘void ota_onStart()’:

ota:19:3: error: ‘displayClear’ was not declared in this scope

displayClear(); ^~~~~~~~~~~~

C:\Users\werne\AppData\Local\Temp\arduino_modified_sketch_467796\ota.ino:19:3: note: suggested alternative: ‘spiSSClear’

displayClear(); ^~~~~~~~~~~~ spiSSClear

ota:22:7: error: ‘ArduinoOTA’ was not declared in this scope

if (ArduinoOTA.getCommand() == U_FLASH) ^~~~~~~~~~

C:\Users\werne\AppData\Local\Temp\arduino_modified_sketch_467796\ota.ino:22:7: note: suggested alternative: ‘Arduino_h’

if (ArduinoOTA.getCommand() == U_FLASH) ^~~~~~~~~~ Arduino_h

ota:22:34: error: ‘U_FLASH’ was not declared in this scope

if (ArduinoOTA.getCommand() == U_FLASH) ^~~~~~~

ota:28:3: error: ‘displayMessage’ was not declared in this scope

displayMessage(0,"Updating " + type); ^~~~~~~~~~~~~~

C:\Users\werne\AppData\Local\Temp\arduino_modified_sketch_467796\ota.ino: In function ‘void ota_onEnd()’:

ota:33:3: error: ‘displayMessage’ was not declared in this scope

displayMessage(2,“End”); ^~~~~~~~~~~~~~

C:\Users\werne\AppData\Local\Temp\arduino_modified_sketch_467796\ota.ino: In function ‘void ota_onProgress(unsigned int, unsigned int)’:

ota:40:5: error: ‘lcd’ was not declared in this scope

lcd.setCursor(10,1); ^~~

C:\Users\werne\AppData\Local\Temp\arduino_modified_sketch_467796\ota.ino: At global scope:

ota:47:18: error: variable or field ‘ota_onError’ declared void

void ota_onError(ota_error_t error) { ^~~~~~~~~~~

ota:47:18: error: ‘ota_error_t’ was not declared in this scope

C:\Users\werne\AppData\Local\Temp\arduino_modified_sketch_467796\ota.ino:47:18: note: suggested alternative: ‘error_t’

void ota_onError(ota_error_t error) { ^~~~~~~~~~~ error_t

exit status 1

variable or field ‘ota_onError’ declared void

Gerald Lechner

Gerald Lechner

@Wofgang Menzel: Es gibt leider zahlreiche Streams, die mit der Software nicht wiedergegeben werden können. Ursache kann das verwendete Stream-Protokoll oder Audioformat sein. Deshalb habe ich die Test-Funktion eingebaut. Der Stream muss MP3 sein. https:// funktioniert nicht. Bei manchen der URLs kann statt https:// auch einfach http:// geschrieben werden. Über den folgenden Link habe ich die URLs gefunden, die funktioniert haben.
https://hendrikjansen.nl/henk/streaming3.html#du

Wolfgang Menzel

Wolfgang Menzel

Hallo, ich muss mich doch nochmal melden.
Das Radio spielt perfekt. Allerdings habe ich Probleme, neue Sender einzusetzen über http://webradio/. Wenn ich auf Testen gehe, dann kommt sofort Webradio ERROR. Ich habe viele Sender von der Liste aus https://linupedia.org/opensuse/Radiosender ausprobiert, aber alles mit ERROR.

Gruß
Wolfgang

Schorsch

Schorsch

Besten Dank. Es lag an der Board-Verwalter-URL. Meine alte war ganz anders. Das Teil spuckte nur eine Version 1.0.6 aus.
Mit der Neuen gab es auch eine Version 2.0.5.

Gerald Lechner

Gerald Lechner

@Werner: void ota_onError(ota_error_t) gibt nur die Stelle im Code an, wo der Fehler auftritt. Danach sollte noch die eigentliche Fehlermeldung folgen.
@Schorsch: Das sieht nach einem Versionsproblem aus. Wie im Beitrag angegeben muss die Version des ESP32 Package 2.0.1 oder höher und die der ESP8266audio Bibliothek 1.9.7 sein

Schorsch

Schorsch

Hallo,
ich bekomme die Fehlermeldung (gleich 3x mal mit unterschiedlichen Libraries):

C:\Users\Schorsch\Documents\Arduino\libraries\ESP8266Audio\src\AudioOutputI2S.cpp: In member function ‘bool AudioOutputI2S::SetPinout()’:
C:\Users\Schorsch\Documents\Arduino\libraries\ESP8266Audio\src\AudioOutputI2S.cpp:95:41: error: ‘i2s_pin_config_t’ has no non-static data member named ‘mck_io_num’
.data_in_num = I2S_PIN_NO_CHANGE};
Was kann ich tuen?
Danke

Wolfgang Menzel

Wolfgang Menzel

Wow, ein super Projekt. Hochachtung vor der starken Leistung.
Ich habe es einfach mal auf einem Steckbrett aufgebaut und es funktioniert auf Anhieb, allerdings noch ohne Ton, habe die Verstärker erst bestellt.
Die Konfigurationen haben sofort geklappt, Senderauswahl und Lautstärkeregelung geht auch.
Das Display zeigt alle Infos an. Vielleicht mache ich mich mal an die Arbeit und setze ein 1.3 OLED ein (oder 2.4 TFT).
Grüsse
Wolfgang

Werner

Werner

Hallo
Ich habe bisher nur das Display angeschlossen. Beim überprüfen in der Arduino IDE bekomme ich schon diese Fehlermeldung: void ota_onError(ota_error_t)
Das Display zeigt nichts an

Gerald Lechner

Gerald Lechner

@Werner: Das ist nicht die ganze Fehlermeldung. Der wesentliche Teil fehlt. Um Helfen zu können, brauche ich die ganze Fehlermeldung.
@Jörg Linsel: Das Board ist “ESP32 Dev Module”. Wenn trotzdem Fehlermeldungen kommen, brauche ich die genauen Fehlermeldungen um zu helfen.
@Konrad S.:Sollte auch mit der IDE 2.0 funktionieren allerdings geht danndas Laden des Programms über OTA nicht, da die Netzwerk Ports derzeit von der Arduino IDE 2.0 nicht unterstützt werden. Upload über USB funktioniert aber.

Konrad S.

Konrad S.

Hallo Team AZ,

wieder mal ein Interessanter Blog. Kleine Frage bevor ich loslege.
Geht das Ganze auch mit der Arduino IDE 2.0?

Danke

K. Sternberg

Jörg Linsel

Jörg Linsel

Hallo,
super Projekt. Meine Hochachtung.
Welches Board stelle ich ein?
Ich hoffe, daß mit dem richtigen Board die Fehlermeldungen verschwinden.

MfG Jörg

Werner

Werner

Hallo.Beim kompilieren bekomme ich die Fehlermeldung: void ota_onError(ota_error_t error) {
Was muß ich tun

Andreas Wolter

Andreas Wolter

@Ines: Wenn man die ZIP-Datei entpackt und dann mit der Arduino IDE die Datei webradio_MAX.ino öffnet, sollten alle anderen Dateien auch geöffnet werden. Sie erscheinen im oberen Teil des Editors als Reiter, nicht als separate Fenster.
Ich habe das hier eben kurz getestet und es funktioniert auch.

Grüße,
Andreas Wolter
AZ-Delivery Blog

Ines

Ines

Hallo, habe die ZIP Datei geladen und in Sketchbook entpackt. So weit so gut. Wenn ich jetzt den Sketch lade, wird nur der webradio_MAX.ino geladen und sonst kein andere… Könnt mal bitte jemand genau schreiben was ich machen muss damit ich den Sketch komplett laden kann? Bitte, Bitte

MfG Ines

Lascia un commento

Tutti i commenti vengono moderati prima della pubblicazione