- Avantages du processeur multicœur
- ESP32 et FreeRTOS
- Recherche de l'ID de noyau ESP32
- Programmation ESP32 Dual Core
Les modules ESP sont populaires pour leurs fonctionnalités Wi-Fi comme ESP8266, ESP-12E, etc. Ce sont tous des modules microcontrôleurs puissants avec des fonctionnalités Wi-Fi. Il existe un module ESP de plus qui est plus puissant et polyvalent que les modules ESP précédents - son nom est ESP32. Il dispose d'une connectivité Bluetooth et Wi-Fi et nous avons déjà expliqué les capacités BLE d'ESP32 et utilisé ESP32 dans de nombreux projets IoT. Mais très peu de gens savent que l' ESP32 est un microcontrôleur Dual-core.
L'ESP32 possède deux microprocesseurs Tensilica Xtensa LX6 32 bits, ce qui en fait un puissant microcontrôleur double cœur (core0 et core1). Il est disponible en deux variantes single-core et dual-core. Mais la variante dual-core est plus populaire car il n'y a pas de différence de prix significative.
ESP32 peut être programmé en utilisant Arduino IDE, Espressif IDF, Lua RTOS, etc. Lors de la programmation avec Arduino IDE, le code ne fonctionne que sur Core1 car Core0 est déjà programmé pour la communication RF. Mais voici ce tutoriel, nous allons montrer comment utiliser les deux cœurs d'ESP32 pour effectuer deux opérations simultanément. Ici, la première tâche sera de faire clignoter la LED embarquée et la deuxième tâche sera de récupérer les données de température du capteur DHT11.
Voyons d'abord les avantages d'un processeur multicœur par rapport à un seul cœur.
Avantages du processeur multicœur
- Les processeurs multicœurs sont utiles lorsqu'il y a plus de 2 processus à travailler simultanément.
- Le travail étant réparti entre différents cœurs, sa vitesse augmente et plusieurs processus peuvent être terminés en même temps.
- La consommation d'énergie peut être réduite car, lorsqu'un cœur est en mode veille, il peut être utilisé pour arrêter les périphériques qui ne sont pas utilisés à ce moment-là.
- Les processeurs double cœur doivent basculer entre les différents threads moins souvent que les processeurs monocœur car ils peuvent en gérer deux à la fois au lieu d'un à la fois.
ESP32 et FreeRTOS
Le micrologiciel FreeRTOS est déjà installé sur la carte ESP32. FreeRTOS est un système d'exploitation en temps réel open-source qui est très utile en multitâche. RTOS aide à gérer les ressources et à maximiser les performances du système. FreeRTOS a de nombreuses fonctions API à des fins différentes et en utilisant ces API, nous pouvons créer des tâches et les faire fonctionner sur différents cœurs.
La documentation complète des API FreeRTOS peut être trouvée ici. Nous allons essayer d'utiliser certaines API dans notre code pour créer une application multitâche qui fonctionnera sur les deux cœurs.
Recherche de l'ID de noyau ESP32
Ici, nous utiliserons Arduino IDE pour télécharger le code dans ESP32. Pour connaître le Core ID sur lequel le code s'exécute, il existe une fonction API
xPortGetCoreID ()
Cette fonction peut être appelée depuis la fonction void setup () et void loop () pour connaître l'ID de base sur lequel ces fonctions sont exécutées.
Vous pouvez tester cette API en téléchargeant le croquis ci-dessous:
void setup () { Serial.begin (115200); Serial.print ("fonction setup () s'exécutant sur le noyau:"); Serial.println (xPortGetCoreID ()); } void loop () { Serial.print ("fonction loop () s'exécutant sur le noyau:"); Serial.println (xPortGetCoreID ()); }
Après avoir téléchargé le croquis ci-dessus, ouvrez le moniteur série et vous constaterez que les deux fonctions s'exécutent sur core1, comme indiqué ci-dessous.
À partir des observations ci-dessus, on peut conclure que l' esquisse Arduino par défaut fonctionne toujours sur core1.
Programmation ESP32 Dual Core
Arduino IDE prend en charge FreeRTOS pour ESP32 et les API FreeRTOS nous permettent de créer des tâches pouvant s'exécuter indépendamment sur les deux cœurs. La tâche est le morceau de code qui effectue certaines opérations sur la carte comme le clignotement de la LED, l'envoi de la température, etc.
La fonction ci-dessous est utilisée pour créer des tâches qui peuvent s'exécuter sur les deux cœurs. Dans cette fonction, nous devons donner des arguments comme une priorité, un identifiant de base, etc.
Maintenant, suivez les étapes ci-dessous pour créer une tâche et une fonction de tâche.
1. Commencez par créer des tâches dans la fonction de configuration d' annulation. Ici, nous allons créer deux tâches, une pour le clignotement de la LED toutes les 0,5 seconde et une autre tâche consiste à obtenir la lecture de la température toutes les 2 secondes.
La fonction xTaskCreatePinnedToCore () prend 7 arguments:
- Nom de la fonction pour implémenter la tâche (tâche1)
- Tout nom donné à la tâche («tâche1», etc.)
- Taille de la pile allouée à la tâche en mots (1 mot = 2 octets)
- Paramètre d'entrée de tâche (peut être NULL)
- Priorité de la tâche (0 est la priorité la plus basse)
- Handle de tâche (peut être NULL)
- ID de base où la tâche sera exécutée (0 ou 1)
Maintenant, créez Task1 pour faire clignoter la led en donnant tous les arguments dans la fonction xTaskCreatePinnedToCore ().
xTaskCreatePinnedToCore (Task1code, "Task1", 10000, NULL, 1, NULL, 0);
De même, créez Task2 pour Task2 et définissez le core id 1 dans le 7 e argument.
xTaskCreatePinnedToCore (Task2code, "Task2", 10000, NULL, 1, NULL, 1);
Vous pouvez modifier la priorité et la taille de la pile en fonction de la complexité de la tâche.
2. Maintenant, nous allons implémenter la fonction Task1code et Task2code . Ces fonctions contiennent le code de la tâche requise. Dans notre cas, la première tâche fera clignoter la led et une autre tâche va chercher la température. Créez donc deux fonctions distinctes pour chaque tâche en dehors de la fonction de configuration des annulations.
La fonction Task1code pour le clignotement de la LED intégrée après 0,5 seconde est implémentée comme indiqué ci-dessous.
Void Task1code (void * parameter) { Serial.print ("Task1 running on core"); Serial.println (xPortGetCoreID ()); for (;;) {// boucle infinie digitalWrite (led, HIGH); retard (500); digitalWrite (led, LOW); retard (500); } }
De même, implémentez la fonction Task2code pour récupérer la température.
void Task2code (void * pvParameters) { Serial.print ("Task2 s'exécutant sur le cœur"); Serial.println (xPortGetCoreID ()); pour (;;) { float t = dht.readTemperature (); Serial.print ("Température:"); Serial.print (t); retard (2000); } }
3. Ici, la fonction de boucle vide restera vide. Comme nous le savons déjà , la fonction de boucle et de configuration s'exécute sur core1, vous pouvez donc implémenter la tâche core1 dans la fonction de boucle vide également.
Maintenant que la partie de codage est terminée, téléchargez simplement le code à l'aide de l'IDE Arduino en choisissant la carte ESP32 dans le menu Outils. Vérifiez que vous avez connecté le capteur DHT11 à la broche D13 de l'ESP32.
Maintenant, les résultats peuvent être surveillés sur Serial Monitor ou Arduino IDE comme indiqué ci-dessous:
Des applications complexes telles que le système en temps réel peuvent être créées en exécutant plusieurs tâches simultanément à l'aide de deux cœurs d'ESP32.
Le code complet avec une vidéo de démonstration est donné ci-dessous.