PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : std::thread für ESP32 unter Arduino IDE zum Laufen zu kriegen...?



HaWe
23.05.2019, 16:42
hallo,
ist jemand erfahren in std::thread und besitzt auch einen Arduino-kompatiblen ESP32?

Ich bin dabei zu vesuchen, eine std::thread Implementierung zu bekommen, bin aber selber zu wenig erfahren damit (habe selber nur geringe Kenntnisse in C99 Posix pthread).

Ich habe hier ein Topic eröffnet und auch schon einen Vorschlag, der allerdings zwar compilier- aber nicht lauffähig ist:
https://github.com/espressif/arduino-esp32/issues/2814

Welche Kenner und Könner können hier weiterhelfen und den Beispielcode zum Laufen kriegen?


#include <Arduino.h>
#include <thread>
#include <chrono>

#ifndef LED_BUILTIN
#define LED_BUILTIN 13
#endif

const auto one_sec = std::chrono::seconds
{
1
};

void counter_loop() {
uint32_t counter = 0;
while(true) {
Serial.print("counter_loop: ");
Serial.println(counter);
std::this_thread::sleep_for(one_sec);
}
}

void blinker_loop() {
uint32_t counter = 0;
while(true) {
digitalWrite(LED_BUILTIN, HIGH);
std::this_thread::sleep_for(one_sec);
digitalWrite(LED_BUILTIN, LOW);
std::this_thread::sleep_for(one_sec);
}
}


void setup() {
Serial.begin(115200);
pinMode(LED_BUILTIN, OUTPUT);
std::thread counter_loop_thread(counter_loop);
std::thread blinker_loop_thread(blinker_loop);
}

uint32_t main_loop_counter = 0;
void loop() {
main_loop_counter++;
Serial.print("main loop: ");
Serial.println(main_loop_counter);
delay(10000);
}

Fehlerausgabe seriell:

Rebooting...
ets Jun 8 2016 00:22:57

rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd _drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:928
ho 0 tail 12 room 4
load:0x40078000,len:8424
ho 0 tail 12 room 4
load:0x40080400,len:5868
entry 0x4008069c
counter_loop: 0
abort() was called at PC 0x400e5ca7 on core 1

Backtrace: 0x40089150:0x3ffb1ed0 0x4008937d:0x3ffb1ef0 0x400e5ca7:0x3ffb1f10 0x400e5cee:0x3ffb1f30 0x400d0da2:0x3ffb1f50 0x400d0f92:0x3ffb1f70 0x400d1bc3:0x3ffb1fb0 0x40087c9d:0x3ffb1fd0

Rebooting...
ets Jun 8 2016 00:22:57

rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd _drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:928
ho 0 tail 12 room 4
load:0x40078000,len:8424
ho 0 tail 12 room 4
load:0x40080400,len:5868
entry 0x4008069c
counter_loop: 0
abort() was called at PC 0x400e5ca7 on core 1

(dauerhaft wiederholend)

shedepe
24.05.2019, 08:53
Hi,

std::thread counter_loop_thread(counter_loop);
std::thread blinker_loop_thread(blinker_loop);

Definier die Threads global, bzw. als Pointer. Sonst werden die instantan wieder zerstört beim Verlassen von setup() (Scope von Variablen).
Und dann entscheide dich mal ob du in dem Thread oder in der Mainloop eine Serielle Ausgabe machst. Sonst versuchst du unter Umständen von zwei Threads gleichzeitig auf das selbe Stück Hardware zuzugreifen. Je nachdem wie der Chip aufgebaut ist, könnte das durchaus als Hardware Error zu einem Cpu Reset führen.

HaWe
24.05.2019, 09:17
hallo,
danke, den 1. Teil mache und teste ich sofort!
auf der anderen Seite sollten gerade die Threads ihren momentanen Status per Serial an die Konsole melden, damit man den augenblicklichen Status erkenn kann, so ähnlich wie bei fprintf(stderr, ...) auf meinem Pi ... :-k

- - - Aktualisiert - - -

update:
Code geändert:


#include <Arduino.h>
#include <thread>
#include <chrono>

#ifndef LED_BUILTIN
#define LED_BUILTIN 13
#endif

const auto one_sec = std::chrono::seconds
{
1
};

void counter_loop() {
static uint32_t counter = 0;
while(true) {
Serial.print("counter_loop: ");
Serial.println(counter);
std::this_thread::sleep_for(one_sec);
}
}

void blinker_loop() {
static uint32_t counter = 0;
while(true) {
digitalWrite(LED_BUILTIN, HIGH);
Serial.print("blinker_loop (HIGH) counter: ");
Serial.println(counter);
std::this_thread::sleep_for(one_sec);

digitalWrite(LED_BUILTIN, LOW);
Serial.print("blinker_loop (LOW) counter: ");
Serial.println(counter);
std::this_thread::sleep_for(one_sec);
}
}

std::thread counter_loop_thread(counter_loop);
std::thread blinker_loop_thread(blinker_loop);

void setup() {
Serial.begin(115200);
pinMode(LED_BUILTIN, OUTPUT);

}

uint32_t main_loop_counter = 0;
void loop() {
main_loop_counter++;
Serial.print("main loop: ");
Serial.println(main_loop_counter);
delay(10000);
}


Good news: es läuft (irgendwie ;) ),
und die LED blinkt auch!
A-Bär:
Trotz "static" in den threads zählen aber die counter dort nicht hoch:


