DFPlayer mit Arduino Nano auslesen

Hallo,

Ich möchte mir mit einem DFPlayer Mini und einem Arduino Nano einen kleinen portablen MP3-Player basteln. Wie man den Player benutzt, weiß ich, auch mit dem Arduino hat alles geklappt. Allerdings frage ich mich, ob man die Informationen über den gespielten Titel irgendwie vom Arduino auslesen lassen kann, um ihn auf einem Display anzeigen zu lassen. Oder noch besser, die gesamte Wiedergabeliste einlesen. Ist das irgendwie zu bewerkstelligen?

Philuminati:
... Allerdings frage ich mich, ob man die Informationen über den gespielten Titel irgendwie vom Arduino auslesen lassen kann, um ihn auf einem Display anzeigen zu lassen. Oder noch besser, die gesamte Wiedergabeliste einlesen. Ist das irgendwie zu bewerkstelligen?

AFAIR war das erst kürzlich Thema hier. Hast Du die Suche probiert?

Gruß

Gregor

Hab nichts gefunden, hast Du einen Link?

Philuminati:
Hab nichts gefunden, hast Du einen Link?

Ob es wirklich funktioniert, kann ich nicht sagen, aber hier steht einiges dazu geschrieben.

Hallo,

ob den Weg aus dem verlinkten Thread gehen willst, ist Deine Entscheidung.
Ich kann nur bestätigen: es gibt keinen Weg über den DPlayer mini an die Daten zukommen, er kann es nicht.

Gruß aus Berlin
Michael

Hallo zusammen,

mein von @HotSystems verlinkter Beitrag (danke dir) aus Mai/2017 hat nach wie vor Bestand: Vom DFPlayer lässt sich absolut nichts einlesen. Er ist wirklich nur ein Slave, der genau den Titel spielt welcher vom Controller vorgegeben wird.

Meine damals vorgestellte Lösung hatte sich auf den Winzling ATTiny 85 bezogen - und der war dadurch absolut vollgestopft. Die knapp 1800 Titel und ca. 500 Interpreten liegen in einem externen EEPROM und werden vom LCD angezeigt - parallel dazu wird lediglich die ID dazu (z.B. 1234.mp3) zum DFPlayer gesendet. Das alles zusammen ist für meine Belange ein ausreichender MP3-Player mit netten Optionen: Wunschliste - nur Titel eines Interpreten - Zufallssong usw.

Wenn man einen größeren Controller mit mehr RAM verwendet kann man die vom TO gewünschten Funktionen (Liste der gespielten Songs) sicherlich ebenfalls noch einbauen. Hierzu bräuchte man "lediglich" die angeforderte Songnummer hinterlegen und kann dann - querverknüpft - auf die Titel/Interpreten zurückgreifen.

Das ist vielleicht sogar noch eine nette Idee für mein "Küchenradio", welche ich dieses Jahr umsetzen könnte. :wink:

LG, Rudi

Das Ding ist, dass ich mir auch gedacht habe, externe EEPROM könnte eigentlich den Job machen... :smiley: Und siehe da, es ist tatsächlich auch deine Lösung, also denke ich, ich mache es einfach genau so. Kannst du mir sagen, wie du das Ganze auf dem EEPROM organisiert hast? Ich denke da gerade an zB 32 Byte große "Segmente" für jeweils einen Titel. Bei mir werden es max. 300 Titel.

Hallo,
aber klar doch kann ich dir gerne sagen wie mein EEPROM organisiert ist.

Dein Gedanke mit den 32 Bytes je Titel ist im ersten Moment korrekt. Die allermeisten davon sind wesentlich kürzer. Daraus folgt, dass du bei der Übertragung immer genau diese 32 Bytes je Titel übertragen musst – kürzere Titel als 32 Zeichen sind mit Blanks aufzufüllen. Das allein sichert die extrem simple Umsetzung der generierter Titel-Nummer, welche dann mit 32 multipliziert die tatsächliche Adresse im EEPROM ermittelt. Hast du also z.B. per Zufall den Titel Nr. 88 erzeugt (für 0088.mp3), dann rechnest du 88 * 32 = 2816 ... und hast somit die tatsächliche Adresse im EEPROM, von der aus du jetzt die 32 Bytes auslesen kannst. Eigentlich recht einfach.

