Dev-Branch

Das einzige Problem mit der Hypothese ist, dass der Arduino loop im dem loopTask mit der Priorität 1 läuft (was die niedrigste ist, das nicht der IDLE loop ist). Damit wird der Task von allen anderen Tasks, die wir am Laufen und Priorität > 1 haben unterbrochen.

Der ESP32 hat ein preemptives Multitasking, d.h. sobald ein Task mit einer höheren Priorität bereit wird, kommt der bei dem nächsten Scheduling Slot (was bei Arduino alle 1 ms ist) dran. Mit vTaskDelay wird „nur“ der Scheduler früher und öfter aufgerufen mit „hey du kannst mich unterbrechen“.

Der AudioPlayer sollte auch die höchste Prio von allen unseren Tasks haben, d.h. immer zuerst dran kommen, sobald er etwas zu tun hat. @tueddy was ist der Hintergrund, dass der AudioPlayer_Task mit 556d1f4 auf Priorität 2 reduziert wurde? Damit ist er gleich mit dem RFID Task gleich auf.

Könnt ihr kurz prüfen, ob durch diese Änderung die Störungen weg sind:

--- a/src/AudioPlayer.cpp
+++ b/src/AudioPlayer.cpp
@@ -135,7 +135,7 @@ void AudioPlayer_Init(void) {
                        "mp3play", /* Name of the task */
                        6000, /* Stack size in words */
                        NULL, /* Task input parameter */
-                       2 | portPRIVILEGE_BIT, /* Priority of the task */
+                       3 | portPRIVILEGE_BIT, /* Priority of the task */
                        &AudioTaskHandle, /* Task handle. */
                        1 /* Core where the task should run */
                );

edit: Leider kann ich die Aussetzer bei mir nicht nachstellen, ich habe mit der DEV keine Störungen, Rotary aktiv oder nicht macht bei mir keinen Unterschied.

Der RFID-Task läuft auf dem anderen Core und ist deshalb keine echte Konkurenz für den Audio-Task.
So wie ich es verstanden hatte kann der Sheduler einen Task nicht beliebig unterbrechen sondern ist auf delays oder waits o.ä. angewiesen, kann aber auch sein, dass ich das falsch verstanden habe.

Der Grund für diesen Commit war das wir die Erhöhung auf Priorität 3 zuvor damit wieder rückgängig gemacht haben. Weil das enorme Probleme wie z.B. nicht reagierende Weboberfläche/Taster mit sich gebracht hat, die Erhöhung war keine gute Idee.

Jetzt haben wir keine Audiostörungen mehr. Wenn doch dann bitte berichten…

Hm, ja, stimmt für den PN5180, wie ich gerade sehe. Der MFRC522 läuft auf Core 1, wie der AduioPlayer Task. Sollten wir gleich ziehen :smile:

FreeRTOS ist ein fully preemtive system, also nein, ein delay / yield aus einem nieder-prioren Task ist nicht zwingen notwendig um ein Context Switch zu forcieren (das ist bei Cooperative Multitasking notwendig).
ABER, das gilt nur für den Task mit der niedrigsten Priorität. Alle anderen (vor allem die mit der höchsten Prio) müssen sich selbst in den Blocking State bringen (was vTaskDelay, bzw warten auf eine Queue/Semaphore tut). Wenn der Task das nicht tut, kommt kein anderer Task mit einer niedrigeren Priorität dran (weil der Scheduler schaut, dass immer der Task mit der höhsten Priorität im „ready“ oder „running“ State CPU Zeit bekommt).

Ich kann die FreeRTOS Seite zu Tasks wärmstens empfehlen :slight_smile:

Okay, das ganze Thema mit den Problemen war an mir vorbei gegangen :slight_smile:

2 „Gefällt mir“

Sehr guter Hinweis mit dem MFRC522. Das sollten wir tatsächlich gerade ziehen.
In diesem Fall wird das ganze nochmal deutlich spannender!
Aktuell gibt es die Folgenden Tasks auf Core 1 (und irgendeiner oder das Zusammenspiel dieser muss ja was damit zu tun haben)…
Jeweils in Klammer die Prio:

ipc1           	(24)
arduino_events 	(19)
async_tcp      	(3)
mp3play        	(2)
Led_Task       	(1)
loopTask       	(1)
IDLE           	(0)

Könnte es vvielleicht auch an den Peripherie-Zugriffen liegen? Gerade in der loopTask werden viele Register / Timer ausgelesen. Könnte das ein Unterbrechen des Shedulers eventuell verzögern / verhindern wenn hier im hintergrund Semaphoren eingebaut sind o.ä.?

