GD3200B - Anzahl angezeigter Ordner erst nach 2.tem Auflegen der Karte richtig

Ein zweifaches auflegen der Karte ist ja nichts anderes als das die Anzahl der Tracks vom vorherigen Ordner übernommen wird, nur ist dieser immer noch der Gleiche. Wird ein neuer Ordner aufgerufen, ist hier wiederum die Anzahl der Dateien die des davor abgespielten, also nicht korrekt. Das Problem ist, wenn von einem Ordner mir großer Anzahl von Dateien in einen mit wenig Dateien gesprungen wird, dann kann das System sich aufhängen bei willkürlicher Auswahl der Startdatei.
Ist bei mir so bei einem Wechsel aus einem Ordner mit 165 Dateien in ein Verzeichnis mit nur 5 Dateien.

Die Verzeichnisnummer wird immer korrekt ausgelesen und auch im Album Modus abgespielt.

Das mit dem doppelten Auslesen der Anzahl von Dateien im Ordner hatte ich auch schon erfolglos versucht. Für weitere Versuche fehlen mir leider sie Programmierkenntnisse.

Trotz allem ein sehr schönes Projekt.

Das ist wohl so, ja.

@pitpossum79 hat noch ausprobiert, was passiert, wenn man am Ende von PlayFolder, wenn aus dem betroffenen Ordner abgespielt wird, noch einmal versucht mp3.getFolderTrackCount(myFolder->folder) auszuführen. Leider kam als Ergebnis nur ein Com Error 129.

Ich habe gestern auch noch ein wenig mit dem GB3200B probiert.

Bei mir war es so, dass getFolderTrackCount sich immer auf den Ordner bezog, wo aktuell ein Titel läuft. Dieser Wert hat sich nicht geändert/aktualisiert, wenn danach ein Titel aus einem anderen Ordner abgespielt wurde und man währenddessen nicht getFolderTrackCount aufruft.

Ein Fix könnte also sein, den getFolderTrackCount erst / nochmal gerade dann durchzuführen, wenn ein Titel aus dem gewünschten Ordner läuft - ggf. braucht es einen kurzen delay (500ms-2s?) nach dem Start des Titels, bis die Abfrage einen korrekten Wert zurückliefert.

1 „Gefällt mir“

Hallo,