Schwieriger wird es, die Daten ins EEPROM zu übertragen. Bekanntlich sind diese Chips in „Pages“ zu 32, 64 oder 128 Bytes organisiert. Wenn man diese Tatsache nicht berücksichtigt ... produziert man Chaos im EEPROM. Ich selbst habe – um das Gehampel mit den Pages zu umgehen – jedes Byte der Source-Datenbank einzeln ins EEPROM übertragen! Das dauerte bei meinen 1800 Titeln zwar eine gute Viertelstunde – aber damit hatte ich gerechnet und konnte damit gut leben. Die 1800 Titel belegen auf meiner 8 GB SD-Card fast den gesamten Raum. „Nur“ 300 Titel auf diese Weise ins EEPROM zu bekommen (und auszulesen) ist ja noch recht einfach. 300 x 32 Byte = 9600 Bytes Speicherverbrauch. Damit kann man gut leben.

Interessant wurde es aber für mich, als ich zu den Titeln auch die Interpreten erfahren wollte. Vor allen Dingen wenn man eine gemischte Datenbank hat, in der „Einzelstücke“ oder auch Sammlungen existieren. Dann kommt man mit dem o.g. Verfahren nicht mehr hin und muß einige ausführlichere „Klimmzüge“ machen. Dazu aber später mehr – falls Interesse besteht.

LG, Rudi

Für den Fall, es darf auch ein anderer MP3-Player sein: In meinem MP3-Player Projekt habe ich den von Adafruit verwendet, da man dort vollen Zugriff auf die Speicherkarte hat, die man mit einem PC verändern kann.

Ich würde an sich schon beim DFPlayer bleiben, weil ich den schon da liegen hab... war ein Geschenk. Was Rudi angeht, liebend gern würde ich mehr erfahren. Das Thema EEPROM ist für mich gänzliches Neuland, und auch wenn ich das Meiste davon verstehe, fände ich ein bisschen Unterstützung nicht schlecht. :slight_smile:

@agmue
So ist das wohl immer im Leben: Man hat ein Problem umständlich - aber dennoch erfolgreich - gelöst ... und dann erfährt man nachträglich, dass man das viel einfacher bewerkstelligt bekommen hätte ... aber egal, das Teil von Adafruit kannte ich noch nicht. Ich werde mich dort sicherlich einlesen, wie und ob das Teil für spätere Projekte eingesetzt werden kann. Danke für den Tipp :slight_smile:

@Philuminati
Okay, nachfolgend meine Gedanken von Anfang letzten Jahres und wie ich den DFPlayer „gezähmt“ bekam:

Zunächst wollte ich mit meinen 1800 MP3s nach o.g. Muster vorgehen ... mehr verpackt eine 8 GB Karte eh nicht. Wenn man rechnet 1800 x 32 Bytes ergibt das 57.600 Bytes Text. Passende EEPROMS mit max. 65.536 Bytes Kapazität waren auch vorhanden. Die Titel konnte ich nach obiger Vorgabe problemlos (inkl. jeweiliger Auffüllung auf 32 Bytes) gut unterbringen.

Direkt am Anfang kam aber der Wunsch auf, zu den Titeln auch die Interpreten abzuspeichern. Und ebenso wollte ich eine Funktion einbauen, mittels der ich alle Songs eines einzelnen Interpreten spielen lassen konnte. Wie z.B. von meiner CD „Forty Licks“ von den „Rolling Stones“. Je nach persönlicher Stimmung halt. Das EEPROM nach den Interpreten absuchen war „zeitnah“ nicht möglich. Und mit einem 64 kByte EEPROM wäre das ein nutzloses Unterfangen. Ebenso war es nicht möglich, auf die SD-Karte „direkt“ zuzugreifen und eine gespeicherte Textdatei auszuwerten. Also beschritt ich folgenden Weg:

