- Vorteile des Multi-Core-Prozessors
- ESP32 und FreeRTOS
- Suchen der ESP32-Kern-ID
- ESP32 Dual Core Programmierung
ESP-Module sind beliebt für ihre Wi-Fi-Funktionen wie ESP8266, ESP-12E usw. Dies sind alles leistungsstarke Mikrocontroller-Module mit Wi-Fi-Funktionen. Es gibt ein weiteres ESP-Modul, das leistungsfähiger und vielseitiger ist als frühere ESP-Module - es heißt ESP32. Es verfügt über Bluetooth- und Wi-Fi-Konnektivität und wir haben bereits die BLE-Funktionen von ESP32 erläutert und ESP32 in vielen IoT-Projekten verwendet. Nur sehr wenige Menschen wissen, dass ESP32 ein Dual-Core-Mikrocontroller ist.
ESP32 verfügt über zwei 32-Bit-Tensilica Xtensa LX6-Mikroprozessoren, was es zu einem leistungsstarken Dual-Core-Mikrocontroller (Core0 und Core1) macht. Es ist in zwei Varianten Single-Core und Dual-Core erhältlich. Die Dual-Core-Variante ist jedoch beliebter, da es keinen signifikanten Preisunterschied gibt.
ESP32 kann mit Arduino IDE, Espressif IDF, Lua RTOS usw. programmiert werden. Während der Programmierung mit Arduino IDE wird der Code nur auf Core1 ausgeführt, da Core0 bereits für die HF-Kommunikation programmiert ist. In diesem Tutorial wird gezeigt, wie beide Kerne von ESP32 verwendet werden, um zwei Vorgänge gleichzeitig auszuführen. Hier besteht die erste Aufgabe darin, die integrierte LED zu blinken, und die zweite Aufgabe besteht darin, die Temperaturdaten vom DHT11-Sensor abzurufen.
Lassen Sie uns zunächst die Vorteile eines Multi-Core-Prozessors gegenüber einem einzelnen Core sehen.
Vorteile des Multi-Core-Prozessors
- Mehrkernprozessoren sind nützlich, wenn mehr als zwei Prozesse gleichzeitig arbeiten müssen.
- Da die Arbeit auf verschiedene Kerne verteilt wird, erhöht sich ihre Geschwindigkeit und mehrere Prozesse können gleichzeitig abgeschlossen werden.
- Der Stromverbrauch kann reduziert werden, da sich ein Kern im Leerlauf befindet, um die zu diesem Zeitpunkt nicht verwendeten Peripheriegeräte herunterzufahren.
- Dual-Core-Prozessoren müssen seltener zwischen verschiedenen Threads wechseln als Single-Core-Prozessoren, da sie zwei gleichzeitig und nicht jeweils einen verarbeiten können.
ESP32 und FreeRTOS
Auf der ESP32-Karte ist bereits die FreeRTOS-Firmware installiert. FreeRTOS ist ein Open-Source-Echtzeitbetriebssystem, das beim Multitasking sehr nützlich ist. RTOS hilft bei der Verwaltung der Ressourcen und der Maximierung der Systemleistung. FreeRTOS verfügt über viele API-Funktionen für verschiedene Zwecke. Mit diesen APIs können wir Aufgaben erstellen und auf verschiedenen Kernen ausführen.
Eine vollständige Dokumentation der FreeRTOS-APIs finden Sie hier. Wir werden versuchen, einige APIs in unserem Code zu verwenden, um eine Multitasking-Anwendung zu erstellen, die auf beiden Kernen ausgeführt wird.
Suchen der ESP32-Kern-ID
Hier verwenden wir die Arduino IDE, um den Code in ESP32 hochzuladen. Um die Core-ID zu ermitteln, auf der der Code ausgeführt wird, gibt es eine API-Funktion
xPortGetCoreID ()
Diese Funktion kann über die Funktionen void setup () und void loop () aufgerufen werden, um die Kern-ID zu ermitteln, auf der diese Funktionen ausgeführt werden.
Sie können diese API testen, indem Sie die folgende Skizze hochladen:
void setup () { Serial.begin (115200); Serial.print ("setup () -Funktion läuft auf dem Kern:"); Serial.println (xPortGetCoreID ()); } void loop () { Serial.print ("Funktion loop (), die auf dem Kern ausgeführt wird:"); Serial.println (xPortGetCoreID ()); }}
Öffnen Sie nach dem Hochladen der obigen Skizze den seriellen Monitor, und Sie werden feststellen, dass beide Funktionen wie unten gezeigt auf core1 ausgeführt werden.
Aus den obigen Beobachtungen kann geschlossen werden, dass die Standard-Arduino-Skizze immer auf core1 ausgeführt wird.
ESP32 Dual Core Programmierung
Arduino IDE unterstützt FreeRTOS für ESP32 und FreeRTOS APIs ermöglichen es uns, Aufgaben zu erstellen, die unabhängig auf beiden Kernen ausgeführt werden können. Die Aufgabe ist der Code, der einige Vorgänge auf der Platine ausführt, z. B. blinkende LED, Sendetemperatur usw.
Die folgende Funktion wird verwendet, um Aufgaben zu erstellen, die auf beiden Kernen ausgeführt werden können. In dieser Funktion müssen wir einige Argumente wie Priorität, Kern-ID usw. angeben.
Führen Sie nun die folgenden Schritte aus, um eine Aufgabe und eine Aufgabenfunktion zu erstellen.
1. Erstellen Sie zunächst Aufgaben in der Void-Setup- Funktion. Hier erstellen wir zwei Aufgaben, eine zum Blinken der LED alle 0,5 Sekunden und eine andere zum Ablesen der Temperatur alle 2 Sekunden.
Die Funktion xTaskCreatePinnedToCore () akzeptiert 7 Argumente:
- Funktionsname zur Implementierung der Aufgabe (Aufgabe1)
- Beliebiger Name für die Aufgabe ("Aufgabe1" usw.)
- Der Aufgabe zugewiesene Stapelgröße in Worten (1 Wort = 2 Byte)
- Task-Eingabeparameter (kann NULL sein)
- Priorität der Aufgabe (0 ist die niedrigste Priorität)
- Aufgabenhandle (kann NULL sein)
- Kern-ID, unter der die Aufgabe ausgeführt wird (0 oder 1)
Nun erstellen Task1 für blinkt die LED durch alle Argumente in xTaskCreatePinnedToCore () Funktion zu geben.
xTaskCreatePinnedToCore (Task1code, "Task1", 10000, NULL, 1, NULL, 0);
In ähnlicher Weise schaffen Task2 für Task2 und Kern - ID 1 in der 7 machen ten Argument.
xTaskCreatePinnedToCore (Task2code, "Task2", 10000, NULL, 1, NULL, 1);
Sie können die Priorität und die Stapelgröße abhängig von der Komplexität der Aufgabe ändern.
2. Nun implementieren wir die Task1code- und Task2code- Funktionen. Diese Funktionen enthalten den Code für die gewünschte Aufgabe. In unserem Fall blinkt die erste Aufgabe auf der LED und eine andere Aufgabe ruft die Temperatur ab. Erstellen Sie also zwei separate Funktionen für jede Aufgabe außerhalb der Funktion zum Einrichten von Leeren.
Die Task1code- Funktion zum Blinken der LED an Bord nach 0,5 Sekunden ist wie unten gezeigt implementiert.
Void Task1code (void * -Parameter) { Serial.print ("Task1 läuft auf dem Kern"); Serial.println (xPortGetCoreID ()); für (;;) {// Endlosschleife digitalWrite (led, HIGH); Verzögerung (500); digital (LED, LOW), Verzögerung (500); } }
Implementieren Sie auf ähnliche Weise die Task2code- Funktion zum Abrufen der Temperatur.
void Task2code (void * pvParameters) { Serial.print ("Task2 läuft auf dem Kern"); Serial.println (xPortGetCoreID ()); für (;;) { float t = dht.readTemperature (); Serial.print ("Temperatur:"); Serial.print (t); Verzögerung (2000); } }
3. Hier bleibt die Void-Loop- Funktion leer. Da wir bereits wissen, dass die Schleifen- und Setup- Funktion auf core1 ausgeführt wird, können Sie die core1-Task auch in der void-Schleifenfunktion implementieren.
Jetzt ist der Codierungsteil beendet. Laden Sie den Code einfach mit der Arduino IDE hoch, indem Sie im Menü Extras die ESP32-Karte auswählen. Stellen Sie sicher, dass Sie den DHT11-Sensor an Pin D13 des ESP32 angeschlossen haben.
Jetzt können die Ergebnisse auf Serial Monitor oder Arduino IDE wie folgt überwacht werden:
Komplexe Anwendungen wie das Echtzeitsystem können erstellt werden, indem mehrere Aufgaben gleichzeitig mit zwei ESP32-Kernen ausgeführt werden.
Der vollständige Code zusammen mit einem Demo-Video ist unten angegeben.