1 „Gefällt mir“

Also ich bin aus der Nummer mit dem Ändern von Taskverteilungen komplett raus, das gab schon soo viele Probleme!
Stattdessen könnte man ja mal einen Profiler anwerfen um festzustellen was da noch Zeit stiehlt…

1 „Gefällt mir“

Gerade durch Zufall gefunden: teleplot - Visual Studio Marketplace

Wird von PIO als Serial/UDP Plotter vorgeschlagen…

Es gab ja den Commit

der ein paar Fehler eingeführt hat, die dann fast alle in

gelöst wurden.

Hatte selbst einen Fix geschrieben und wollte den hier melden, dann sehe ich schon, dass ihr mal wieder schneller wart.

Leider sind nicht alle Fehler gelöst, so passiert z.B. noch Folgendes:

  • Mit nicht aufliegender RFID Karte starten (und ohne PLAY_LAST_RFID_AFTER_REBOOT), kurz warten, dann eine Musik-Rfid auflegen, und die LED zeigt eine Fehlermeldung an.

Grund ist die Bedingung in AudioPlayer.cpp line 844
if ((millis() - playbackTimeoutStart) > playbackTimeout) {
diese ist erfüllt, weswegen Folgendes ausgeführt wird:

				// Audio playback timed out, move on to the next
				System_IndicateError();
				gPlayProperties.trackFinished = true;
				playbackTimeoutStart = millis();
			}

Der Error wird angezeigt, aber interessanterweise hat gPlayProperties.trackFinished = true; keine Auswirkungen, d.h. es wird trotzdem der 1. Track abgespielt.

Der selbe Fehler taucht z.B. auch auf, wenn die Playlist vorbei ist, und man erneut eine Musik-Rfid auflegt.

Man müsste wohl beim Auflegen einer neuen Karte, zumindest im mode NO_PLAYLIST den playbackTimeoutStart wieder auf millis() setzen. Wo, wann und mit welchen Bedingungen das (oder etwas ganz anderes) gemacht wird, das sollten besser die Profis entscheiden.

Mein Fix sah auch ganz anders aus als der von laszloh, bin halt auch nur Laie :wink:

Könnt ihr diese Fehler nachstellen?

5 „Gefällt mir“

Verstehe ich das richtig. Ich habe glaube auch das Verhalten…

Wenn ich eine Karte auflege, dann geht kurz die LED auf Rot (Fehler) spielt dann aber doch die gewünschten Dateien ab. Das ist doch auch nicht ganz korrekt, oder ?

Oder ist das ein anderes Problem?

Ja, genau das ist es, es wird in diesen Fällen ein Error über die LED angezeigt, obwohl es ja keiner ist.

1 „Gefällt mir“

Ich bekomme auch die Fehleranzeige. Entweder nach Start & Auflegen einer Karte oder wenn keine Playlist aktiv ist und dann eine Karte aufgelegt wird. Abgespielt wird normal aber die rote NeoPixel-Anzeige ist so nicht richtig

Sorry, grad erst gesehen. Ich werf ein Blick hinein, woher das kommt.

@sfields Fehler ist genau das, was du sagst. Habe auch deine Idee genommen (zurücksetzten der millis wenn playMode nicht aktiv ist) und in Code gegossen.

--- a/src/AudioPlayer.cpp
+++ b/src/AudioPlayer.cpp
@@ -840,14 +840,21 @@ void AudioPlayer_Task(void *parameter) {
                }

                // If error occured: move to the next track in the playlist