Zunächst stellte ich alle MP3s von der PC-Festplatte zusammen und kopierte sie nach Interpreten sortiert in entsprechende Unterordner. Daraus erstellte ich zwei Text-Listen: Eine Interpreten-Liste mit betreffender ID (von 0 bis ca. 500), je Interpret 32 Bytes inkl. Blanks ... und eine Titel-Liste, welche jeweils die ID des Interpreten beinhaltete. Jeder Titel wurde dabei auf max. 30 Bytes aufgefüllt. Die letzten beiden Bytes bis 32 nahmen die ID zum Interpreten auf. Nun ließ ich die beiden Text-Files prüfen, wo irgendwelche Sonderzeichen vorhanden waren, die vom LCD-Display nicht ohne weiteres verarbeitet werden konnten. Auch musste der eine oder andere Tite bzw. Interpret manuell bearbeitet werden. Gerade bei Songs aus der Techno- oder Rapper-Szene kommen schon mal regelrechte „Roman“ vor, die meine 32- (30) Byte-Grenze überschritten.

Als EEPROM wählte ich für diese Datenmenge das 24FC1025-I/P. Dieses hatte 128 kByte Platz, aufgeteilt in 2 „Banks“ zu je 64 kByte. Als nächstes schrieb ich in DELPHI ein Programm, welches die einzelnen Titel inkl. Interpreten-ID seriell an den ARDUINO übertrug. Dort lief ein Empfänger-Programm, um die Titel in „Bank 1“ des EEPROMS zu hinterlegen.

Nun musste die I2C-Adresse für das EEPROM auf „Bank 2“ umgeschaltet werden und ich konnte die 32-Byte-Datensätze für die ca. 500 Interpreten hinterlegen. Da ich mir keine Gedanken um die „Pages“ machen wollte ging alles Byte für Byte rüber und brauchte dadurch diese gute Viertelstunde Zeit.

Nun denn, die Daten waren im EEPROM. Die MP3s wurden aus den jeweiligen Ordnern auf die SD-Karte kopiert. Hierbei habe ich per Software die notwendigen Nummern (0000_ bis 1800_) vor die betreffenden Titel gesetzt und alles ins Root der SD-Karte übertragen.

Die Software im ARDUINO (bzw. im ATTiny85) war nun relativ einfach: Per Menü-Auswahl (oder per Zufall) wurden vom Controller jetzt nur noch die Laufnummern erzeugt (z.B. 0123.mp3) und an den DFPlayer gesendet - schon wurde das gewünschte Lied gedudelt. Dabei kam mir die Tatsache zu Gute, dass der DFPlayer beide Varianten interpretiert: Entweder einen Song der nur mit „0123.mp3“ gespeichert ist, oder in langer Form „0123_honkytonk_women.mp3“. Aus „0123“ konnte direkt die Titel-Adresse in „Bank 1“ ermittelt werden. Am Ende der 32 zu lesenden Bytes waren die 2 Bytes für den Interpreten (z.B. 88). Diese Zahl ergab mit 32 multipliziert die Interpreten-Adresse in „Bank 2“. Auch diese habe ich eingelesen und konnte somit Titel UND Interpret anzeigen lassen, was gerade aus dem Lautsprecher tröpfelte.

Das ganze klingt extrem umständlich und mühsam. Besonders die zusätzliche Software auf dem PC. Aber nur durch die Trennung von Titel und Interpreten konnte ich meinen anfangs gehegten Wunsch nach „Playliste“ oder „Alle Songs eines Interpreten“ usw. realisieren. Das Teil funktioniert auch heute noch ohne Mucken. Und ... was man nicht vergessen sollte: Mein „Küchenradio“ besteht lediglich aus dem DFPlayer, einem ATTiny85, einer 3x3 Analog-Tastatur, einem 20x4 LCD-Display und einem PCF8574, um das LCD via I2C ansprechen zu können.

Erst wenn ich noch mal 1800 oder noch mehr MP3s gesammelt habe werde ich das System ggf ergänzen: Entweder untersuche ich den von @agmue genannten Adafruit-Player ... oder ich erweitere meine Schaltung auf max. 4 EEPROMS. So weit ich weiß können die ARDUINO-Bibliotheken eh nur SD-Karten bis 32 GB verarbeiten. Das ergäbe dann ca. 7200 Songs. Die muss man(n) aber erst mal sammeln; das wären ca. 420 Std bzw. 17,5 Tage unterschiedliche Mucke :wink:

Ich hoffe das war einigermaßen verständlich beschrieben
Falls offene Fragen bleiben: Nur Mut...

LG, Rudi