main loop: 1
counter_loop: 0
blinker_loop (LOW) counter: 0
blinker_loop (HIGH) counter: 0
counter_loop: 0
counter_loop: 0
blinker_loop (LOW) counter: 0
blinker_loop (HIGH) counter: 0
counter_loop: 0
counter_loop: 0
blinker_loop (LOW) counter: 0
blinker_loop (HIGH) counter: 0
counter_loop: 0
counter_loop: 0
blinker_loop (LOW) counter: 0
blinker_loop (HIGH) counter: 0
counter_loop: 0
counter_loop: 0
blinker_loop (LOW) counter: 0
blinker_loop (HIGH) counter: 0
counter_loop: 0
main loop: 2
counter_loop: 0
blinker_loop (LOW) counter: 0
blinker_loop (HIGH) counter: 0
counter_loop: 0
counter_loop: 0
blinker_loop (LOW) counter: 0
blinker_loop (HIGH) counter: 0
counter_loop: 0
counter_loop: 0
blinker_loop (LOW) counter: 0
blinker_loop (HIGH) counter: 0
counter_loop: 0
counter_loop: 0
blinker_loop (LOW) counter: 0
blinker_loop (HIGH) counter: 0
counter_loop: 0
counter_loop: 0
blinker_loop (LOW) counter: 0
blinker_loop (HIGH) counter: 0
counter_loop: 0
main loop: 3
counter_loop: 0
blinker_loop (LOW) counter: 0
blinker_loop (HIGH) counter: 0
counter_loop: 0
counter_loop: 0
blinker_loop (LOW) counter: 0
blinker_loop (HIGH) counter: 0
counter_loop: 0
counter_loop: 0
blinker_loop (LOW) counter: 0
blinker_loop (HIGH) counter: 0
counter_loop: 0
counter_loop: 0
blinker_loop (LOW) counter: 0
blinker_loop (HIGH) counter: 0
counter_loop: 0
counter_loop: 0
blinker_loop (LOW) counter: 0
blinker_loop (HIGH) counter: 0
counter_loop: 0
main loop: 4

Ceos
24.05.2019, 09:26
versuchs mal mit "thread_local" zwischen static und uint_32

das static wird bei thread_local zwar impliziert aber schaden kanns nicht es explizit zu schreiben

thread_local sorgt dafür dass die variable im richtigen stack kontext verwendet wird

Nachtrag: std::threads haben jeweils einene eigenen stack kontext und wenn man darin mit statischen variablen arbeitet kann das zu kuriosen erscheinungen führen, deshalb sollte man variablen die nur für den thread relevnt sind immer als thread_local definieren damit sie im stack korrekt verarbeitet werden, ansonsten natürlich mit globalen variabl... äh objekten arbeiten bitte

HaWe
24.05.2019, 09:30
danke für den Tipp, aber leider: nein


void counter_loop() {
static thread_local uint32_t counter = 0;
while(true) {
Serial.print("counter_loop: ");
Serial.println(counter);
std::this_thread::sleep_for(one_sec);
}
}

void blinker_loop() {
static thread_local uint32_t counter = 0;
while(true) {
digitalWrite(LED_BUILTIN, HIGH);
Serial.print("blinker_loop (HIGH) counter: ");
Serial.println(counter);
std::this_thread::sleep_for(one_sec);

digitalWrite(LED_BUILTIN, LOW);
Serial.print("blinker_loop (LOW) counter: ");
Serial.println(counter);
std::this_thread::sleep_for(one_sec);
}
}


main loop: 1
counter_loop: 0
blinker_loop (LOW) counter: 0
blinker_loop (HIGH) counter: 0
counter_loop: 0
counter_loop: 0
blinker_loop (LOW) counter: 0
blinker_loop (HIGH) counter: 0
counter_loop: 0
counter_loop: 0
blinker_loop (LOW) counter: 0
blinker_loop (HIGH) counter: 0
counter_loop: 0
counter_loop: 0
blinker_loop (LOW) counter: 0
blinker_loop (HIGH) counter: 0
counter_loop: 0
counter_loop: 0
blinker_loop (LOW) counter: 0
blinker_loop (HIGH) counter: 0
counter_loop: 0
main loop: 2
counter_loop: 0
blinker_loop (LOW) counter: 0
blinker_loop (HIGH) counter: 0
counter_loop: 0
counter_loop: 0
blinker_loop (LOW) counter: 0
blinker_loop (HIGH) counter: 0
counter_loop: 0
counter_loop: 0
blinker_loop (LOW) counter: 0
blinker_loop (HIGH) counter: 0
counter_loop: 0
counter_loop: 0
blinker_loop (LOW) counter: 0
blinker_loop (HIGH) counter: 0
counter_loop: 0
counter_loop: 0
blinker_loop (LOW) counter: 0
blinker_loop (HIGH) counter: 0
counter_loop: 0
main loop: 3


auch keine Änderung, wenn man dann das static wieder rausnimmt.

Ceos
24.05.2019, 09:31
öhm ... ich seh da eigentlich kein problem, du erstellst counter mit 0 und gibst es ständig immer wieder aus ohne damit überhaupt was zu machen ... cih glaube du hast da irgendwo in der schleife dein counter++ vergessen oder !?

edit: muss gesetehen habs das counter++ beim ersten mal lesen mental in den code gedichtet und hab den offensichtlichen fehler nicht gleich bemerkt (aber das thread_local sollte dennoch bei jeder lokalen variable dabei sein)

HaWe
24.05.2019, 09:38
hahahaha, ich lach mich tot..... ](*,)

JA!!!

sogar ohne static und ohne thread_local:


#include <Arduino.h>
#include <thread>
#include <chrono>

#ifndef LED_BUILTIN
#define LED_BUILTIN 13
#endif

const auto one_sec = std::chrono::seconds
{
1
};

void counter_loop() {
uint32_t counter = 0;
while(true) {
Serial.print("counter_loop: ");
Serial.println(counter);
std::this_thread::sleep_for(one_sec);
counter++;
}
}

void blinker_loop() {
uint32_t counter = 0;
while(true) {
digitalWrite(LED_BUILTIN, HIGH);
Serial.print("blinker_loop (HIGH) counter: ");
Serial.println(counter);
std::this_thread::sleep_for(one_sec);

digitalWrite(LED_BUILTIN, LOW);
Serial.print("blinker_loop (LOW) counter: ");
Serial.println(counter);
std::this_thread::sleep_for(one_sec);
counter++;
}
}

std::thread counter_loop_thread(counter_loop);
std::thread blinker_loop_thread(blinker_loop);

void setup() {
Serial.begin(115200);
pinMode(LED_BUILTIN, OUTPUT);

}

uint32_t main_loop_counter = 0;
void loop() {
main_loop_counter++;
Serial.print("main loop: ");
Serial.println(main_loop_counter);
delay(10000);
}


