ESP32-2432S028 mit 2.8" Touchscreen (Cheap Yellow Display)
DC Utilities V5: MP3-Player

Bevor ihr mit diesem Artikel startet, solltet ihr euch zum Einstieg in die Materie zuerst ein wenig einlesen und die Hardware und das Pinout des TouchScreen-ESP32 ESP32-2432S028R-kennenlernen.

Außerdem solltet ihr euch eine Entwicklungsumgebung mit PlatformIO einrichten, wie in diesem Artikel besprochen. Danach solltet ihr noch den Artikel Programmierung des Displays mit der TFT_eSPI-Library lesen, in dem ihr lernt, wie wir etwas auf dem Display ausgeben.

Sowie den Artikel über die Programmierung des Touchscreen Digitizer XPT2046, der im Cheap Yellow Display steckt.

Damit wäre dann die Hardware-Ansteuerung von Display und Touchscreen bewerkstelligt. Nun kommt als Dialogsystem die LGVL Library obendrauf. In diesem Artikel erfahrt ihr, wie man diese für die weitere Verwendung einbindet und mit der Standard-LVGL-Demo (die, mit dem das Gerät ausgeliefert wurde) testet.

Im darauffolgenden Artikel haben wir dann gelernt, wie man LVGL-Dialoge entwirft und mittels Events steuert. Damit haben wir genügend gelernt, um unsere eigenen Anwendungen mit LVGL-Dialogen zu programmieren.

Doc Cool's Utilities V5


Im vorletzten Artikel habe ich die erste Version von Doc Cool's Utilities vorgestellt und die Idee, die dahinter steckt. Dies soll eine Sammlung von nützlichen Programmen sein, die über ein Menü aufgerufen werden sollen.

Da ich bemerkt habe, das es auch einige englischsprachige Leser gibt, versuche ich, die Dialog im Programm in (einfachem) Englisch zu halten, damit mehr Leute etwas davon haben, denn die fertige Firmware wird es wieder zum Download geben.

Außerdem spare ich mir, den kompletten Source-Code immer wieder zu wiederholen. Der steht ja schon in den vorhergehenden Artikeln. Ich werde also nur noch auf die neu hinzugekommenen Sachen eingehen. Das macht die ganzen Erklärungen kürzer und übersichtlicher.

Aus technischen Gründen, nämlich damit die WLAN-Antenne und evtl. weitere Antenne nicht von der Hand verdeckt werden und weil es der natürlicher Handhaltung am meisten entspricht, habe ich mich für ein Design der Dialoge im Portrait-Modus, also hochkant, entschieden.

Hardware: PC-Speaker

Dass und wie der Lautsprecher am besten um einen Widerstand um die 100 Ohm angeschlossen wird, habe ich bereits im letzten Artikel beschrieben. Da steht auch alles über die Audio-Library, die wir hier verwenden.

Mein Cheap Yellow Display ist inzwischen in das selbst entworfene 3D-gedruckte Gehäuse V3 eingezogen. Der Lautsprecher hat nun eine Buchse im Gehäuse und lässt sich damit jetzt ein- und ausstecken.

Neues Utility: MP3-Player


Die ESP32-AudioI2S-Library kann nicht nur zu MP3- und anderen Streams im Internet Verbindung aufnehmen und sie abspielen. Nein, sie kann natürlich auch lokale Audio-Dateien wiedergeben. Das geht ganz einfach. Zum Beispiel mit der Zeile audio.connecttoFS(SD, "/test.wav"); Eigentlich sollte die Library dabei folgende Formate beherrschen: Auf der sicheren Seite ist man also mit MP3-Dateien, AAC-Dateien und kurzen .WAV-Dateien. Zum Glück ist das, was ich am meisten verwende.

Da .wav-Dateien aber Abstürze (das CYD führt dann einfach einen Reset durch) sehr unschön sind, werden mit dem MP-Player nur .MP3, .M4A und .AAC-Dateien gesucht und abgespielt.