Soweit so gut... Ich denke ich verstehe das alles. Die Sache mit der Interpreten-ID finde ich gut, da bin ich nicht draufgekommen. Kannst du mir das mit den Pages nochmal erklären? Ich hab mir bisschen was zu EEPROMs durchgelesen und ich steige noch nicht ganz durch, was den Schreibvorgang angeht, wenn man mehrere Bytes schreiben will. Und wie man beim Lesen aus den Bytes wieder Strings macht. Und als letztes, ich habe bei mir versucht, eine 0000.mp3 abzuspielen. Hat nicht geklappt; gab ne IndexOutOfBoundException oder so. Das heißt, dass die Indizierung erst bei 1 beginnt und man dann folglich für die EEPROM-Adresse (Titelnummer-1)*32 machen müsste, oder? Btw, ich habe vor, einen 16 Kilobyte Speicher zu nehmen. Ich denke, dass bei meiner "geringen" Titelzahl das ausreichend sein sollte. Korrigier mich wenn ich falsch liege. :slight_smile:

Und noch so außenrum, ich habe mir zwei Lautsprecher besorgt, die eine super Qualität an den Tag legen, die ich gerne für das Projekt nutzen würde. Die beiden Lautsprecher werden in den Ohrenwärmern eines Skihelms landen :smiley: und ich wüsste gerne, wie ich genau einen Verstärker an den DFPlayer anschließe, um die beiden Lautsprecher mit Stereo zu verwenden. Beide haben 3 Watt Leistung bei 4 Ohm Impendanz.

Jetzt wird’s kompliziert :wink: das mit den „Pages“ wurde hier im Forum schon öfters angesprochen und ich tue mich schwer, diese großartige Erklärung noch einmal neu zu erfinden. Hier findes du mehr dazu: Verständnisfrage EEPROM schreiben

Ergänzend ein einfaches Beispiel aus meinem eigenen Verständnis:
eeprom.jpg

(A)
Du hast ein EEPROM mit z.B. 8 Bytes Page-Größe

(B)
Du möchtest 6 Bytes ab Adresse 6 schreiben

(C)
Zwischen „Wire.beginTransmission()“ und „Wire.endTramsmission()“ wird beim Schreiben ein interner Zähler im EEPROM gesetzt. Heißt: Ab Adresse 6 geht das ganze noch 2 Bytes lang gut. Nach dem Schreiben des 2. Bytes wird der interne Zähler wieder auf 0 gesetzt.

(D)
Das bewirkt in diesem Fall, dass die restlichen 4 Bytes am Anfang der selben Page landen ... und somit das ganze Teil vollkommen zerschießen.

Sicherlich geht das Senden von größeren Bytefolgen wesentlich schneller, aber aus Gründen der eigenen Sicherheit sollte man sich auf das Senden einzelner Bytes beschränken. Anderenfalls müßtest du komplizierte Programme entwerfen, die mit entsprechenden Buffern arbeiten und diese Sachen berücksichtigen. Vielleicht gibt es ja hier irgendwo eine fertige Bibliothek. Mögen fachkundigere Kollegen mich berichtigen.


Das Auslesen und Umwandeln in Strings (ich mag Strings gar nicht...) reicht es, wenn du die EEPROM-Adresse vorgibst und in einer Schleife die 32 Bytes in einen geeigneten (String-)Buffer einliest. Am Schluß pappst du noch eine Null-Terminierung dran - und fertig ist der String. Musst halt nur darauf achten, dass der "Ziel-String" 1 Byte länger sein muß als die zu lesenden Zeichen. Falls du wie ich mit Interpreten-ID arbeitest ist es natürlich erforderlich, die letzten beiden Bytes in einen INT zu übertragen. Diese beiden Bytes im String selbst müssen dann auf \0 gesetzt werden. Die Interpreten-ID ist dann (hochgerechnet) die Adresse für den Interpreten - den du wiederum auf die selbe Weise einlesen könntest.


0000.mp3 - Okay, da hatte ich etwas falsches in Erinnerung :frowning: Die Titel müssen in der Tat mit 0001.mp3 beginnen. Die weitere Vorgehensweise "(Titelnummer - 1) * 32" zur Ermittlung der tatsächlichen Adresse ist aber korrekt. Außerdem dürfen die MP3s NICHT im Root der SD-Card liegen, sondern dort in einem Unterverzeichnis "mp3". Für diese Fehler kann ich nur "Sorry" sagen.


