Es wurde schon tausend Mal gefragt und eigentlich habe ich es verstanden und wie ich glaube richtig gemacht, aber es funktioniert nicht.
Ich möchte die Anzahl der Tracks auf der SD-Karte im DFPlayer Mini auslesen. Dazu mein Code (Auszug):
SoftwareSerial mySoftwareSerial(10,11); // RX, TX
DFRobotDFPlayerMini myDFPlayer;
...
int anzahl = 1; // define global
void setup() {
mySoftwareSerial.begin(9600);
if (!myDFPlayer.begin(mySoftwareSerial)) { //Use softwareSerial to communicate with mp3.
while(true) { delay(0); } // Code to compatible with ESP8266 watch dog.
}
delay(2000); // give it time to start
...
anzahl = myDFPlayer.readFileCounts(); // set it
}
void loop() {
Serial.print("Count: "); Serial.println(anzahl); // print it
}
Beim Auslesen in loop() wird "anzahl" als -1 gelesen und die entsprechenden weiteren Abfragen funktionieren natürlich auch nicht.
Definiere ich anzahl = myDFPlayer.readFileCounts(); innerhalb von loop(), funktioniert alles bestens. Es ist aber Unfug, diese Zahl, die sich ja im Betrieb nicht ändert, bei jedem Durchlauf neu auszulesen, das muss doch möglich sein, sie in setup() nur einmal zu definieren?
SoftwareSerial mySoftwareSerial(10, 11); // RX, TX
DFRobotDFPlayerMini myDFPlayer;
int anzahl = -1; // define global
void setup()
{
mySoftwareSerial.begin(9600);
if (!myDFPlayer.begin(mySoftwareSerial)) //Use softwareSerial to communicate with mp3.
{
while (true)
{
delay(0); // Code to compatible with ESP8266 watch dog.
}
}
delay(2000); // give it time to start
while (anzahl < 0)
{ anzahl = myDFPlayer.readFileCounts(); } // set it
Serial.println(anzahl);
}
void loop()
{
Serial.print("Count: ");
Serial.println(anzahl); // print it
}
Weil der DF-Player wohl mehr als 2 Sekunden braucht bis er die Anzahl erfasst hat.
Du kannst ja mal spaßeshalber das delay(2000); in ein delay(10000); abändern.
Dann funktioniert es wahrscheinlich auch.
Die While-Schleife läuft ja so lange bis nicht mehr "-1" zurückgegeben wird.
Hier eine Code-Variante ganz ohne delay(2000) aber mit Ausgabe der Variable Anzahl
Auch ohne includes weil die Zeilen nicht gepostet wurden
#define dbgi(myFixedText, variableName,timeInterval) \
{ \
static unsigned long intervalStartTime; \
if ( millis() - intervalStartTime >= timeInterval ){ \
intervalStartTime = millis(); \
Serial.print( F(#myFixedText " " #variableName"=") ); \
Serial.println(variableName); \
} \
}
SoftwareSerial mySoftwareSerial(10, 11); // RX, TX
DFRobotDFPlayerMini myDFPlayer;
int anzahl = -1; // define global
void setup() {
mySoftwareSerial.begin(9600);
if (!myDFPlayer.begin(mySoftwareSerial)) //Use softwareSerial to communicate with mp3.
{
while (true)
{
delay(0); // Code to compatible with ESP8266 watch dog.
}
}
while (anzahl < 0)
{ anzahl = myDFPlayer.readFileCounts(); } // set it
dbgi("01",anzahl,500); // schreibe alle halbe Sekunde den Wert Anzahl in den seriellen Monitor
Serial.println(anzahl);
}
void loop() {
Serial.print("Count: ");
Serial.println(anzahl); // print it
}
Wenn Sie den Quellcode der Funktion in der Bibliothek betrachten
können Sie sehen, dass die Funktion bei einem erfolglosen Anforderungsvorgang -1 zurückgibt. Das bedeutet, dass Ihr DFPlayer trotz der willkürlichen 2-sekündigen Verzögerung, die Sie zuvor hatten, noch nicht bereit war.
Die von austriaka@my_xy_projekt gepostete Lösung durchläuft eine Schleife, bis "anzahl" nicht mehr negativ ist, was bedeutet, dass sie auf das Modul wartet, bis es bereit ist, die Anzahl bereitzustellen, und erst dann fortsetzt.
Ach, so einfach kann es sein.
Da ich VOLUME, EQ etc. auch schon setze und das funktioniert, bin ich auf diese Idee natürlich nicht gekommen. Danke dir!
Sehe ich das richtig, dass ich mir den delay(2000) dann auch ersparen kann, weil es ohnehin erst weitergeht, wenn der Player alles gelesen hat?
Nein.
Das ist nur ein Workaround.
Und las Dich nicht von dem C-Kram ablenken, du musst definitiv noch eine Abbruchfunktion einbauen, da Du sonst dort gefangen bist.
void setup()
{
mySoftwareSerial.begin(9600);
if (!myDFPlayer.begin(mySoftwareSerial)) //Use softwareSerial to communicate with mp3.
{
while (true)
{ delay(0); } // Code to compatible with ESP8266 watch dog.
}
while (anzahl < 0)
{
anzahl = myDFPlayer.readFileCounts(); // set it
if (millis() > 20000)
{ anzahl = 0; }
}
Serial.println(anzahl);
}
Stimmt. Der muss da natürlich auch noch rein...
Aber das ist nciht meine Schleife Vielleicht soll der ja gar nicht weitermachen, wenn der DFPlayer nicht angeschlossen ist?
Wenn er angeschlossen ist und das Dateisystem kaputt ist, gibt es wenigstens eine 0
Das ist Vereinbarung, aber weit verbreitet.
0 -> ok
kleiner 0 -> Fehler (evtl. mit jeweils einer Nummer nach Art des Fehlers)
größer 0 -> Warnung/Info (evtl. mit jeweils einer Nummer nach Art der Info)
Das wurde bei uns damals in C konsequent eingehalten. Auch die darunter liegenden PL/SQL - Routinen hielten sich an diese Konvention.
Natürlich muss man genau dokumentieren (bei uns im Headerfile) was welcher Returncode bedeutet.
@J-M-L und @my_xy_projekt
myDFPlayer.begin() gibt auch false zurück, wenn keine SD-Karte eingelegt ist. Insofern gehts eh nicht weiter, wenn begin() nicht erfolgreich ist. Das ist ein Code-Teil, den ich einfach aus dem Beispiel der Bibliothek behalten habe.
if (anzahl > 0) wird vor dem Abspielen abgefragt. Insofern sollte also nichts passieren, außer dass dann eben nichts passiert, oder?
if (millis() > 20000) { anzahl = 0; }
funktioniert leider nicht. Anzahl ist dann immer 0. Und nachdem ich die millis()-Funktion noch nicht durchschaut habe ... lass ich es einfach
Gibt dir die Laufzeit des Controllers in ms zurück, läuft nach 49 tagen über und fängt dann erneut bei 0 an.
Da sollte also 20 sekunden bei rauskommen.
Und bis dahin sollte der ausgelesen sein.