sei doch bitte so nett und schreib das mal komplett als thread, nicht dass ich es falsch versteh und dann nur Mist raus
kommt.
Druckbare Version
sei doch bitte so nett und schreib das mal komplett als thread, nicht dass ich es falsch versteh und dann nur Mist raus
kommt.
ich habe mal noch explizit die Variablen getrennt um irgendwelche Phänomene auszuschließenCode: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());
}
}
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...:
Code:// 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);
}
- - - Aktualisiert - - -Zitat:
Code: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
lad dir doch mal ne "portable" Arduino IDE herunter... ;)
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
update: der Code jetzt hier scheint besser zu laufen:
code:Zitat:
Code:> 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:
Code: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);
}
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:
Code: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)
update:
mutex ist doch drin, braucht nur zusätzlich
was ich nicht wusste,Code:#include <mutex>
dann klappt jetzt auch
Code:std::mutex print_mutex;
void myPrint(String str) // String: Arduino API // C++: std::string
{
print_mutex.lock();
Serial.println(str);
print_mutex.unlock();
}
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!!):
funktioniert nicht, weil anfangs cfg noch keine Werte enthält und daher einen Fehler zurückgibt,Code:esp_pthread_cfg_t cfg;
esp_pthread_get_cfg(&cfg);
cfg.prio=1;
esp_pthread_set_cfg(&cfg);
und
funktioniert auch nicht, weil die hier verwendete FunktionCode: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();
};
esp_pthread_get_default_config();
nicht gefunden wird.
siehe Topic-Posts u.a.
https://github.com/espressif/ESP8266...SDK/issues/609
https://github.com/espressif/esp-idf...ment-496157019
und folgende...
betroffene libs am ehesten wohl
https://github.com/espressif/ESP8266...ts/pthread/src
Hat jemand eine idee, wie es richtig geht?
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