Zu einem guten Verstärker kann ich nichts sagen. Wenn ich mehr Lautstärke brauche dann nehme ich irgend einen, den ich gerade griffbereit habe. Ist manchmal haarsträubend - aber dazu kann ich nichts geeignetes schreiben.

Viel Erfolg
Rudi

eeprom.jpg

RudiDL5:
... aber egal, das Teil von Adafruit kannte ich noch nicht. Ich werde mich dort sicherlich einlesen, wie und ob das Teil für spätere Projekte eingesetzt werden kann. Danke für den Tipp :slight_smile:

Hallo Rudi, schön mal wieder was von Dir zu lesen!

Für mein Projekt hat der Player auch mechanisch genau gepaßt, bei anderen Projekten muß man halt genauer schauen. Man hat normalen Zugriff auf die Speicherkarte, dafür braucht der Arduino Rechenzeit zum Musikschaufeln. - Wenn Du bei Adafruit nach "mp3" suchst, stößt Du noch auf weitere potenziell interessante Hardware. Es gibt aber noch mehr Anbieter, eine Suche, wenn man weiß, was man will, dürfte lohnend sein. Aber Du bist ja "Profi", Du weißt das eh :slight_smile:

@Philuminati: Sorry wegen des kleinen Exkurses.

Philuminati:
Ich hab mir bisschen was zu EEPROMs durchgelesen und ich steige noch nicht ganz durch, was den Schreibvorgang angeht, wenn man mehrere Bytes schreiben will.

Nutze anstelle des Dateityps String besser char. Möglicherweise meintest Du aber auch nur String=Zeichenkette.

Philuminati:
Und wie man beim Lesen aus den Bytes wieder Strings macht.

Für ein EEPROM sind es nur Nullen und Einsen. Es ist Deine Interpretation und die Deines Programmes, ob es sich dabei um Zahlen oder Buchstaben handelt.

OK, also das mit den Pages ist mir jetzt klar. Wenn ich lese, muss ich aber die Pages nicht beachten, richtig? So interpretiere ich zumindest die Aussage mit der Schleife. Und wie genau mache ich das mit den Chars? Kann ich einfach die Bytes auslesen und einen Cast (char) davorsetzen oder ist das zu simpel gedacht. Denn dann würde ich einfach sagen, dass ich ein Chararray mit 30 Plätzen aufmache, jedes Byte beim Auslesen direkt caste und anschließend die letzten beiden Bytes als Integer auslesen lasse.

Char (mit Vorzeichen) und Byte (ohne Vorzeichen) sind nur unterschiedliche Betrachtungen der gleichen 8 Bit. Die Zeichen sind eine weitere Betrachtungsweise.

Gruß Tommy

Bei max. 32 zu lesenden Bytes muss der Empfangs-Buffer wegen der 0-Terminierung immer 1 Byte länger sein. Das ist der Hauptgrund, warum ich keine Strings nutze sondern nur doch klar definierte Char-Arrays. Da weiss man was man hat und schenkt den vielen kleinen Fallen mehr Beachtung... Und JA, beim Lesen ist die Page-Grenze irrelevant.

Mein EEPROM ist gerade angekommen und somit kann ich mit dem Basteln beginnen :). Zwei Fragen: Kann ich mir einfach eine Klasse erstellen, die aus einem char[30] und einem Int besteht, und diese dann mit der get-Methode füllen? Und zweitens, ich glaube, mein Baustein hat 64-Byte-Pages. Dann könnte ich doch eigentlich auch einfach immer die 32er-Pakete als ein Ganzes schreiben lassen, oder? Hier das Datenblatt: https://www.mouser.de/datasheet/2/268/21191s-22168.pdf Es handelt sich um einen 24LC128. Sprich 16 KByte.

Philuminati:
Mein EEPROM ist gerade angekommen ...

Die EEPROM-Bibliothek ist für den internen Speicher eines Arduinos gedacht, nicht für externe Bausteine. Sorry, mein Fehler.

Dein Speicher wird mittels I2C angesprochen. Laß mal den I2C-Scanner laufen, auf welcher Adresse sich der Baustein meldet. Ggf. PullUp-Widerstände nicht vergessen.