main loop: 1
counter_loop: 1
blinker_loop (LOW) counter: 0
blinker_loop (HIGH) counter: 1
counter_loop: 2
counter_loop: 3
blinker_loop (LOW) counter: 1
blinker_loop (HIGH) counter: 2
counter_loop: 4
counter_loop: 5
blinker_loop (LOW) counter: 2
blinker_loop (HIGH) counter: 3
counter_loop: 6
counter_loop: 7
blinker_loop (LOW) counter: 3
blinker_loop (HIGH) counter: 4
counter_loop: 8
counter_loop: 9
blinker_loop (LOW) counter: 4
blinker_loop (HIGH) counter: 5
counter_loop: 10
main loop: 2
counter_loop: 11
blinker_loop (LOW) counter: 5
blinker_loop (HIGH) counter: 6
counter_loop: 12
counter_loop: 13
blinker_loop (LOW) counter: 6
blinker_loop (HIGH) counter: 7
counter_loop: 14
counter_loop: 15
blinker_loop (LOW) counter: 7
blinker_loop (HIGH) counter: 8
counter_loop: 16
counter_loop: 17
blinker_loop (LOW) counter: 8
blinker_loop (HIGH) counter: 9
counter_loop: 18
counter_loop: 19
blinker_loop (LOW) counter: 9
blinker_loop (HIGH) counter: 10
counter_loop: 20
main loop: 3
counter_loop: 21


vielen Dank an euch beide, das ist jetzt echt ne super Basis um weiterzumachen!
Ein Riesen-Schritt für die Menschheit!
großartig, danke!

Ceos
24.05.2019, 09:40
sogar ohne static und ohne thread_local:

wie gesagt, thread_local ist garnicht falsch, erspart dir später womöglich kuriose bugs ... ich würde es immer drin lassen!

HaWe
24.05.2019, 09:57
okidoki, danke!

- - - Aktualisiert - - -

PS,
interessanter Effekt, gerade bemerkt:
in der blinker_loop zählt der counter zwischen den sleeps und dem LED ON/OFF-Paar weiter, obwohl ich hier denselben counterwert für ON und OFF erwartet hätte, bis zum nächsten loop-Durchlauf für das nächste ON/OFF-Paar

Ceos
24.05.2019, 10:05
hast du dazu einen aktualisierten code ?

HaWe
24.05.2019, 10:29
ist immer noch der von #7 !

- - - Aktualisiert - - -

gerade getestet:
thread_local uint32_t counter = 0;
macht hier auch keinen Unterschied

Ceos
24.05.2019, 10:30
ja ... sorry ... hab ich nicht gesehen

interessante ausgabe, gebe ich zu ... es wäre mal interessant zu erfahren wie der zeitliche ablauf bei der ausgabe aussieht! ich vermute hier das problem!

benutze mal irgend einen timer mit einer auflösung im wenigstens 100tel Sekunden bereich und speichere vor und nach jedem sleep jeweils einmal die zeit und gib die zeiten plus die aktuelle zeit auch als print aus

also quasi print("Jetzt: %d Vorher: %d Nachher %d",timer.now(), beforesleep, aftersleep)

so kann man erstmal prüfen ob der sleep vernünftig funktioniert und dann ob der print hier irgendwelche delays verursacht

ich denke dass die ausgaben bei dir nicht chronologisch korrekt ausgegeben werden

HaWe
24.05.2019, 10:36
hmmm... könnte vlt...
andererseits wird in den blinker_thread zwischen dem ON/OFF-Paar gar nicht inkrementiert, also egal, wann das ausgegeben wird, es müsste 1 ON/OFF-Paar IMO erwartungsgemäß IMMER mit demselben gemeinsamen counter-Wert erscheinen...
...oder?

Ceos
24.05.2019, 10:52
nicht zwingend, deswegen meinte ich ja ich vermute hier eine sogenannte race condition, ich würde gerne ausschließen dass der print hier dazwischen funkt und daher wollte ich auch dass du in einer print funktion gleichzeitig variablen und einen funktionsaufruf nutzt um mal einen einblick auf den ablauf zu bekommen und das sleep gleichzeitg zu testen (zwei sleeps in einem thread können je nach architektur lustige effekte haben)

und mit architektur meine ich das thread handling und den "sheduler"

HaWe
24.05.2019, 10:55
ok, aber ich verstehe deinen code-Vorschlag noch nicht exakt.

Könntest du das bitte mal in den ino-Code genau hineinschreiben, fertig compilierbar?

Ceos
24.05.2019, 11:33
sorry, da müsste ich erstmal selber was probieren, hab keinen plan wie man auf die schnelle bei arduino nen timer hinbastelt

HaWe
24.05.2019, 12:01
sorry, da müsste ich erstmal selber was probieren, hab keinen plan wie man auf die schnelle bei arduino nen timer hinbastelt

reicht dir millis()
oder float secs = millis/1000.0 ?

Ceos
24.05.2019, 12:33
völlig, nur irgend eine Zeitreferenz



uint64_t vorher, nachher; //ich nehme einfach mal an dass millis uint64 ist
vorher= millis();
std::this_thread::sleep_for(one_sec);
nachher = millis;

Serial.println("sleep1:");
Serial.println(vorher);
Serial.println(nachher);
Serial.println(millis);

soll natürlich jeweils für jeden sleep dann sleep1 sleep2 und sleep3 heißen damit man weis welcher gerade ausgegeben wird

meine Vermutung ist, dass zwischen vorher und nachher immer rund 1000 Differenz ist, aber der 3te Wert zwischen den Sleeps vorwärts und rückwärts springt

oder, da wir neuen Code reinbringen, der counter plötzlich anfängt richtig zu zählen weil wir die racing condition brechen

HaWe
24.05.2019, 12:34
danke,
und wie jetzt wo hin kopiert?

Ceos
24.05.2019, 12:37
jeweils um die 3 Zeilen mit
"std::this_thread::sleep_for(one_sec);"

herum nur eben für jede ein anderes "sleep1" "sleep2" "sleep3"

HaWe
24.05.2019, 12:39
sei doch bitte so nett und schreib das mal komplett als thread, nicht dass ich es falsch versteh und dann nur Mist raus
kommt.

Ceos
24.05.2019, 12:44
void counter_loop() {
static thread_local uint32_t counter = 0;
thread_local uint64_t vorher1, nachher1;
while(true) {
Serial.print("counter_loop: ");
Serial.println(counter);
vorher1 = millis();
std::this_thread::sleep_for(one_sec);
nachher1 = millis();
println("Sleep1:");
println(vorher1);
println(nachher1);
println(millis());
}
}