Die Suche nach Dateien geschieht folgendermaßen: Es werden alle Dateien mit den entsprechenden Endungen unterhalb des Verzeichnisses /mp3 auf der SD-Karte gesucht. Findet die Suchroutine ein Unterverzeichnis, so wird dieses auch nach MP3-Dateien durchsucht. Da die Suchroutine rekursiv programmiert ist, darf im Unterverzeichnis wieder ein Unterverzeichnis sein und darin wiederum eines. Es ist also kein Problem, seine MP3-Ordner samt Interpreten- oder Album-Unterordnern (oder beides) nach /mp3 zu kopieren. Doch sollten es nicht mehr als ein paar Hundert sein, sonst wird die Sache zu langsam. Auch wenn schon die schnellere subdir.getNextFileName(&isDir)-Methode des SD-Filesystems benutzt wird.

Es wird immer im Wiederholungsmodus abgespielt, das heißt: ist ein Lied zuende, geht es mit dem nächsten weiter. Ist das letzte Lied zuende, geht es mit dem ersten wieder los. Man kann mit dem rechten Button zwischen Normal- und Zufallswiedergabe wechseln. Die Buttons zeigen immer an, was passieren wird, wenn man darauf klickt. Beim Start ist man im normalen Wiedergabemodus (1, 2, 3, 4, 5 ...). Das Symbol mit dem überkreuzten Pfeilen wechselt in den Zufallsmodus (z. B. 1, 5, 3, 4, 5, 2 ...). Das ist schön, wenn man bei vielen MP3s nicht immer dieselbe Reihenfolge hören will. Hörbücher etc. muss man natürlich der Reihe nach abspielen.

Ansonsten gibt es noch drei Knöpfe zum Pausieren und zum Sprung zum Vorherigen und Nächsten Lied.

