- Zalety wielordzeniowego procesora
- ESP32 i FreeRTOS
- Znajdowanie identyfikatora rdzenia ESP32
- Programowanie dwurdzeniowe ESP32
Moduły ESP są popularne ze względu na ich funkcje Wi-Fi, takie jak ESP8266, ESP-12E, itp. Są to potężne moduły mikrokontrolerów z funkcjami Wi-Fi. Jest jeszcze jeden moduł ESP, który jest mocniejszy i bardziej wszechstronny niż poprzednie moduły ESP - jego nazwa to ESP32. Posiada łączność Bluetooth i Wi-Fi, a wyjaśniliśmy już możliwości BLE ESP32 i używaliśmy ESP32 w wielu projektach IoT. Ale bardzo niewiele osób wie, że ESP32 to dwurdzeniowy mikrokontroler.
ESP32 ma dwa 32-bitowe mikroprocesory Tensilica Xtensa LX6, co czyni go potężnym dwurdzeniowym mikrokontrolerem (core0 i core1). Jest dostępny w dwóch wariantach jednordzeniowych i dwurdzeniowych. Ale wariant dwurdzeniowy jest bardziej popularny, ponieważ nie ma znaczącej różnicy w cenie.
ESP32 można zaprogramować za pomocą Arduino IDE, Espressif IDF, Lua RTOS itp. Podczas programowania z Arduino IDE kod działa tylko na Core1, ponieważ Core0 jest już zaprogramowany do komunikacji RF. Ale w tym samouczku pokażemy, jak używać obu rdzeni ESP32 do wykonywania dwóch operacji jednocześnie. Tutaj pierwszym zadaniem będzie miganie wbudowanej diody LED, a drugim będzie pobranie danych temperatury z czujnika DHT11.
Najpierw zobaczmy zalety wielordzeniowego procesora w porównaniu z jednym rdzeniem.
Zalety wielordzeniowego procesora
- Procesory wielordzeniowe są przydatne, gdy jednocześnie działają więcej niż 2 procesy.
- Ponieważ praca jest rozłożona na różne rdzenie, jej prędkość wzrasta i wiele procesów może być zakończonych w tym samym czasie.
- Zużycie energii można zmniejszyć, ponieważ gdy którykolwiek rdzeń jest w trybie bezczynności, można go użyć do wyłączenia urządzeń peryferyjnych, które nie są w tym czasie używane.
- Procesory dwurdzeniowe muszą rzadziej przełączać się między różnymi wątkami niż procesory jednordzeniowe, ponieważ mogą obsługiwać dwa naraz zamiast jednego.
ESP32 i FreeRTOS
Płyta ESP32 ma już zainstalowane oprogramowanie układowe FreeRTOS. FreeRTOS to system operacyjny czasu rzeczywistego typu open source, który jest bardzo przydatny w wielozadaniowości. RTOS pomaga w zarządzaniu zasobami i maksymalizowaniu wydajności systemu. FreeRTOS ma wiele funkcji API do różnych celów i za pomocą tych API możemy tworzyć zadania i uruchamiać je na różnych rdzeniach.
Pełną dokumentację interfejsów FreeRTOS API można znaleźć tutaj. Postaramy się użyć niektórych interfejsów API w naszym kodzie, aby zbudować aplikację wielozadaniową, która będzie działać na obu rdzeniach.
Znajdowanie identyfikatora rdzenia ESP32
Tutaj użyjemy Arduino IDE do przesłania kodu do ESP32. Aby poznać identyfikator rdzenia, na którym działa kod, istnieje funkcja API
xPortGetCoreID ()
Tę funkcję można wywołać z funkcji void setup () i void loop (), aby poznać identyfikator rdzenia, na którym działają te funkcje.
Możesz przetestować ten interfejs API, przesyłając poniższy szkic:
void setup () { Serial.begin (115200); Serial.print (funkcja "setup () działająca na rdzeniu:"); Serial.println (xPortGetCoreID ()); } void loop () { Serial.print (funkcja "loop () działająca na rdzeniu:"); Serial.println (xPortGetCoreID ()); }
Po załadowaniu powyższego szkicu otwórz monitor Serial, a zobaczysz, że obie funkcje działają na core1, jak pokazano poniżej.
Z powyższych obserwacji można wywnioskować, że domyślny szkic Arduino zawsze działa na core1.
Programowanie dwurdzeniowe ESP32
Arduino IDE obsługuje FreeRTOS dla ESP32, a interfejsy API FreeRTOS pozwalają nam tworzyć zadania, które mogą działać niezależnie na obu rdzeniach. Zadaniem jest fragment kodu, który wykonuje pewne operacje na płytce, takie jak miganie diody, wysyłanie temperatury itp.
Poniższa funkcja służy do tworzenia zadań, które mogą działać na obu rdzeniach. W tej funkcji musimy podać kilka argumentów, takich jak priorytet, identyfikator rdzenia itp.
Teraz wykonaj poniższe kroki, aby utworzyć zadanie i funkcję zadania.
1. Najpierw utwórz zadania w funkcji void setup . Tutaj utworzymy dwa zadania, jedno na miganie diody LED co 0,5 sekundy i drugie zadanie to odczyt temperatury co 2 sekundy.
Funkcja xTaskCreatePinnedToCore () przyjmuje 7 argumentów:
- Nazwa funkcji do realizacji zadania (zadanie1)
- Dowolna nazwa nadana zadaniu („zadanie1” itp.)
- Wielkość stosu przydzielona do zadania słownie (1 słowo = 2 bajty)
- Parametr wejściowy zadania (może wynosić NULL)
- Priorytet zadania (0 to najniższy priorytet)
- Uchwyt zadania (może mieć wartość NULL)
- Identyfikator rdzenia, w którym zadanie zostanie uruchomione (0 lub 1)
Teraz utwórz Task1 do migania diody, podając wszystkie argumenty funkcji xTaskCreatePinnedToCore ().
xTaskCreatePinnedToCore (kod_zadania, "zadanie1", 10000, NULL, 1, NULL, 0);
Podobnie, tworzenie Task2 do Task2 i wytwarzania rdzenia ID 1 do 7 th argumentów.
xTaskCreatePinnedToCore (Task2code, "Task2", 10000, NULL, 1, NULL, 1);
Możesz zmienić priorytet i rozmiar stosu w zależności od złożoności zadania.
2. Teraz zaimplementujemy funkcję Task1code i Task2code . Te funkcje zawierają kod wymaganego zadania. W naszym przypadku pierwsze zadanie będzie mrugało diodą a drugie zadanie pobierze temperaturę. Zrób więc dwie osobne funkcje dla każdego zadania poza funkcją konfiguracji pustej przestrzeni.
Funkcja Task1code do migania wbudowanej diody LED po 0,5 sekundy jest zaimplementowana, jak pokazano poniżej.
Void Kod zadania1 (parametr void *) { Serial.print ("Zadanie1 działa na rdzeniu"); Serial.println (xPortGetCoreID ()); for (;;) {// nieskończona pętla digitalWrite (led, WYSOKA); opóźnienie (500); digitalWrite (LED, LOW) opóźnienia (500); } }
Podobnie, zaimplementuj funkcję Task2code do pobierania temperatury.
void Task2code (void * pvParameters) { Serial.print ("Task2 działa na rdzeniu"); Serial.println (xPortGetCoreID ()); for (;;) { float t = dht.readTemperature (); Serial.print ("Temperatura:"); Serial.print (t); opóźnienie (2000); } }
3. Tutaj funkcja void loop pozostanie pusta. Jak już wiemy, funkcja pętli i konfiguracji działa na rdzeniu1, więc można również zaimplementować zadanie core1 w funkcji pętli pustej .
Teraz część kodowania się skończyła, więc po prostu prześlij kod za pomocą Arduino IDE, wybierając kartę ESP32 w menu Narzędzia. Upewnij się, że podłączyłeś czujnik DHT11 do styku D13 ESP32.
Teraz wyniki można monitorować na Serial Monitor lub Arduino IDE, jak pokazano poniżej:
Złożone aplikacje, takie jak system czasu rzeczywistego, można budować, uruchamiając wiele zadań jednocześnie przy użyciu dwóch rdzeni ESP32.
Pełny kod wraz z filmem demonstracyjnym znajduje się poniżej.