void blinker_loop() {
static thread_local uint32_t counter = 0;
thread_local uint64_t vorher2, nachher2, vorher3, nachher3;
while(true) {
digitalWrite(LED_BUILTIN, HIGH);
Serial.print("blinker_loop (HIGH) counter: ");
Serial.println(counter);
vorher2 = millis();
std::this_thread::sleep_for(one_sec);
nachher2 = millis();
println("Sleep2:");
println(vorher2);
println(nachher2);
println(millis());

digitalWrite(LED_BUILTIN, LOW);
Serial.print("blinker_loop (LOW) counter: ");
Serial.println(counter);
vorher3 = millis();
std::this_thread::sleep_for(one_sec);
nachher3 = millis();
println("Sleep3:");
println(vorher3);
println(nachher3);
println(millis());
}
}

ich habe mal noch explizit die Variablen getrennt um irgendwelche Phänomene auszuschließen

HaWe
24.05.2019, 12:55
ah, ok....!
Man merkt: kein Arduinorianer... ;)

print geht nicht, nur Serial.print,
und Serial.print geht nicht mit uint64_t 8)

habe es geändert, das Ergebnis sieht aber ziemlich wirr aus...:


// std::thread for ESP32, Arduino IDE

// https://www.roboternetz.de/community/threads/73446-std-thread-f%C3%BCr-ESP32-unter-Arduino-IDE-zum-Laufen-zu-kriegen?p=652309&viewfull=1#post652309

// https://github.com/espressif/arduino-esp32/issues/2814#issuecomment-495525603


#include <Arduino.h>
#include <thread>
#include <chrono>

#ifndef LED_BUILTIN
#define LED_BUILTIN 13
#endif

const auto one_sec = std::chrono::seconds
{
1
};

void counter_loop() {
static thread_local uint32_t counter = 0;
thread_local uint32_t vorher1, nachher1;
while(true) {
Serial.print("counter_loop: ");
Serial.println(counter);
vorher1 = millis();
std::this_thread::sleep_for(one_sec);
nachher1 = millis();
Serial.println("Sleep1:");
Serial.println(vorher1);
Serial.println(nachher1);
Serial.println(millis());
}
}

void blinker_loop() {
static thread_local uint32_t counter = 0;
thread_local uint32_t vorher2, nachher2, vorher3, nachher3;
while(true) {
digitalWrite(LED_BUILTIN, HIGH);
Serial.print("blinker_loop (HIGH) counter: ");
Serial.println(counter);
vorher2 = millis();
std::this_thread::sleep_for(one_sec);
nachher2 = millis();
Serial.println("Sleep2:");
Serial.println(vorher2);
Serial.println(nachher2);
Serial.println(millis());

digitalWrite(LED_BUILTIN, LOW);
Serial.print("blinker_loop (LOW) counter: ");
Serial.println(counter);
vorher3 = millis();
std::this_thread::sleep_for(one_sec);
nachher3 = millis();
Serial.println("Sleep3:");
Serial.println(vorher3);
Serial.println(nachher3);
Serial.println(millis());
}
}




std::thread counter_loop_thread(counter_loop);
std::thread blinker_loop_thread(blinker_loop);

void setup() {
Serial.begin(115200);
pinMode(LED_BUILTIN, OUTPUT);

}

uint32_t main_loop_counter = 0;
void loop() {
main_loop_counter++;
Serial.print("main loop: ");
Serial.println(main_loop_counter);
delay(10000);
}