-               if (gPlayProperties.playMode != NO_PLAYLIST && gPlayProperties.playMode != BUSY && !audio->isRunning() && !gPlayProperties.pausePlay) {
-                       if ((millis() - playbackTimeoutStart) > playbackTimeout) {
-                               // Audio playback timed out, move on to the next
-                               System_IndicateError();
-                               gPlayProperties.trackFinished = true;
-                               playbackTimeoutStart = millis();
+               if (gPlayProperties.playMode != NO_PLAYLIST && gPlayProperties.playMode != BUSY) {
+                       // we check for timeout
+                       if (!audio->isRunning() && !gPlayProperties.pausePlay) {
+                               if ((millis() - playbackTimeoutStart) > playbackTimeout) {
+                                       // Audio playback timed out, move on to the next
+                                       System_IndicateError();
+                                       gPlayProperties.trackFinished = true;
+                                       playbackTimeoutStart = millis();
+                               }
                        }
+               } else {
+                       // we are idle, update timeout so that we do not get a spurious error when launching into a playlist
+                       playbackTimeoutStart = millis();
                }
+
                if ((System_GetOperationMode() == OPMODE_BLUETOOTH_SOURCE) && audio->isRunning()) {
                        // do not delay here, audio task is time critical in BT-Source mode
                } else {

Die verschachtelte if finde ich nicht ganz elegant, komme aber auch keine elegantere Lösung gerade. Wenn jemand eine bessere Idee hat, nur her damit :slight_smile:

3 „Gefällt mir“

Das scheint soweit zu klappen, sowohl normales abspielen als auch mit der M3U Playlist mit ungültigen Eintrag (Dann rotes Neoixel-Feedback + Sprung auf nächsten Track nach Timeout) :+1:

Danke für die Rückmeldung und das Umsetzen. Im Moment ist ja an einigen Ecken was los im Code.

1 „Gefällt mir“

Wie gewünscht, hier ein Vorschlag zur besseren Lesbarkeit und eine Verschachtelung weniger:

Konnte es leider nicht testen. Es sollte sich beim Umbau aber kein Fehler eingeschlichen haben.

// If error occured: move to the next track in the playlist
boolean activeMode = (gPlayProperties.playMode != NO_PLAYLIST && gPlayProperties.playMode != BUSY);
boolean noAudio = (!audio->isRunning() && !gPlayProperties.pausePlay);
boolean timeout = ((millis() - playbackTimeoutStart) > playbackTimeout); 
if activeMode { 
	// we check for timeout
	if (noAudio && timeout) {
		// Audio playback timed out, move on to the next
		System_IndicateError();
		gPlayProperties.trackFinished = true;
		playbackTimeoutStart = millis();
	}
} else {
	// we are idle, update timeout so that we do not get a spurious error when launching into a playlist
	playbackTimeoutStart = millis();
}

@Niko Das ist sicher lesbarer - Müsste aber zunächst auch mal getestet sein, mindestens von Dir :wink:

Gibt es denn jetzt noch Probleme/Fehler mit dem aktuellen DEV?
Weil Plan ist es die vielen Bugfixes, vor allem die bessere Abspielbarkeit von MP3’s, noch vor Weihnachten in den Master zu übernehmen.

4 „Gefällt mir“

Der Code schaut gut aus, aber es gab einige Punkte. C++ (und alle mondernen gcc’s, also auch avr-gcc) hat ein Data Type bool, es gibt keinen guten Grund boolean von Arduino zu verwenden (Arduino selbst empfiehlt bool :wink: ). Rad neuerfinden und type safety und so :slight_smile: .

Hab die Variablen auch noch const gemacht, um den Compiler mit der Nase drauf zu stoßen, dass die Variablen wegzuoptimiert werden können.

// If error occured: move to the next track in the playlist
const bool activeMode = (gPlayProperties.playMode != NO_PLAYLIST && gPlayProperties.playMode != BUSY);
const bool noAudio = (!audio->isRunning() && !gPlayProperties.pausePlay);
const bool timeout = ((millis() - playbackTimeoutStart) > playbackTimeout); 
if (activeMode) { 
	// we check for timeout
	if (noAudio && timeout) {
		// Audio playback timed out, move on to the next
		System_IndicateError();
		gPlayProperties.trackFinished = true;
		playbackTimeoutStart = millis();
	}
} else {
	// we are idle, update timeout so that we do not get a spurious error when launching into a playlist
	playbackTimeoutStart = millis();
}

Funktioniert bei mir ohne Auffälligkeiten. Läuft mit der m3u und den Playlists über RFID & Web-UI.

4 „Gefällt mir“

Ich habe schlecht geschlafen und bisschen krank bin ich auch noch…

aber wie kann da const funktionieren?
Die Werte können doch nicht zur Compilezeit bekannt sein ?!

Hi,
const ist nicht constexpr (das sind Variablen dessen Inhalt zu Compile-Zeit bekannt ist). Const sagt dem Compiler, dass die Variable zur Laufzeit nur 1x gesetzt wird und ihr Inhalt sich danach nie ändern wird (basically es ist eine read-only Variable).

Der Compiler wird sich auch Beschweren (mit error, also Beschweren mit großem B :smiley: ), wenn du versucht den Inhalt einer const Variable zu modifizieren.

1 „Gefällt mir“

aha danke für die Erleuchtung…