habe heute den DFplayer mini mit MH-ET LIVE (MH2024K-24SS) Chip probiert.
(editiert: zuvor MH-ET LIVE (MH2024K-16SS)

KEINE WERBUNG!!!

KEINE WERBUNG!!!
Alles wie es soll, keinen Fehler wie beim GD3200B bzgl. Anzahl Dateien im Ordner.

Eine Anpassung im Code für den GD3200B wäre jedoch für viele andere sehr hilfreich.
Leider traue ich mir das mit meinen jetzigen Programmierkenntnissen nicht zu.
Bin jedoch gerne bereit Vorschläge unter „Anleitung“ zu probieren.

Grüße an alle die das hier möglich machen und am Leben halten!

Ich teile hier dann mal eine mögliche Lösung. @Bastelmatz und ich hatte anscheinend den selben Ansatz.
Damit der Player sicher die Dateien im richtigen Ordner zählt, muss er vorher etwas daraus abspielen. Hierfür eignet sich eine Datei mit Stille. Diese kann man zum Beispiel hier herunterladen. Die Datei muss länger sein als das im Code eingefügte delay, jedoch will man ja auch nicht unnötig Speicher belegen. Getestet wurde mit der 2 Sekunden-Datei. Diese wird dann in jedem Ordner als 000.mp3 eingefügt.

Im Code wird dann bei Start der Wiedergabe zunächst die Stille abgespielt und dann die Anzahl der Ordner ermittelt. Wie lange der Player dazwischen braucht muss man ein wenig probieren. Je länger das Delay, desto länger dauert es bis die Wiedergabe beginnt. Ist es allerdings zu kurz, wird die Trackanzahl wieder falsch ermittelt. Am besten probiert man aus, was im eigenen Aufbau gut funktioniert.
Im Code muss dann entsprechend zu Beginn von playFolder() die Wiedergabe der Stille ergänzt werden und diese natürlich bei der Anzahl der ermittelten Tracks wieder abgezogen werden:

void playFolder() {
    Serial.println(F("== playFolder()")) ;
    disablestandbyTimer();
    knownCard = true;
    _lastTrackFinished = 0;
    mp3.playFolderTrack(myFolder->folder, 0);
    Serial.println(F("kurze Pause"));
    delay(1500);  //diese Delay so kurz wie möglich wählen
    numTracksInFolder = mp3.getFolderTrackCount(myFolder->folder) - 1;
    firstTrack = 1;
    Serial.print(numTracksInFolder);
    Serial.print(F(" Dateien & 1 Stille in Ordner "));
    Serial.println(myFolder->folder);
    ...

Vielen Dank an @Volker-W und @pitpossum79 fürs Testen.

3 „Gefällt mir“

Ich antworte mal hier, damit es im Kontext einigermaßen erhalten bleibt.

→ Die Zusammenfassung bez. GB3200B folgt unten.

.

Das ganze DFPlayer Handling ist bei mir eigentlich in den Tonuino_DFPlayer Dateien (.h und .cpp) zusammengefasst.

Da meine Software sich strukturell deutlich von der Standardversion unterscheidet, kann ich leider nicht sagen, ob und wie der nachfolgende Code dafür relevant ist.

Trotzdem folgen hier ein paar vermeintlich relevante Auszüge.

.

Zunächst ein paar Definitionen zum nachfolgenden Verständnis

	static const uint8_t largeFolders = 15; // 1-15
	static const uint8_t smallFolders = 84; // 16-99
	static const uint8_t FOLDERCODE_MP3 = 0;
	static const uint8_t FOLDERCODE_ADVERTISEMENT = 100;
	static const uint8_t TRACKNUMBER_SILENCE = 0;

	static uint16_t tracksFolderLarge[largeFolders];
	static uint8_t tracksFolderSmall[smallFolders];

.

Hier ein Auszug aus der

Tonuino_DFPlayer.cpp:

void TonuinoDFPlayer::setup(uint8_t pinBusy, bool hasChip_GB3200B, bool hasChip_MH2024_16SS)
{
	pin_Busy = pinBusy;
	hasGB3200B = hasChip_GB3200B;
	
	pinMode(pinBusy, INPUT);
	
	// DFPlayer Mini initialisieren
	mp3.begin();
	mp3.ignoreCheckSum = hasChip_MH2024_16SS;
	// Zwei Sekunden warten bis der DFPlayer Mini initialisiert ist
	delay(2000);
	
	tonuinoPlayer.pauseAndStandBy();
}
void TonuinoDFPlayer::start()
{
	if (!isPlaying())
	{
		Serial.println(F("Start player"));
		mp3.start();
		delay(800);
	}
}
uint16_t TonuinoDFPlayer::getFolderTrackCount(uint16_t folder)
{
	if (hasGB3200B)
	{
		// return count from last request
		if (folder > largeFolders)
		{
			uint8_t index = folder - largeFolders - 1;
			if (tracksFolderSmall[index] > 0)
			{
				return tracksFolderSmall[index];
			}
		}
		else
		{
			uint8_t index = folder - 1;
			if (tracksFolderLarge[index] > 0)
			{
				return tracksFolderLarge[index];
			}
		}
		playTrack(folder, TRACKNUMBER_SILENCE);
		delay(100);
		pause();
	}
	uint16_t trackCount = mp3.getFolderTrackCount(folder);
	// save track count for this folder
	if (folder > largeFolders)
	{
		uint8_t index = folder - largeFolders - 1;
		tracksFolderSmall[index] = trackCount;
	}
	else
	{
		uint8_t index = folder - 1;
		tracksFolderLarge[index] = trackCount;
	}
	return trackCount;
}
void TonuinoDFPlayer::playTrack(uint8_t folder, uint16_t track)
{
	Serial.print(F("Play track "));
	Serial.print(track);
	Serial.print(F(" from folder "));
	Serial.println(folder);
	lastStartedFolder = folder;
	lastStartedTrack = track;
	if (folder == FOLDERCODE_ADVERTISEMENT)
	{
		mp3.playAdvertisement(track);
	}
	else
	{
		activeFolder = folder;
		activeTrack = track;
		if (folder == 0 || folder == FOLDERCODE_MP3)
		{
			tonuinoPlayer.pauseAndStandBy();
			mp3.playMp3FolderTrack(track);
		}
		else
		{
			if (track > 255)
			{
				if (folder > 0 && folder <= largeFolders)
				{
					mp3.playFolderTrack16(folder, track);
				}
				else
				{
					Serial.print(F("No large file support for that folder"));
				}
			}
			else
			{
				mp3.playFolderTrack(folder, track);
			}
			delay(PLAYTRACK_DELAY);
		}
	}
}
void TonuinoDFPlayer::trackFinished()
{
	if (hasGB3200B && (lastStartedFolder == FOLDERCODE_ADVERTISEMENT))
	{
		Serial.print(F("Last started track "));
		Serial.print(lastStartedTrack);
		Serial.print(F(" in folder "));
		Serial.println(lastStartedFolder);
		lastStartedFolder = activeFolder;
		lastStartedTrack = activeTrack;
		return;
	}
	
	Serial.print(F("Active track "));
	Serial.print(activeTrack);
	Serial.print(F(" in folder "));
	Serial.print(activeFolder);
	Serial.print(F(", Current track "));
	Serial.println(tonuinoPlayer.currentTrack());
	
	// Somehow the DFPlayer finished event is raised twice
	// Ignore the second finish event 
	// (every new track would have the play track delay)
	if (millis() - timeLastFinished < PLAYTRACK_DELAY)
	{
		Serial.println(F("Finish event ignored!"));
		return;
	}
	bool isCurrentTrack = activeTrack == tonuinoPlayer.currentTrack();
	activeTrack = 0;
	if (isCurrentTrack)
	{
		tonuinoPlayer.trackFinished();
		if (tonuinoPlayer.isPlaying && musicDSLoaded)
		{
			nextTrack();
		}
	}
	timeLastFinished = millis();
}

.

Auszug aus der modifizierten

Tonuino_DFMiniMp3.h:

    void sendPacket(uint8_t command, uint16_t arg = 0, uint16_t sendSpaceNeeded = c_msSendSpace)
    {
		Serial.print("Send DFPlayer command: ");
		Serial.print(command);
		Serial.print(" with argument ");
		Serial.println(arg);
		
            uint8_t out[DfMp3_Packet_SIZE] = { 0x7E,
            0xFF,
            06,
            command,
            00,
            static_cast<uint8_t>(arg >> 8),
            static_cast<uint8_t>(arg & 0x00ff),
            00,
            00,
            0xEF };

		if (ignoreCheckSum)
		{
			out[DfMp3_Packet_HiByteCheckSum] = 0xEF;
			out[DfMp3_Packet_LowByteCheckSum] = 00;
			out[DfMp3_Packet_EndCode] = 00;
		}
		else
		{
			setChecksum(out);
		}
		
        // wait for spacing since last send
        while (((millis() - _lastSend) < _lastSendSpace))
        {
            // check for event messages from the device while
            // we wait
            loop();
            delay(1);
        }

        _lastSendSpace = sendSpaceNeeded;
        _serial.write(out, DfMp3_Packet_SIZE);

        _lastSend = millis();
    }
    uint16_t listenForReply(uint8_t command)
    {
        uint8_t replyCommand = 0;
        uint16_t replyArg = 0;

        do
        {
            if (readPacket(&replyCommand, &replyArg))
            {
                if (command != 0 && command == replyCommand)
                {
                    return replyArg;
                }
                else
                {
                    switch (replyCommand)
                    {
                    case 0x3c: // usb
                        T_NOTIFICATION_METHOD::OnPlayFinished(DfMp3_PlaySources_Usb, replyArg);
                        break;

                    case 0x3d: // micro sd
					case 0x4c:
                        T_NOTIFICATION_METHOD::OnPlayFinished(DfMp3_PlaySources_Sd, replyArg);
                        break;

                    case 0x3e: // flash
                        T_NOTIFICATION_METHOD::OnPlayFinished(DfMp3_PlaySources_Flash, replyArg);
                        break;

                    case 0x3F:
                        _isOnline = true;
                        T_NOTIFICATION_METHOD::OnPlaySourceOnline(static_cast<DfMp3_PlaySources>(replyArg));
                        break;

                    case 0x3A:
                        _isOnline = true;
                        T_NOTIFICATION_METHOD::OnPlaySourceInserted(static_cast<DfMp3_PlaySources>(replyArg));
                        break;

                    case 0x3B:
                        _isOnline = true;
                        T_NOTIFICATION_METHOD::OnPlaySourceRemoved(static_cast<DfMp3_PlaySources>(replyArg));
                        break;

                    case 0x40:
                        T_NOTIFICATION_METHOD::OnError(replyArg);
                        return 0;
                        break;

                    default:
                        // unknown/unsupported command reply
                        break;
                    }
                }
            }
            else
            {
                if (replyArg != 0)
                {
                    T_NOTIFICATION_METHOD::OnError(replyArg);
                    if (_serial.available() == 0)
                    {
                        return 0;
                    }
                }
            }
        } while (command != 0);

        return 0;
    }

.

Auszug aus der

Tonuino_MainController.cpp:

// DFPlayer Mini initialisieren
	dfPlayer.setup(pinConfig.DFPlayer_Busy, hwConfig.Chip_GB3200B, hwConfig.Chip_MH2024_16SS);
	
	// set settings
	dfPlayer.volumeMin = swConfig.VolumeMin;
	dfPlayer.volumeMax = swConfig.VolumeMax;
	dfPlayer.volumeIncrement = swConfig.VolumeIncrement;
	dfPlayer.setVolume(swConfig.VolumeInit);
	dfPlayer.setEqualizer(swConfig.Equalizer);

	[...]

	dfPlayer.start();
	// give DFPlayer some more time to init (otherwise finish event of MP3 track is not generated)
	delay(1000);
	// play startup sound
	dfPlayer.playMP3AndWait(261);

.
.
.

Anmerkungen

In meiner getFolderTrackCount() Methode habe ich noch folgende Anpassungen drin:

  • Speichern der Titelanzahl in einem Array

    • Da sich die Titelanzahl in dem Ordner während des Betriebs nicht ändert
    • Bei der nächsten Abfrage für diesen Ordner, wird dieser Wert zurückgegeben
    • Es wird nicht erneut „Stille“ abgespielt und auch kein mp3.getFolderTrackCount(folder) Aufruf
  • Da ich in meiner Software LargeFolder * unterstütze, ist das o.g. Array-Handling auf „Large“ und „Small“ folder aufgeteilt (um 84 Byte Speicherplatz zu sparen)

    • .* „Large“ Ordner sind die Ordner (0 bzw.) 1-15, wo mehr als 255 Titel enthalten sein können.
      • Um genau zu sein, können bis zu 3000 Titel in diesen Ordnern enthalten sein

.
.
.

Anpassungen für Chip GB3200B:

Wenn ich das richtig überblicke, sind folgende Anpassungen relevant:

  • Einen Titel aus genau dem Ordner abspielen, wo man die Titelanzahl mit getFolderTrackCount(folderNumber) ermitteln will.
    • Vorzugsweise einen Titel ohne echte Geräusche also „Stille“, bspw:
	playTrack(folder, TRACKNUMBER_SILENCE);
	delay(100);
	pause();
	uint16_t trackCount = mp3.getFolderTrackCount(folder);
  • Das Finish-Event für Advertisement Titel abfangen, bspw. in meinem Kontext (s.o.):
	if (hasGB3200B && (lastStartedFolder == FOLDERCODE_ADVERTISEMENT))
	{
		lastStartedFolder = activeFolder;
		lastStartedTrack = activeTrack;
		return;
	}

.
.
.

Anpassungen für Chip MH2024_16SS:

Wenn ich das richtig überblicke, sind folgende Anpassungen relevant:

  • Ausreichend Verzögerung nach dem mp3.begin() und mp3.start()
    • Afaik 1-x Sekunden, bspw.
	delay(1000);
  • Im DFMiniMP3 die Notification-Case 0x4C hinzufügen, um das FinishEvent zu erzeugen
	case 0x3d: // micro sd
	case 0x4c:
		T_NOTIFICATION_METHOD::OnPlayFinished(DfMp3_PlaySources_Sd, replyArg);
		break;

Sowie die Checksummen Prüfung ignorieren:

	uint8_t out[DfMp3_Packet_SIZE] = { 0x7E,
	0xFF,
	06,
	command,
	00,
	static_cast<uint8_t>(arg >> 8),
	static_cast<uint8_t>(arg & 0x00ff),
	00,
	00,
	0xEF };

	if (ignoreCheckSum)
	{
		out[DfMp3_Packet_HiByteCheckSum] = 0xEF;
		out[DfMp3_Packet_LowByteCheckSum] = 00;
		out[DfMp3_Packet_EndCode] = 00;
	}
	else
	{
		setChecksum(out);
	}
1 „Gefällt mir“