• Witaj na Forum Arduino Polska! Zapraszamy do rejestracji!
  • Znajdziesz tutaj wiele informacji na temat hardware / software.
Witaj! Logowanie Rejestracja


Ocena wątku:
  • 0 głosów - średnia: 0
  • 1
  • 2
  • 3
  • 4
  • 5
ESP32 Dual Core watchdogs
#1
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]
Kod:
esp_task_wdt_reset()
[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
 


Załączone pliki Miniatury
   
 
Odpowiedź
#2
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ć.
 
Odpowiedź
#3
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?
 
Odpowiedź
#4
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.
 
Odpowiedź
#5
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?? 
 
Odpowiedź
#6
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".
 
Odpowiedź
#7
Czytam i czytam o FreeRTOS ale to nie dla mnie Wink 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();
}
 
Odpowiedź
#8
No Twój największy błąd to założenie, że mogę Ci w tym pomóc Big Grin. 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ść.
 
Odpowiedź
  


Skocz do:


Przeglądający: 1 gości