main loop: 1
Sleep1:
1
1001
1001
counter_loop: 0
Sleep2:
1
1001
1001
blinker_loop (LOW) counter: 0
Sleep3:
1001
2001
2001
blinker_loop (HIGH) counter: 0
Sleep1:
1001
2001
2001
counter_loop: 0
Sleep1:
2001
3001
3001
counter_loop: 0
Sleep2:
2001
3001
3001
blinker_loop (LOW) counter: 0
Sleep3:
3001
4001
4001
blinker_loop (HIGH) counter: 0
Sleep1:
3001
4001
4001
counter_loop: 0
Sleep1:
4001
5001
5001
counter_loop: 0
Sleep2:
4001
5001
5001
blinker_loop (LOW) counter: 0
Sleep3:
5001
6001
6001
blinker_loop (HIGH) counter: 0
Sleep1:
5001
6001
6001
counter_loop: 0
Sleep1:
6001
7001
7001
counter_loop: 0
Sleep2:
6001
7001
7001
blinker_loop (LOW) counter: 0
Sleep3:
7001
8001
8001
blinker_loop (HIGH) counter: 0
Sleep1:
7001
8001
8001
counter_loop: 0
Sleep1:
8001
9001
9001
counter_loop: 0
Sleep2:
8001
9001
9001
blinker_loop (LOW) counter: 0
Sleep3:
9001
10001
10001
blinker_loop (HIGH) counter: 0
Sleep1:
9001
10001
10001
counter_loop: 0
main loop: 2
Sleep1:
10001
11001
11001
counter_loop: 0
Sleep2:
10001
11001
11001
blinker_loop (LOW) counter: 0
Sleep3:
11001
12001
12001
blinker_loop (HIGH) counter: 0
Sleep1:
11001
12001
12001
counter_loop: 0
Sleep1:
12001
13001
13001
counter_loop: 0
Sleep2:
12001
13001
13001
blinker_loop (LOW) counter: 0
Sleep3:
13001
14001
14001
blinker_loop (HIGH) counter: 0
Sleep1:
13001
14001
14001
counter_loop: 0
Sleep1:
14001
15001
15001
counter_loop: 0
Sleep2:
14001
15001
15001
blinker_loop (LOW) counter: 0
Sleep3:
15001
16001
16001
blinker_loop (HIGH) counter: 0
Sleep1:
15001
16001
16001
counter_loop: 0
Sleep1:
16001
17001
17001
counter_loop: 0
Sleep2:
16001
17001
17001
blinker_loop (LOW) counter: 0
Sleep3:
17001
18001
18001
blinker_loop (HIGH) counter: 0
Sleep1:
17001
18001
18001
counter_loop: 0
Sleep1:
18001
19001
19001
counter_loop: 0
Sleep2:
18001
19001
19001
blinker_loop (LOW) counter: 0
Sleep3:
19001
20001
20001
blinker_loop (HIGH) counter: 0
Sleep1:
19001
20001
20001
counter_loop: 0
main loop: 3
Sleep1:
20001
21001
21001
counter_loop: 0
Sleep2:
20001
21001
21001
blinker_loop (LOW) counter: 0
Sleep3:
21001
22001
22001
blinker_loop (HIGH) counter: 0
Sleep1:
21001
22001
22001
counter_loop: 0
Sleep1:
22001
23001
23001
counter_loop: 0
Sleep2:
22001
23001
23001
blinker_loop (LOW) counter: 0
Sleep3:
23001
24001
24001
blinker_loop (HIGH) counter: 0
Sleep1:
23001
24001
24001
counter_loop: 0
Sleep1:
24001
25001
25001
counter_loop: 0
Sleep2:
24001
25001
25001
blinker_loop (LOW) counter: 0
Sleep3:
25001
26001
26001
blinker_loop (HIGH) counter: 0
Sleep1:
25001
26001
26001
counter_loop: 0
Sleep1:
26001
27001
27001
counter_loop: 0
Sleep2:
26001
27001
27001
blinker_loop (LOW) counter: 0
Sleep3:
27001
28001
28001
blinker_loop (HIGH) counter: 0
Sleep1:
27001
28001
28001
counter_loop: 0
Sleep1:
28001
29001
29001
counter_loop: 0
Sleep2:
28001
29001
29001
blinker_loop (LOW) counter: 0
Sleep3:
29001
30001
30001
blinker_loop (HIGH) counter: 0
Sleep1:
29001
30001
30001
counter_loop: 0
main loop: 4
Sleep1:
30001
31001
31001
counter_loop: 0
Sleep2:
30001
31001
31001
blinker_loop (LOW) counter: 0
Sleep3:
31001
32001
32001
blinker_loop (HIGH) counter: 0
Sleep1:
31001
32001
32001
counter_loop: 0
Sleep1:
32001
33001
33001
counter_loop: 0
Sleep2:
32001
33001
33001
blinker_loop (LOW) counter: 0
Sleep3:
33001
34001
34001
blinker_loop (HIGH) counter: 0
Sleep1:
33001
34001
34001
counter_loop: 0
Sleep1:
34001
35001
35001
counter_loop: 0
Sleep2:
34001
35001
35001
blinker_loop (LOW) counter: 0
Sleep3:
35001
36001
36001
blinker_loop (HIGH) counter: 0
Sleep1:
35001
36001
36001
counter_loop: 0
Sleep1:
36001
37001
37001
counter_loop: 0
Sleep2:
36001
37001
37001
blinker_loop (LOW) counter: 0
Sleep3:
37001
38001
38001
blinker_loop (HIGH) counter: 0
Sleep1:
37001
38001
38001
counter_loop: 0
Sleep1:
38001
39001
39001
counter_loop: 0
Sleep2:
38001
39001
39001
blinker_loop (LOW) counter: 0
Sleep3:
39001
40001
40001
blinker_loop (HIGH) counter: 0
Sleep1:
39001
40001
40001
counter_loop: 0
main loop: 5
Sleep1:
40001
41001
41001
counter_loop: 0
Sleep2:
40001
41001
41001
blinker_loop (LOW) counter: 0
Sleep3:
41001
42001
42001
blinker_loop (HIGH) counter: 0
Sleep1:
41001
42001
42001
counter_loop: 0
Sleep1:
42001
43001
43001
counter_loop: 0
Sleep2:
42001
43001
43001
blinker_loop (LOW) counter: 0
Sleep3:
43001
44001
44001
blinker_loop (HIGH) counter: 0
Sleep1:
43001
44001
44001
counter_loop: 0
Sleep1:
44001
45001
45001
counter_loop: 0
Sleep2:
44001
45001
45001
blinker_loop (LOW) counter: 0
Sleep3:
45001
46001
46001
blinker_loop (HIGH) counter: 0
Sleep1:
45001
46001
46001
counter_loop: 0
Sleep1:
46001
47001
47001
counter_loop: 0
Sleep2:
46001
47001
47001
blinker_loop (LOW) counter: 0
Sleep3:
47001
48001
48001
blinker_loop (HIGH) counter: 0
Sleep1:
47001
48001
48001
counter_loop: 0
Sleep1:
48001
49001
49001
counter_loop: 0
Sleep2:
48001
49001
49001
blinker_loop (LOW) counter: 0
Sleep3:
49001
50001
50001
blinker_loop (HIGH) counter: 0
Sleep1:
49001
50001
50001
counter_loop: 0
main loop: 6
Sleep1:
50001
51001
51001
counter_loop: 0
Sleep2:
50001
51001
51001
blinker_loop (LOW) counter: 0
Sleep3:
51001
52001
52001
blinker_loop (HIGH) counter: 0
Sleep1:
51001
52001
52001
counter_loop: 0
Sleep1:
52001
53001
53001
counter_loop: 0
Sleep2:
52001
53001
53001
blinker_loop (LOW) counter: 0
Sleep3:
53001
54001
54001
blinker_loop (HIGH) counter: 0
Sleep1:
53001
54001
54001
counter_loop: 0



- - - Aktualisiert - - -

lad dir doch mal ne "portable" Arduino IDE herunter... ;)

Ceos
24.05.2019, 13:07
das entspricht aber ziemlich gut meiner Vermutung, die prints kommen irgendwie durcheinander

zwischen der ersten und 2ten Zahl pro Sleep ist immer sauber 1000 differenz

aber wenn wir mal die letzten paar ausgaben ansehen siehst du dass 2 mal hintereinander "Sleep1" mit jeweils einer Sekunden Abstand ausgegeben wird und "Sleep2" und "Sleep3" immer direkt hintereinander obwohl man eher erwarten würde dass es immer 1 -> 2 -> 1 -> 3 -> 1 -> 2 gehen sollte

Das heißt das der print scheinbar in einer anderen Reihenfolge ausgegeben wird

