Zrobiłem sobie program testowy na razie i przyszło mi do głowy by wykorzystać dwa rdzenie bo co drugi będzie sobie odpoczywał.. Arduino standardowo wykorzystuje tylko 2 rdzeń pierwszy odpoczywa
Zastosowałem się do przykłądu:
https://randomnerdtutorials.com/esp32-du...duino-ide/
Ten przykład działa, ale jak pousuwam "
delay" w pętlach "
Kod:
void Task1code( void * pvParameters ){
for(;;){
digitalWrite(led1, HIGH);
digitalWrite(led1, LOW);
}
}
void Task2code( void * pvParameters ){
for(;;){
digitalWrite(led2, HIGH);
digitalWrite(led2, LOW);
}
}
Ze względu że core 0 jest obciązony 100% nie ma czasu na funkcję "watchdogs" czytałem czytałem i głowa już boli.
I gdy dam "delay" w przykładzie i w moim kodzie
Kod:
void Task1code( void * pvParameters ){
for(;;){
digitalWrite(led1, HIGH);
digitalWrite(led1, LOW);
delay (10);
}
}
Ma czas na watchdogs.. I jest ok ale tak czytam jeszcze to:
https://docs.espressif.com/projects/esp-.../wdts.html
To dobrze tam rozumię że wystarczy w kodzie umieścić [/url]
[url=https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/system/wdts.html#_CPPv318esp_task_wdt_resetv]
I będzie resetowało watchdoga?? i nie będzie błędu
Nie tyle chodzi o to by WDT zresetować co dać czas głównemu rdzeniowi czas na obsługę WIFI czy tam tego co normalnie robi sobie ESP w między czasie. Może być też "delay(0)", oczywiście nie będzie trwał 0 tylko tyle ile tamte procesy wymagają. Może też być funkcja yield();. W ESP8266 robił to na pewno też sam w funkcji loop(), po prostu pętla nie mogła trwać dłużej niż okres WDT i od czasu do czasu trzeba było dorzucić delay(0) lub yield() - to podobno to samo.
Wstaw sobie ten WDT reset i sprawdź, ja bym tam nie grzebał bez potrzeby, nie wiem aż tak dobrze co tam ma się robić.
Dzięki na namiar nie sądziłem że to chodzi też o Wifi myślałem że tylko o funkcję WDT
Jest jakaś możliwość by sprawdzić obliczyć ile potrzebuje czasu na inne swoje zadania?
To zależy co tam się dzieje z WIFI. No i ten WDT też powinien być resetowany w dobrze wybranym miejscu, jest właśnie po to, że jak wejdziesz w funkcję, która z powodu błędu zablokuje uC to ma go zresetować. Do oszacowania ile to trwa można wziąć oscyloskop, ustawić jakiś pin na 0, potem na 1, wpisać delay(0), ustawić pin na 0 i zmierzyć ile trwają te delay(0) na pinie.
Delay(0) nie działa wsumie nie ma prawa działać biorąc poniższy kod dla usług działających w tle z biblioteki esp:
Kod:
void delay(unsigned long ms)
{
uint32_t start = micros();
while (ms > 0) {
yield();
while ( ms > 0 && (micros() - start) >= 1000) {
ms--;
start += 1000;
}
}
}
Wychodzi że musi być minimum delay(1); i z takim też działa.
A funkcja
yield(); musi być z czasem samo funkcja tylko sie odnosi do przekazania na usługi działające w tle ale bez czasu nic nie zrobi..
Mam pytanie czy idzie jakoś podejrzeć zapełnienie stosu Wifi??
No widzisz, kiedyś też wrzuciłem kod z delay(1) jako rozwiązanie problemu i zostałem poinformowany, że delay(0) wystarczy. I faktycznie tak było dla ESP8266, chodziło o pętlę while(1); użytą by na spokojnie zobaczyć wyniki obliczeń w monitorze portu. W ESP32 na core1 w ogóle tym nie trzeba się było martwić. Może zmienili funkcję delay. W ogóle oglądałem przykład w szkicach o WDT i trochę mnie rozczarował. Nauczyłem się, że w AVR jest to osobny sprzęt (no też nie zawsze musi zadziałać dobrze, widziałem próby resetowania WDT w przerwaniach), który działa zupełnie niezależnie od programu. W ESP32 po prostu była zrobiona funkcja w timerze, która sobie sprawdzała stan zmiennej i jeśli ta przekroczyła stan licznika to funkcja przerwania wywoływała funkcję do resetu.
Twój problem polega pewnie na tym, że są dwa timery w ESP32 powiązane z WDT:
https://community.hiveeyes.org/t/esp32-m...wdt/1554/2, może z komunikatu odczytasz o który chodzi. Zapewne procka resetuje ten, który kontroluje czy taski są przełączane.
Samo yield() też nie wystarcza, może trzeba mieć większego kija do stukania w ESP32?
No ciekawe pytanie o stos WIFI, chciałbym je umieć zrozumieć. Pewnie bez pytania do Igrr'a się nie dowiesz
https://github.com/espressif/arduino-esp32/issues . Ja wiem tylko tyle, że część użytych źródeł pochodzi od Espressif jako skompilowane gotowce, zawartość nie jest znana i są poruszane różne teorie spiskowe co Chińczycy przemycają poniżej kosztów produkcji do EU. Natomiast zastanawiam się czy nie chodzi bardziej o to, że w ESP jest użyty FreeRTOS ( o którym prawie nic nie wiem) i jak chcesz lepiej wiedzieć co się dzieje w ESP32 to pewnie z nim się powinieneś poznać, bo WIFI niekoniecznie musi być używane, a skoro go nie ma w kodzie Arduino to może nie ma i jego stosu. Więc te delaye są potrzebne bardziej do tego: "czy tam tego co normalnie robi sobie ESP w między czasie".
Czytam i czytam o FreeRTOS ale to nie dla mnie
ja dopiero początkujący ledwo ogarniam arduino podstawy a gdzie zajmować się wielowątkowością.
Ze względu że chciałem tylko aby na Core1 był mniejszy kod który pisze szybszy i będę dopisywał wiec trochę przerzucić na Core0 bo po co się ma nudzić skoro jest no ale on mi fiksował bo na nim jest WDT jak i obsługa stosu Wifi , nie wiem czy skojarzysz jak sie kiedyś pytałem o kolejność loop? (przepis itd.). Wiec wykorzystałem to że już tak pisałem (definicje funkcji) i było podzielone wiec utworzyłem zadania ich wywołanie "xTaskCreatePinnedToCore" jest możliwość przypisania tego "przepisu" gdzie ma sie wykonać i funkcja vTaskDelay() określam co ile ten przepis ma się wykonywać
Ten void loop() to jest po staremu jak było bez FreeRTOS
Myślałem pierw o jednym zadaniu na Core0 (tak jak mam na Core1) i dać minimalny zakres vTaskDelay dla wszystkich ale niektóre nie potrzebują tak częstego powtarzania.
Jak myślisz sporo w tym błędów??
Jeszcze może wiesz czy lepiej zapis do UDP wykonywać na jednym rdzeniu czy może być na dwóch? bo mam obawy czy zapis do UDP z core0 nie zakłuć zapis do UDP core1 gdy czasowo się pokryją.
Ale jeszcze zmienię bo wyczytałem że vTaskDelayUntil jest dokładniejsze niż vTaskDelay
Kod:
xTaskCreatePinnedToCore( WiFi_conect_Core_0, "CPU_0", 10000, NULL, 1, &CPU_0, 0);
xTaskCreatePinnedToCore( AC_data_Core_0, "CPU_0", 10000, NULL, 1, &CPU_0, 0);
xTaskCreatePinnedToCore(
Core_1, /* Task function. */
"CPU_1", /* name of task. */
10000, /* Stack size of task */
NULL, /* parameter of the task */
1, /* priority of the task */
&CPU_1, /* Task handle to keep track of created task */
1); /* pin task to core 1 */
}
void WiFi_conect_Core_0 ( void * pvParameters ){
for(;;){
WiFi_conect();
// AC_data();
vTaskDelay(1000);
}
}
void AC_data_Core_0 ( void * pvParameters ){
for(;;){
// WiFi_conect();
AC_data();
vTaskDelay(50);
}
}
void Core_1( void * pvParameters ){
for(;;){
recvWithEndMarker(); // loop odczytu z Serial2
showNewData(); // loop zapisu serial2 do UDP
showUdpData(); // loop odczytu udp i zapisu do Serial2
AC_data_send();
nexLoop(nex_listen_list); // loop wyswietlacza Nextion
}
}
void loop () {
// WiFi_conect();
// nexLoop(nex_listen_list); // loop wyswietlacza Nextion
// recvWithEndMarker(); // loop odczytu z Serial2
// showNewData(); // loop zapisu serial2 do UDP
// showUdpData(); // loop odczytu udp i zapisu do Serial2
// AC_data();
// AC_data_send();
}
No Twój największy błąd to założenie, że mogę Ci w tym pomóc
. Nic ciekawego z tymi prockami nie robię, to tylko zabawa. Widocznie dobrze ściemniam, ale jak byś zajrzał w moje karty przez ramię to nie ma tu żadnych figur. Mi wystarcza to co daje Arduino w przykładach i zamykam temat z funkcją millis() by zapewnić pseudo wielowątkowość.