So, auch ich konnte nicht anders und musste, nur um es zu wissen, bei tinytronics eine Bestellung aufgeben.
Als DFR0299 wurden mir, wie auf der Homepage dargestellt, Player mit dem DFROBOT LISP3 Chip geschickt.
Hier kann ich die Beobachtungen von @Thomas-Lehnert zum Einschaltgeräusch bestätigen. Der Player durchlief den DFPlayerAnalizer den ich auf github gefunden habe ohne Probleme. Auch die DEV schien zuerst ohne Probleme zu laufen. Allerdings ist mir dann doch aufgefallen, dass der Player nach der Advert-Funktion ein TrackFinished Event sendet, das beim Tonuino dann ein nextTrack auslöst.
Der als AC20BP angebotene Player ist mir mit einem JL Chip statt des abgebildeten YX5200 geliefert worden.
Dieser Player tut was er soll und läuft bisher ohne Probleme.
Edit: der gelieferte JL läuft doch nicht ganz reibungslos.
Der TrackFinish Event entspricht nicht dem alt bekannten, sondern dem vom hier im Forum auch schon besprochenen MH2024K-16SS
Ich habe das mal gecheckt. Es ist tatsächlich so, dass der Player auch nach dem Abspielen eines Advert ein OnPlayFinished(DfMp3_PlaySources source, uint16_t track) ausgibt, das dann die Queue jeweils einen Wert weiter schaltet. Das bewirkt, dass wenn der aktuelle Track beendet ist, der nächste Track praktisch übersprungen wird. Werden beim Abspielen eines Tracks mehrere adverts abgespielt, werden soviele Tracks in Folge übersprungen wie Adverts abgespielt wurden. Man muss also einen Weg finden das nextTrack beim Abspielen eines Adverts zu unterdrücken und zwar explizit für den dfRobot Player.
Das Problem mit dem Finish-Event bei Advertisement gab’s schonmal in der Diskussion über den GB3200B. @Bastelmatz hat für seine Software dafür eine Lösung gefunden:
Hier dachte ich bisher, dass der o.a. Fix für das doppelte Finish-Event nach einer Datei aus den Ordner 1 bis 99 gedacht ist
Das Phäomen hatte ich eben auch in der DEV, so dass der o.a. Fix hier nicht zu greifen scheint.
Ich habe eine Lösung dafür gefunden, die unabhängig davon ob ein Player das EndOfTrack Event nach Advert ausgibt oder nicht, funktioniert. Es ist also keine Unterscheidung mehr notwendig ob der Player das bei Advert ausgibt oder nicht.
Dazu habe ich eine boolVariable AdvPlaying eingefügt, die beim Abspielen von Advert auf true gesetzt wird.
// ******************** DF-Player **************************************************
// DFPlayer Mini
SoftwareSerial mySoftwareSerial(2, 3); // RX, TX // Digitalpins zur Steuerung des DF-Players
uint8_t numFolders; // Anzahl der Ordner im Speichermedium
uint8_t numTracksInFolder; // Anzahl der Tracks im Ordner
uint8_t firstTrack; // erster Track
uint8_t currentQueueIndex; // index in queue[] aktuelle Tracknr in der queue
uint8_t queueSize; // Länge der queue
uint8_t queue[255]; // max 255 tracks/folder. entries 0..254 and values 1..255 are used.
uint8_t volume; // Lautstärke
bool AdvPlaying = false; // Advert wird abgespielt, Voreinstellung Nein
Wird jetzt ein Advert abgespielt und der Player gibt ein EndOfTrack Event aus, wird bei AdvPlaying = true ,die Anweisung nextTrack(track); nicht ausgeführt. Im Code sieht das so aus:
// Meldung vom Df Player - Track beendet , Meldung erfolgt
static void OnPlayFinished(DfMp3_PlaySources source, uint16_t track) // am Ende von normalen mp3 Files
{ // am Ende von Files aus dem mp3-Ordner
delay(100);
// Zusatzabfrage für DF-Player, die auch am Ende
// von Adverts ein Track beendet ausgeben. z.B.DFROBOT DF 290
if(!AdvPlaying) // Wenn kein Advert abgespielt wurde
{
// #ifdef Konsole
PrintlnSourceAction(source, "OPFin -> nxtTr"); // wird am Ende von advert-Tracks nicht gesendet
// #endif
nextTrack(track); // Wenn der Track regulär beendet wird , nextTrack.
}
AdvPlaying = false; // Marker zurücksetzen dass Advert gespielt wurde
} // außer bei advert-Tracks
Zu jeder PlayAdvert Anweisung wurde das setzen der Variable AdvPlaying auf true hinzugefügt.
z.B.
@Thomas-Lehnert würdest du das vielleicht auch einmal so teilen, dass man das mit der DEV nutzen kann. Denn das define für die Konsole gibts da ja nicht
Ja, ist doch ganz einfach. die #ifdef und #endif weglassen und es geht in der DEV. Auch ohne die def geht das, dann wird nur die Ausgabe in der Konsole nicht ausgeführt. Aber ja, ich werde das so ändern, dass es überall funktioniert.
Diese ganzen Klone sind echt der „Hammer“!
Diese Lösung klappt gut, für die meißten Versionen, die ich ausprobiert habe! Leider führt sie bei meinen „neuen JL“ von tinytronics dazu, dass, nachdem einmal ein Advertisement abgespielt wurde, das nextTrack nicht mehr verarbeitet wird .
Also doch wieder Codeanpassung je nach Modell
Hast du konsequent nach jedem Advertaufruf diese Zeile eingefügt?
Das NextTrack wird nach abspielen eines Advert nur unterdrückt, wenn der Player nach dem Abspielen eines Advert das EndOfTrack Event ausgibt. Gibt der Player das Event nicht aus, wird dieser Part gar nicht ausgeführt. Wichtig ist das Zurücksetzen der Variablen AdvPlaying auf false, nach jedem Event EOT, sonst wird jeder weitere NextTrack auch unterdrückt.
Zusätzlich sollte bei den Fehlermeldungen des DF-Players bei Auftreten eines advertiseErrors das advPlaying auch auf false zurückgesetzt werden. Je nach Fork kann das unterschiedlich aussehen. Bei mir sieht das so aus.
case DfMp3_Error_Advertise: {
Serial.print(F("7- adv")); // Fehler beim Abspielen Advert
AdvPlaying = false;
break;
}
Jupp, habe die DEV dahingehend durchsucht und die Zeile bei jedem Advertaufruf eigefügt.
Das habe ich in die static void OnPlayFinished so wie von dir geschrieben rein gesetzt.
Habe dann nach dem Raufladen nur den Player getauscht, und wie geschrieben, bei den meißten Exemplaren macht es das was es soll. Nur der neue JL führt kein nextTrack mehr aus nachdem einmal ein advert gelaufen ist. Bis dahin gibt es keine Probleme.
Eine Fehlermeldung bekomme ich nie ausgegeben, aber
das werde ich nochmal austesten
Edit: wobei ich in der DEV keine eigene Fehlerausgabe nur für Advert gefunden habe, sondern nur eine static void OnError
Setze mal diesen Part zusätzlich vor die if(!AdvPlaying)
Dann kannst du in der Konsole sehen wann das EOT Event ausgegeben wird, unabhängig ob von Advert oder normalem mp3Track. Die ausführung des nextTrack ist trotzdem von der if abfrage abhängig, auch wenn es jedesmal angezeigt wird. Wenn es ausgeführt wird, wird es dann doppelt angezeigt.
Der sendet auch generell ein anderes Finish-Event, aber das habe habe in der dfplayer lib schon angepasst. Das Problem war schon vom MH2024K-16SS her bekannt.
Hier mal ein Konsolenauszug . Es wird im Albummodus abgespielt.
Die 3x Wait for TrackToFinisch kommen nachdem ich 3x über Longpress PlayTaste die Tracknummer als Advertise ansagen ließ.
Das darauffolgende nextTrack wurde manuell über die VorwTaste ausgelöst. OK.
Die folgenden 3 WaitForTrack… wurden wieder durch 3 maliges Ansagen der Tracknummer durch Longpress Play als advert ausgegeben.
Der folgende Nexttrack wurde durch normales weitergehen in der Queue ohne Tastendruck ausgeführt. OK.
Sichtbar durch SD-K OPFin -> nxtTr OK.
14:25:00.259 -> Alb.modus -> nxtTrk
14:25:00.259 -> idx: 2 --> 3 von: 76
14:25:00.307 -> Play Q-idx: 3, Trk: 4
14:25:00.307 ->
14:25:00.307 -> StdBy OFF
14:25:06.968 -> Wait for Track To Finish
14:25:12.829 -> Wait for Track To Finish
14:25:18.562 -> Wait for Track To Finish
14:25:23.049 ->
14:25:23.049 -> Alb.modus -> nxtTrk
14:25:23.049 -> idx: 3 --> 4 von: 76
14:25:23.049 -> Play Q-idx: 4, Trk: 5
14:25:23.049 ->
14:25:23.049 -> StdBy OFF
14:25:36.436 -> Wait for Track To Finish
14:25:41.354 -> Wait for Track To Finish
14:25:45.606 -> Wait for Track To Finish
14:28:31.834 -> SD-K OPFin -> nxtTr
14:28:31.834 ->
14:28:31.834 -> Alb.modus -> nxtTrk
14:28:31.834 -> idx: 4 --> 5 von: 76
14:28:31.834 -> Play Q-idx: 5, Trk: 6
14:28:31.834 ->
14:28:31.834 -> StdBy OFF
Sobald ich ein Advert ausgegeben hatte bekomme ich nur noch das vor dem if angezeigt. Habe das nxtTr zur Unterscheidung mit 1 und 2 ergänzt.
Das Zurücksetzen von AdvPlaying auf false scheint dann also bei dem Chip irgendwie nicht zu klappen.
Kann dann ja eigentlich nur mit dem anderen Finish-Event zusammen hängen, oder?!
Das Rücksetzen wird ja nicht von dem Chip gemacht, sondern jedesmal wenn das TrackFinish Event vom Player kommt, wird das advPlaying auf false gesetzt.
Wenn das erste nxtTrk nach deiner nummerierung kommt, dann tritt auch das Event auf und das Rücksetzen müsste durch den Code erfolgen. Hast du die geschweiften Klammern richtig gesetzt, so dass das Rücksetzen ausserhalb der if abfrage erfolgt? Wenn das in der Abfrage ist, kann das Rücksetzen nicht funktionieren, weil durch das Abspielen des Advert advPlaying ja true ist. dadurch wird die Abfragebedingung nicht erfüllt und das Rücksetzen geht nicht, und der automatische nextTrack auch nicht.
class Mp3Notify {
public:
static void OnError(uint16_t errorCode) {
// see DfMp3_Error for code meaning
Serial.println();
Serial.print("Com Error ");
Serial.println(errorCode);
if(errorCode==7) AdvPlaying = false;
}
static void PrintlnSourceAction(DfMp3_PlaySources source, const char* action) {
if (source & DfMp3_PlaySources_Sd) Serial.print(F("SD"));
if (source & DfMp3_PlaySources_Usb) Serial.print(F("USB"));
if (source & DfMp3_PlaySources_Flash) Serial.print(F("Flash"));
Serial.println(action);
}
static void OnPlayFinished(DfMp3_PlaySources source, uint16_t track) {
// Serial.print("Track beendet");
// Serial.println(track);
delay(100);
PrintlnSourceAction(source, "OPin -> nxtTr1");
if (!AdvPlaying) {
PrintlnSourceAction(source, "OPin -> nxtTr2");
nextTrack(track);
}
AdvPlaying = false;
}
So habe ich das Zurücksetzen im Code verewigt.
Und noch eine Konsolenausgabe.
Habe eine Karte mit Hörbuch-Modus aufgelegt, ein automatisches nextTrack abgewartet, dann eine Sleeptimer-Karte aufgelegt (als advertise wird der Modifier-Aktivierungssound abgespielt) (Phänomen ist aber jedem anderen advertise das gleiche), dann wieder bis zum nächsten automatischen nextTrack gewartet und da kommt dann halt nur die Ausgabe vor der if-Abfrage.