ich bin nur etwas überrascht dass die millis immer so exakt gleich sind! Ich hatte gehofft dass die Ausgaben da wenigstens minimal um 1ms versetzt sind um die tatsächliche Ausführungszeit zu sehen :(

----

leider kann ich jetzt auch erstmal nicht weiter mithelfen, ich bin das wochenende offline unterwegs und die reise geht gleich los

HaWe
24.05.2019, 14:08
update: der Code jetzt hier scheint besser zu laufen:





> counter_loop: 0
> blinker_loop (HIGH) counter: 0
> main loop: 1
> blinker_loop (LOW) counter: 0
> counter_loop: 1
> counter_loop: 2
> blinker_loop (HIGH) counter: 1
> blinker_loop (LOW) counter: 1
> counter_loop: 3
> counter_loop: 4
> blinker_loop (HIGH) counter: 2
> blinker_loop (LOW) counter: 2
> counter_loop: 5
> counter_loop: 6
> blinker_loop (HIGH) counter: 3
> blinker_loop (LOW) counter: 3
> counter_loop: 7
> counter_loop: 8
> blinker_loop (HIGH) counter: 4
> blinker_loop (LOW) counter: 4
> counter_loop: 9
> counter_loop: 10
> blinker_loop (HIGH) counter: 5
> main loop: 2
> blinker_loop (LOW) counter: 5
> counter_loop: 11
> counter_loop: 12
> blinker_loop (HIGH) counter: 6
> blinker_loop (LOW) counter: 6
> counter_loop: 13
> counter_loop: 14
> blinker_loop (HIGH) counter: 7
> blinker_loop (LOW) counter: 7
> counter_loop: 15
> counter_loop: 16
> blinker_loop (HIGH) counter: 8
> blinker_loop (LOW) counter: 8
> counter_loop: 17
> counter_loop: 18
> blinker_loop (HIGH) counter: 9
> blinker_loop (LOW) counter: 9
> counter_loop: 19
> counter_loop: 20
> blinker_loop (HIGH) counter: 10
> main loop: 3
> blinker_loop (LOW) counter: 10

code:

```

// std::thread for ESP32, Arduino IDE

#include <Arduino.h>
#include <thread>
#include <chrono>

#ifndef LED_BUILTIN
#define LED_BUILTIN 13
#endif

const auto one_sec = std::chrono::seconds
{
1
};

void counter_loop() {
thread_local uint32_t counter = 0;
while(true) {
Serial.print("counter_loop: ");
Serial.println(counter);
std::this_thread::sleep_for(one_sec);
counter++;
}
}

void blinker_loop() {
thread_local uint32_t counter = 0;
while(true) {
digitalWrite(LED_BUILTIN, HIGH);
Serial.print("blinker_loop (HIGH) counter: ");
Serial.println(counter);
std::this_thread::sleep_for(one_sec);

digitalWrite(LED_BUILTIN, LOW);
Serial.print("blinker_loop (LOW) counter: ");
Serial.println(counter);
std::this_thread::sleep_for(one_sec);
counter++;
}
}


std::unique_ptr<std::thread> counter_loop_thread;
std::unique_ptr<std::thread> blinker_loop_thread;

void setup() {
Serial.begin(115200);
//debug
delay(2000);

counter_loop_thread.reset(new std::thread(counter_loop));
blinker_loop_thread.reset(new std::thread(blinker_loop));
}


uint32_t main_loop_counter = 0;
void loop() {
main_loop_counter++;
Serial.print("main loop: ");
Serial.println(main_loop_counter);
delay(10000);
}
```

- - - Aktualisiert - - -

update2:
gleich gutes Ergebnis bei dieser Code-Implementierung:


std::thread *counter_loop_thread;
std::thread *blinker_loop_thread;


void setup() {
Serial.begin(115200);
//debug
delay(2000);
counter_loop_thread = new std::thread(counter_loop);
blinker_loop_thread = new std::thread(blinker_loop);
}

shedepe
24.05.2019, 14:35
Was du suchst ist ein std::mutex (in der Hoffnung dass der implementiert wurde). Ein Mutex ist eine Synchronisierungsobjekt zwischen Threads.
D.h. du brauchst in etwas sowas:



std::mutex m_lock;

void myWrite(std::string str)
{
m_lock.lock();
Serial.print(str);
m_lock.unlock();
}

HaWe
24.05.2019, 15:16
Was du suchst ist ein std::mutex (in der Hoffnung dass der implementiert wurde). Ein Mutex ist eine Synchronisierungsobjekt zwischen Threads.
D.h. du brauchst in etwas sowas:



std::mutex m_lock;

void myWrite(std::string str)
{
m_lock.lock();
Serial.print(str);
m_lock.unlock();
}


danke für den wertvollen Tipp, das ist sehr hilfreich!
Für den Augenblick geht es ja auch ohne (s. Serial logs), aber wenn es mal zeitkritischer wird: auf jeden Fall dann!
Danke!

Ich gucke später auch mal, ob der tatsächlich implementiert wurde!

PS:
auch für dich fände ich es klasse, wenn du dir mal ne portable IDE installieren könntest! 8)

HaWe
28.05.2019, 14:49
update:
mutex ist doch drin, braucht nur zusätzlich

#include <mutex>

was ich nicht wusste,
dann klappt jetzt auch


std::mutex print_mutex;

void myPrint(String str) // String: Arduino API // C++: std::string
{
print_mutex.lock();
Serial.println(str);
print_mutex.unlock();
}

HaWe
28.05.2019, 18:26
es gibt hier noch einen Bug oder Issue, wie man thread prios richtig setzt - bisher brachten alle Vorschläge noch keine Lösung.
Man muss nämlich die thread prios der main loop prio angleichen, wenn beide ohne delays parallel laufen sollen
(std::threads laufen nämlich per prio=5 per default, main loop nur bei default prio=1!!):


esp_pthread_cfg_t cfg;
esp_pthread_get_cfg(&cfg);
cfg.prio=1;
esp_pthread_set_cfg(&cfg);

funktioniert nicht, weil anfangs cfg noch keine Werte enthält und daher einen Fehler zurückgibt,

und



esp_pthread_cfg_t cfg;
if (esp_pthread_get_cfg(&cfg) != ESP_OK) {
cfg = esp_pthread_get_default_config();
}
cfg.prio=1;
if (esp_pthread_set_cfg(&cfg) != ESP_OK) {
printf("esp_pthread_set_cfg failed\n");
abort();
};

funktioniert auch nicht, weil die hier verwendete Funktion
esp_pthread_get_default_config();
nicht gefunden wird.

siehe Topic-Posts u.a.
https://github.com/espressif/ESP8266_RTOS_SDK/issues/609
https://github.com/espressif/esp-idf/issues/3544#issuecomment-496157019
und folgende...

betroffene libs am ehesten wohl
https://github.com/espressif/ESP8266_RTOS_SDK/tree/master/components/pthread/src


Hat jemand eine idee, wie es richtig geht?

