- Avantatges del processador multi-nucli
- ESP32 i FreeRTOS
- Cerca de l'identificador principal de l'ESP32
- Programació ESP32 Dual Core
Els mòduls ESP són populars per les seves funcions Wi-Fi com ESP8266, ESP-12E, etc. Tots aquests són mòduls de microcontrolador potents amb funcionalitats Wi-Fi. Hi ha un mòdul ESP més potent i versàtil que els mòduls ESP anteriors: el seu nom és ESP32. Té connectivitat Bluetooth i Wi-Fi i ja hem explicat les capacitats BLE d’ESP32 i l’utilitzem en molts projectes IoT. Però molt poca gent sap que ESP32 és un microcontrolador de doble nucli.
ESP32 té dos microprocessadors Tensilica Xtensa LX6 de 32 bits, cosa que el converteix en un potent microcontrolador de doble nucli (core0 i core1). Està disponible en dues variants de nucli únic i de doble nucli. Però la variant de doble nucli és més popular perquè no hi ha diferències de preus significatives.

ESP32 es pot programar mitjançant Arduino IDE, Espressif IDF, Lua RTOS, etc. Mentre es programa amb Arduino IDE, el codi només s'executa en Core1 perquè Core0 ja està programat per a la comunicació RF. Però aquí teniu aquest tutorial que mostrarem com utilitzar els dos nuclis d’ESP32 per realitzar dues operacions simultàniament. Aquí la primera tasca serà parpellejar el LED incorporat i la segona tasca serà obtenir les dades de temperatura del sensor DHT11.
Vegem primer els avantatges d’un processador multi-nucli sobre un sol nucli.
Avantatges del processador multi-nucli
- Els processadors multi-nucli són útils quan hi ha més de 2 processos per treballar simultàniament.
- A mesura que el treball es distribueix entre diferents nuclis, la seva velocitat augmenta i es poden acabar múltiples processos al mateix temps.
- El consum d'energia es pot reduir perquè, quan qualsevol nucli està en mode d'inactivitat, es pot utilitzar per apagar els perifèrics que no s'utilitzen en aquell moment.
- Els processadors de doble nucli han de canviar entre fils diferents amb menys freqüència que els processadors de nucli únic, ja que poden gestionar dos alhora alhora que un a la vegada.
ESP32 i FreeRTOS
La placa ESP32 ja té instal·lat el firmware FreeRTOS. FreeRTOS és un sistema operatiu de codi obert en temps real que és molt útil en multitarea. RTOS ajuda a gestionar els recursos i a maximitzar el rendiment del sistema. FreeRTOS té moltes funcions d'API per a diferents propòsits i, mitjançant aquestes API, podem crear tasques i fer-les executar en diferents nuclis.
Podeu trobar la documentació completa de les API de FreeRTOS aquí. Intentarem utilitzar algunes API del nostre codi per crear una aplicació multitarea que s’executarà als dos nuclis.
Cerca de l'identificador principal de l'ESP32
Aquí utilitzarem Arduino IDE per carregar el codi a ESP32. Per conèixer l'ID bàsic en què s'executa el codi, hi ha una funció API
xPortGetCoreID ()
Aquesta funció es pot cridar des de la funció void setup () i void loop () per conèixer l'identificador central en què s'executen aquestes funcions.
Podeu provar aquesta API carregant l'esbós següent:
configuració nul·la () { Serial.begin (115200); Serial.print (funció "setup () que s'executa al nucli:"); Serial.println (xPortGetCoreID ()); } void loop () { Serial.print ("loop () function running on core:"); Serial.println (xPortGetCoreID ()); }
Després de penjar l’esbós anterior, obriu el monitor de sèrie i trobareu que les dues funcions s’executen a core1 tal com es mostra a continuació.

A partir de les observacions anteriors, es pot concloure que l' esbós Arduino per defecte sempre s'executa a core1.
Programació ESP32 Dual Core
Arduino IDE és compatible amb FreeRTOS per ESP32 i les API FreeRTOS ens permeten crear tasques que poden executar-se independentment en ambdós nuclis. La tasca és la peça de codi que realitza alguna operació a la placa com el LED parpellejant, la temperatura d’enviament, etc.
La funció següent s'utilitza per crear tasques que poden executar-se als dos nuclis. En aquesta funció, hem de donar alguns arguments com una prioritat, identificador bàsic, etc.
Ara, seguiu els passos següents per crear una tasca i una funció de tasca.
1. En primer lloc, creeu tasques a la funció de configuració nul·la . Aquí crearem dues tasques, una per parpellejar el LED després de cada 0,5 segons i una altra tasca és obtenir la lectura de la temperatura cada 2 segons.
La funció xTaskCreatePinnedToCore () té 7 arguments:
- Nom de la funció per implementar la tasca (tasca1)
- Qualsevol nom que es doni a la tasca ("tasca1", etc.)
- Mida de pila assignada a la tasca en paraules (1 paraula = 2bytes)
- Paràmetre d'entrada de tasca (pot ser NUL)
- Prioritat de la tasca (0 és la prioritat més baixa)
- Gestor de tasques (pot ser NUL)
- Identificador principal on s'executarà la tasca (0 o 1)
Ara, creeu Task1 per parpellejar el led proporcionant tots els arguments de la funció xTaskCreatePinnedToCore ().
xTaskCreatePinnedToCore (Task1code, "Task1", 10000, NULL, 1, NULL, 0);
De la mateixa manera, crear Task2 per Task2 i fer Identificació de l'nucli 1 en el 7 º argument.
xTaskCreatePinnedToCore (Task2code, "Task2", 10000, NULL, 1, NULL, 1);
Podeu canviar la prioritat i la mida de la pila en funció de la complexitat de la tasca.
2. Ara, implementarem la funció Task1code i Task2code . Aquestes funcions contenen el codi per a la tasca requerida. En el nostre cas, la primera tasca parpellejarà el led i una altra tasca obtindrà la temperatura. Per tant, feu dues funcions separades per a cada tasca fora de la funció de configuració del buit.
La funció Task1code per parpellejar el LED incorporat després de 0,5 segons s’implementa com es mostra a continuació.
Void Task1code (paràmetre void *) { Serial.print ("Tasca1 que s'executa al nucli"); Serial.println (xPortGetCoreID ()); per a (;;) {// bucle infinit digitalWrite (led, HIGH); retard (500); digitalWrite (LED, LOW); retard (500); } }
De la mateixa manera, implementeu la funció Task2code per obtenir la temperatura.
void Task2code (void * pvParameters) { Serial.print ("Tasca 2 en execució al nucli"); Serial.println (xPortGetCoreID ()); per a (;;) { float t = dht.readTemperature (); Serial.print ("Temperatura:"); Serial.print (t); endarreriment (2000); } }
3. Aquí la funció de bucle buit romandrà buida. Com ja sabem, la funció de bucle i configuració s'executa a core1, de manera que també podeu implementar la tasca core1 a la funció de bucle buit .
Ara la part de codificació s'ha acabat, així que només heu de carregar el codi mitjançant Arduino IDE triant la placa ESP32 al menú Eines. Assegureu-vos que heu connectat el sensor DHT11 al pin D13 de l’ESP32.

Ara es poden controlar els resultats a Serial Monitor o Arduino IDE com es mostra a continuació:

Es poden crear aplicacions complexes com el sistema en temps real executant diverses tasques simultàniament mitjançant nuclis dobles d’ESP32.
A continuació es mostra el codi complet juntament amb un vídeo de demostració.
