ich hab nochmal ne Frage zum Thema xTasks (FreeRTOS):
Folgender Sketch:
#include <WiFi.h>
#include <WiFiAP.h>
const char ssid[14] = "mySSID";
const char password[21] = "myPW";
unsigned long previousMillis=0;
unsigned long interval=1000;
unsigned long connTimer = 0;
void setup() {
delay(2000);
Serial.begin(115200);
xTaskCreatePinnedToCore(
keepWiFiAlive,
"Keep Wifi Alive",
5000,
NULL,
2,
NULL,
1
);
}
void loop() {
// Alle X Sekunden ein Lebenszeichen (nur zum Testen, ob der loop unterbrechungsfrei läuft)
if (millis() - previousMillis > interval) {
Serial.print("Millis:");
Serial.println(millis());
previousMillis = millis();
}
}
void keepWiFiAlive(void * parameters) {
for (;;) {
if (WiFi.status() == WL_CONNECTED) {
Serial.println("Verbunden!");
vTaskDelay(10000 / portTICK_PERIOD_MS);
continue;
}
WiFi.disconnect();
WiFi.mode(WIFI_AP_STA);
WiFi.begin(ssid, password);
unsigned long startAttemptTime=millis();
while (WiFi.status() != WL_CONNECTED && millis() - startAttemptTime < 5000) {
}
if (WiFi.status() != WL_CONNECTED) {
Serial.println("Nicht verbunden!");
continue;
} else {
// Again connected
continue;
}
}
}
Wenn ich den Task auf Core 1 laufen lasse, unterbricht der xTask den main loop immer für 5
Sekunden, was anzunehmen war, da beide ja auf dem selben Kern laufen):
Millis:2161
Nicht verbunden!
Millis:7172
Nicht verbunden!
Millis:12182
Nicht verbunden!
Millis:17193
D.h. so bringt mir der separate Task nichts, da er den loop unterbricht
Wenn ich den Task auf Core 0 laufen lasse (und genau dann sollte ich ja den Vorteil des zweiten Prozessor-Kerns nutzen können) ....
Millis:2163
Millis:3164
Millis:4165
Millis:5166
Millis:6167
E (9242) task_wdt: Task watchdog got triggered. The following tasks did not reset the watchdog in time:
E (9242) task_wdt: - IDLE (CPU 0)
E (9242) task_wdt: Tasks currently running:
E (9242) task_wdt: CPU 0: loopTask
E (9242) task_wdt: CPU 1: Keep Wifi Alive
E (9242) task_wdt: Aborting.
abort() was called at PC 0x400dbb41 on core 0
Backtrace:0x40083625:0x3ffbe9bc |<-CORRUPTED
... stürzt der ESP ab.
Ich hatte das Thema glaub ich schon mal in einem Post aufgegriffen, bin mir aber nicht mehr sicher, wie die Sachlage war. Daher trau ich mich nochmal fragen:
Kann man mit der Arduino IDE überhaupt den zweiten Kern nutzen?
Ich meine mich erinnern zu können, dass das ein hoffnungsloses Unterfangen ist
dann muß der Kern (Task) entweder regelmäßig den Wachhund füttern oder den Kern auch mal an andere Tasks abgeben.
Ich erinnere mich an ein Projekt, bei dem das Warten mit millis() den Wachhund anschlagen ließ, während delay() den Kern freigegeben hat während es auf das Ende des Intervalls gewartet hat.
Spatestens wenn mehr Tasks als Kerne vorhanden sind, sollte jede(r) Task regelmäßig auf Ereignisse (event) warten, um den anderen Tasks auch eine Chance auf Rechenzeit zu lassen.
Nachtrag: Zum Ausnutzen mehrerer Prozessorkerne reicht es, mehrere Tasks zu schreiben. Dann kann das System Tasks auf die Kerne verteilen, eine Bindung von Tasks an einen bestimmten Kern ist dafür nicht notwendig.
Hier muss man zwischen esp32 und esp8266 unterscheiden.
Der esp32 arbeitet preemptiv, da ist ein yield() nicht unbedingt nötig.
(das war eben auch mein Denkfehler)
Und ja, yield()/delay() leitet in beiden Fällen einen Taskwechsel ein.
Wenn ich verbunden bin, sieht die Ausgabe bei mir auch so aus.
Aber mein Problem ist: Wenn sich der ESP NICHT verbinden kann (weil z.B. jemand das WLAN ausgeschaltet hat) --> Dann läuft der loop nicht mehr durch, weil der ständige neue Verbindungsversuch hier blockiert.
Und genau den Fall hab ich getestet: Bewusst falsche Zugangsdaten im Sketch hinterlegt.
Dann funktionierts eben leider nicht mehr.
Hast du da ein Beispiel? Evtl. direkt meinen Sketch als Grundlage verwenden und da was dazu"bauen", was den Wachhund füttert? Einfach nur das hier hat nicht gereicht
Das verstehe ich leider noch nicht ganz.
Wäre echt super, wenn du mein kleines Beispiel mal entsprechend tunen könntest, wie du meinst, dass es funktionieren müsste. Ich kriegs nicht hin.
Kommt drauf an, wie schnell der Wachhund gefüttert werden möchte. Das ist ggf. einstellbar, sollte irgendwo in der Doku drinstehen. Ein yield() ist eigentlich nur eine Notlösung im koopertiven Multitasking und sagt dem System, daß gerade nichts zu tun ist. Bei länger laufenden Code kann der watchdog auch direkt befriedigt werden um anzuzeigen, daß noch etwas zu tun ist, ohne das Programm zu unterbrechen.
Das kann ich leider nicht, ESP Programmierung kenne ich nur aus den Beiträgen anderer.
Vermutlich reden wir nur aneinander vorbei. Was genau stellst Du Dir unter "zweiten Kern nutzen" vor? Du könntest ja eine Task an den zweiten Kern binden, egal ob das Sinn macht oder nicht. Andernfalls lastet das System alle verfügbaren Kerne aus, ohne daß man sich darum kümmern muß.