HaWe
29.05.2019, 19:35
update:
der ESP32 scheduler arbeitet tatsächlich nur eingeschränkt preemptiv, u.a. da er vom FreeRTOS und seinem Watchdog abhängig ist, der nur begrenzt ausgeblendet/resetted werden kann,sobad ein Thread "stalled", und dann das gesamte System sich aufhängt.
Außerdem scheint es dann auch Probleme mit threads zu geben, die auf den 2 cores laufen und dann (IIUC) ebenfalls zu Konflikten führen.

update:
trotz hoffnungsvoller Nachrichten in ESP32 github repo: noch immer nicht gelöst

HaWe
30.07.2019, 11:42
so, ich habe es hin bekommen:
man muss die thread prios unter die von main loop setzen, damit der watch dog von main gefüttert wird.
Da main immer prio=1 by default hat, müssen die threads bei prio 0 laufen, damit sie nicht blockieren können:



// std::thread for ESP32, Arduino IDE

// ver 0.0.6 fibonacci

#include <Arduino.h>
#include <thread>
#include <freertos/task.h>

#ifndef LED_BUILTIN
#define LED_BUILTIN 13
#endif

const auto one_sec = std::chrono::seconds
{
1
};




uint32_t fibonacci(uint32_t n) {
if(n == 0){
return 0;
} else if(n == 1) {
return 1;
} else {
return (fibonacci(n-1) + fibonacci(n-2));
}
}



void blinker_loop() {
thread_local uint32_t counter = 0;
Serial.println((String)"blinker_loop Current priority :" + uxTaskPriorityGet(NULL));
vTaskPrioritySet(NULL,0);//set Priority
Serial.println((String)"blinker_loop Current priority :" + uxTaskPriorityGet(NULL));
while(true) {
digitalWrite(LED_BUILTIN, HIGH);
Serial.println((String)"blinker_loop (HIGH) counter: "+ counter);
std::this_thread::sleep_for(one_sec);

digitalWrite(LED_BUILTIN, LOW);
Serial.println((String)"blinker_loop (LOW) counter: "+ counter);
std::this_thread::sleep_for(one_sec);

counter++;
}
}


void fibonacci_loop() {
thread_local uint32_t counter = 0, i=0;
Serial.println((String)"fibonacci_loop Current priority :" + uxTaskPriorityGet(NULL));
vTaskPrioritySet(NULL,0);//set Priority
Serial.println((String)"fibonacci_loop Current priority :" + uxTaskPriorityGet(NULL));
while(true) {
for(i=30; i<41; i++) { // limits: test, debug
Serial.println( (String)"Fibbonacci of "+i+"="+fibbonacci(i));
}
Serial.println((String)"fibonacci_loop counter: "+counter);
counter++;
}
}



std::thread *thread_1;
std::thread *thread_2;


void setup() {
Serial.begin(115200);
delay(1000);
thread_1 = new std::thread(blinker_loop);
thread_2 = new std::thread(fibonacci_loop);
}


void loop() {
delay(500);
static uint32_t main_loop_counter = 0;
Serial.println((String)"main loop: " + main_loop_counter);
delay(5000);
main_loop_counter++;
}





blinker_loop Current priority :5
blinker_loop Current priority :0
fibonacci_loop Current priority :5
blinker_loop (HIGH) counter: 0
fibonacci_loop Current priority :0
Fibbonacci of 30=832040
main loop: 0
Fibbonacci of 31=1346269
blinker_loop (LOW) counter: 0
Fibbonacci of 32=2178309
blinker_loop (HIGH) counter: 1
Fibbonacci of 33=3524578
blinker_loop (LOW) counter: 1
blinker_loop (HIGH) counter: 2
Fibbonacci of 34=5702887
blinker_loop (LOW) counter: 2
main loop: 1
blinker_loop (HIGH) counter: 3
blinker_loop (LOW) counter: 3
blinker_loop (HIGH) counter: 4
Fibbonacci of 35=9227465
blinker_loop (LOW) counter: 4
blinker_loop (HIGH) counter: 5
blinker_loop (LOW) counter: 5
main loop: 2
blinker_loop (HIGH) counter: 6
blinker_loop (LOW) counter: 6
Fibbonacci of 36=14930352
blinker_loop (HIGH) counter: 7
blinker_loop (LOW) counter: 7
blinker_loop (HIGH) counter: 8
main loop: 3
blinker_loop (LOW) counter: 8
blinker_loop (HIGH) counter: 9
blinker_loop (LOW) counter: 9
blinker_loop (HIGH) counter: 10
blinker_loop (LOW) counter: 10
Fibbonacci of 37=24157817
blinker_loop (HIGH) counter: 11
main loop: 4
blinker_loop (LOW) counter: 11
blinker_loop (HIGH) counter: 12
blinker_loop (LOW) counter: 12
blinker_loop (HIGH) counter: 13
blinker_loop (LOW) counter: 13
main loop: 5
blinker_loop (HIGH) counter: 14
blinker_loop (LOW) counter: 14
blinker_loop (HIGH) counter: 15
blinker_loop (LOW) counter: 15
blinker_loop (HIGH) counter: 16
blinker_loop (LOW) counter: 16
main loop: 6
blinker_loop (HIGH) counter: 17
blinker_loop (LOW) counter: 17
Fibbonacci of 38=39088169
blinker_loop (HIGH) counter: 18
blinker_loop (LOW) counter: 18
blinker_loop (HIGH) counter: 19
main loop: 7
blinker_loop (LOW) counter: 19
blinker_loop (HIGH) counter: 20
blinker_loop (LOW) counter: 20
blinker_loop (HIGH) counter: 21
blinker_loop (LOW) counter: 21
blinker_loop (HIGH) counter: 22
main loop: 8
blinker_loop (LOW) counter: 22
blinker_loop (HIGH) counter: 23
blinker_loop (LOW) counter: 23
blinker_loop (HIGH) counter: 24
blinker_loop (LOW) counter: 24
main loop: 9
blinker_loop (HIGH) counter: 25
blinker_loop (LOW) counter: 25
blinker_loop (HIGH) counter: 26
blinker_loop (LOW) counter: 26
blinker_loop (HIGH) counter: 27
blinker_loop (LOW) counter: 27
main loop: 10
blinker_loop (HIGH) counter: 28
blinker_loop (LOW) counter: 28
blinker_loop (HIGH) counter: 29
Fibbonacci of 39=63245986
blinker_loop (LOW) counter: 29
blinker_loop (HIGH) counter: 30
main loop: 11
blinker_loop (LOW) counter: 30
blinker_loop (HIGH) counter: 31
blinker_loop (LOW) counter: 31
blinker_loop (HIGH) counter: 32
blinker_loop (LOW) counter: 32
blinker_loop (HIGH) counter: 33
main loop: 12
blinker_loop (LOW) counter: 33
blinker_loop (HIGH) counter: 34
blinker_loop (LOW) counter: 34
blinker_loop (HIGH) counter: 35
blinker_loop (LOW) counter: 35
main loop: 13
blinker_loop (HIGH) counter: 36
blinker_loop (LOW) counter: 36
blinker_loop (HIGH) counter: 37
blinker_loop (LOW) counter: 37
blinker_loop (HIGH) counter: 38
blinker_loop (LOW) counter: 38
main loop: 14
blinker_loop (HIGH) counter: 39
blinker_loop (LOW) counter: 39
blinker_loop (HIGH) counter: 40
blinker_loop (LOW) counter: 40
blinker_loop (HIGH) counter: 41
main loop: 15
blinker_loop (LOW) counter: 41
blinker_loop (HIGH) counter: 42
blinker_loop (LOW) counter: 42
blinker_loop (HIGH) counter: 43
blinker_loop (LOW) counter: 43
blinker_loop (HIGH) counter: 44
main loop: 16
blinker_loop (LOW) counter: 44
blinker_loop (HIGH) counter: 45
blinker_loop (LOW) counter: 45
blinker_loop (HIGH) counter: 46
blinker_loop (LOW) counter: 46
main loop: 17
blinker_loop (HIGH) counter: 47
Fibbonacci of 40=102334155
fibonacci_loop counter: 0
Fibbonacci of 30=832040
blinker_loop (LOW) counter: 47
Fibbonacci of 31=1346269
blinker_loop (HIGH) counter: 48
Fibbonacci of 32=2178309
blinker_loop (LOW) counter: 48
Fibbonacci of 33=3524578
blinker_loop (HIGH) counter: 49
blinker_loop (LOW) counter: 49
main loop: 18
Fibbonacci of 34=5702887
blinker_loop (HIGH) counter: 50
blinker_loop (LOW) counter: 50
blinker_loop (HIGH) counter: 51
Fibbonacci of 35=9227465
blinker_loop (LOW) counter: 51
blinker_loop (HIGH) counter: 52
main loop: 19
blinker_loop (LOW) counter: 52
blinker_loop (HIGH) counter: 53
blinker_loop (LOW) counter: 53
blinker_loop (HIGH) counter: 54
Fibbonacci of 36=14930352
blinker_loop (LOW) counter: 54
blinker_loop (HIGH) counter: 55
main loop: 20
blinker_loop (LOW) counter: 55