Falls das Lied MP3-id3-Information (ID3-Data) enthält, fischt uns die Audio-Library heraus und gibt sie uns an die Funktion void audio_id3data(const char *info) weiter, wo wir sie dann auswerten können:
void audio_id3data(const char *info){ //id3 metadata debug_print("id3data ");debug_println(info); String tag = info; if (tag.substring(0,7) == "Artist:") { lv_label_set_text (lab_audio_artist, tag.substring(8).c_str()); } else if (tag.substring(0,15) == "OriginalArtist:") { lv_label_set_text (lab_audio_artist, tag.substring(16).c_str()); } else if (tag.substring(0,6) == "Album:") { lv_label_set_text (lab_audio_album, tag.substring(7).c_str()); } else if (tag.substring(0,6) == "Title:") { lv_label_set_text (lab_audio_title, tag.substring(7).c_str()); } else if (tag.substring(0,5) == "Year:") { lv_label_set_text (lab_audio_year, tag.substring(6).c_str()); } }
Ich fülle dann die entsprechenden LVGL-Labels mit den gewonnenen Informationen. Auf das optionale - eigentlich sehr schöne und praktische - Durchscrollen von längeren Titeln habe ich verzichtet, was das die CPU sehr belastet und die MP3-Qualität verschlechtert. Apropos MP3-Qualität: Man muss auch (je nach Lautsprecher) auch auf eine genügend starke Spannungsquelle am USB-Port des CYD achten. Bei meinem PC-Anschluss habe ich es häufiger, dass die Stromversorgung nicht ausreicht und der Bildschirm flackert und die Soundqualität übel ist. Manchmal kommt es sogar zu einem Code brown, der anzeigt, dass nicht genügend Strom zum Weitermachen zur Verfügung steht. Dann resetet das CYD.

Auch das Ende des Liedes wird einem mitgeteilt, wenn gewünscht:
void audio_eof_mp3(const char *info){ //end of file debug_print("eof_mp3 ");debug_println(info); // danach weiterspielen ohne file macht reset // nächstes File do_mp3_player_sel_file(-1); }
Das sollten wir auf jeden Fall beachten, denn machen wir nach Ende des Liedes weiterhin ein audio.loop(), läuft der wegen fehlender Quelle ins Leere und bringt das CYD zum Reset.

Außer den MP3-Metadaten zeigt der MP3-Player noch das physische Verzeichnis und den Dateinamen auf der SD-Karte an und hat zwei Slider. Einen zur Einstellung der Lautstärke. Wird der ganz links auf Null gezogen, hält automatisch auch das Lied an.

Der zweite Slider zeigt die Position in der Wiedergabe an. Er startet links und wandert im Verlauf des Liedes ganz nach rechts, wo das Lied endet. Man kann den Slider verschieben, um im Lied vor- und zurückzuspulen oder an eine bestimmte Position zu springen. Sehr praktisch.

Unten schließt der Dialog wieder mit Statuszeile und Zurück-Button ab. In der Statuszeile werden auch alle weiteren Infos der Audio-Library ausgegeben. Meist geht das aber sehr schnell, so dass eigentlich nur die stehenbleibende Bitrate stehen bleibt zum Lesen.

Firmware Download via ESP Web Tools


Du möchtest die Firmware schon einmal ausprobieren, ohne die Entwicklungsumgebung zu installieren oder zu programmieren?

Kein Problem. Schließe einfach dein ESP32 an einen USB-Port deines PC an und klicke auf den deinem Gerät entsprechenden Button:

Die Firmware-Installation funktioniert leider nur mit Google Chrome und Chromium-basierten Browsern wie Microsoft Edge, Opera, Vivaldi oder Brave; jedoch nicht mit Firefox. Bitte benutze eine HTTPS-Verbindung, HTTP funktioniert nicht.

Die Firmware-Installation funktioniert leider nur mit Google Chrome und Chromium-basierten Browsern wie Microsoft Edge, Opera, Vivaldi oder Brave; jedoch nicht mit Firefox. Bitte benutze eine HTTPS-Verbindung, HTTP funktioniert nicht.

Demo und Video

Ich habe wieder ein kleine Demonstrations-Video gemacht, dass die neuen Dialoge in Aktion zeigt:


Mein Fazit zu dieser Programmier-Episode

Da das Abspielen von MP3-Files mit der AudioI2S-Library so einfach ist, gab es da nicht allzuviel zu tun beziehungsweise zu lernen. Außer vielleicht die Callback-Routinen bedienen.

Ein wenig wurde mein super ersten Eindruck von der Library allerdings getrübt. Ich hätte mir ein besseres Fehlermanagement gewünscht. Es muss ja eigentlich nicht gleich ein Reset geben, nur weil das Lied zuende ist und man audio.loop() dann ohne Lied aufruft. Da könnte man dann doch auch einfach eine Fehlermeldung ausgeben. Auch ist nicht gerade toll, dass es einen Reset bei so mancher meiner WAV-Dateien gibt, insbesondere, wenn diese länger waren.

Trotzdem ist das eine tolle Library, die mir viel Arbeit abnimmt. Und meckern ist ja auch nicht das probate Mittel zur Abhilfe. Entweder man meldet solche Fehlerchen dem Entwickler über Github, oder - insbesondere, wenn man merkt, dass dieser keine Zeit oder Lust mehr hat, was ich hier aber nicht glaube - man erstellt einen Fork und arbeitet selbst an einer bereinigten Version. Da mir wiederum die Zeit dafür ein wenig fehlt bzw. ich meine Prioritäten anders gesetzt habe und auch weil ich mit den kleinen Unzulänglichkeiten leben kann, lass ich das sein. Ich wollte diese Begebenheiten aber nicht verschweigen, damit ihr darauf achten und sie umschiffen könnt. Oder bitte nicht als Meckern missverstehen.

Ich werde noch ein wenig weiter mit der Library herum experimentieren. Mal schauen, was die noch so drauf hat...

Ansonsten war die Hauptsache, die ich diesmal dazu gelernt habe, der Umgang mit dem SD-Speicher. Da gibt es ewig viele Beispiele zu und die muss ich hier nicht wiederholen. Dadurch sie selbst einmal angewendet und angepasst zu haben lernt man aber natürlich mehr als einmal drüberfliegen und "achso geht das" zu sagen oder komplette Funktionen per copy and paste in den eigenen Code zu übernehmen.

Weitere Aussichten

Sobald der Bedarf entsteht, oder ich eine nette Idee für das nächste Utility habe, geht es mit dem nächsten Beispiel hier weiter. Dann werden Doc Cool's Utilities um ein weiteres Tool erweitert und es gibt wieder Erklärung und Anleitung, wie man das selbst machen kann.

Quellen, Literaturverweise und weiterführende Links