ntl nur der jetzige Stand, möglicherweise erscheinen doch wieder irgendwann neue Erkenntnisse... ;) 8)

Moppi
30.07.2019, 12:00
Jetzt mal eine ganz ernsthafte Frage. Wozu soll denn so ein Overhead bei den Winzig-Programmen, die normal in der Arduino-IDE verfasst werden, gut sein?
Was versuchst Du denn da, mit tausend Blinkern? ;)


MfG

HaWe
30.07.2019, 12:31
ein Test-Setup zum Simulieren von preemptivem Multithreading mit plötzlich hängenden Einzel-Threads.

Bisher hat der Scheduler nicht preemptiv gearbeitet, weil bei nicht angepassten prios der RTOS watchdog blockiert und resetted wird, dadurch kommt es zum Programmabsturz und Neustart.
Jetzt können die Threads, wenn einer von ihnen blockiert, ungestört weiterlaufen, unter Beobachtung und mit Notfall-Maßnahmen.

Beispiel:
Autonomer Robot, fährt momentan geradeaus. Plötzlich blockiert der Thread, der die i2c-Distanzsensoren ausgelesen hat (oder irgendein anderer wichtiger Kontroll- oder Mess-Thread).
Folge: Robot fährt weiter und crasht, weil der Fehler nicht rechtzeitig erkannt wird.
Jetzt kann per Timestamp-Watcher jeder Thread kontrolliert werden, und wenn einer hängt, kann das System geregelt zum Stoppen gebracht werden, evtl. sogar autonome Reparaturversuche - vorher ging noch nicht mal mehr eine Kontrolle.

Wir hatten dieses Problem auch schon für die Raspi-Plattform in C mit pthread diskutiert.

Moppi
30.07.2019, 12:50
Ich habe schon eine grafische, kooperative Multitasking-Oberfläche in der Vergangenheit in Assembler umgesetzt. Für PC. Daher kenne ich die Probleme.
Die Idee, die Du ansprichst ist daher nicht neu, sondern tauchte damals auch auf. Ich habe dann genau so etwas umgesetzt. Nämlich eine Kontrolle der Bibliotheken im Speicher mit Reparaturfunktion, indem Bibliotheken, deren Prüfsumme nicht mehr stimmte, nachgeladen wurden. Das Ende der Sache war mehr Overhead (also verlorene Rechenleistung) und der Nutzen dummerweise = Null. Das resultierte daraus, dass die Idee zwar gut, aber es nie zu diesen angenommenen Ausnahmen kam. Wenn, dann waren es Einzelfälle, wo ein Programmier- oder Denkfehler zugrunde lag. Ähnlich war es mit der implementierten Stapelüberwachung. Das brachte zumindest was, weil sich bei manchen Programmen nicht gut abschätzen lies, wieviel Stapelspeicher tatsächlich benötigt wird. Nach ein wenig Erfahrung hatte sich dieses Thema aber auch wieder erledigt. So war diese Funktion auch nur während der Entwicklungsphase von Applikationen gut, damit zumindest zwischendurch nicht dauernd das gesamte System hängen blieb.
Fehler beheben ist bsesser, als sich auf solche Funktionen zu verlassen, die dann die Rechenleistung stehlen.


MfG

HaWe
30.07.2019, 13:50
natürlich ist die Idee nicht neu, ich habe preemptives MT sogar schon seit fast 20 Jahren bei Lego RCX, NXT und EV3 benutzt.
Aber bei Arduinos gibt es üblicherweise weder pthread noch std::thread - alles andere ist entweder Murks oder man muss freeRTOS selber implementieren, konfigurieren und compilieren, was extrem kompliziert ist.

Für ESP32 aber ist jetzt std::thread auch in der Arduino IDE verfügbar, und jetzt funktioniert es ja auch! 8)