问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

如何使用Arduino IDE进行ESP32双核编程

创作时间:
作者:
@小白创作中心

如何使用Arduino IDE进行ESP32双核编程

引用
1
来源
1.
https://www.xpstem.com/article/10540

本文将展示如何使用ESP32的两个内核同时执行两个操作。通过利用ESP32的双核特性,可以构建更复杂的应用程序,如实时系统。

ESP模块因其Wi-Fi功能而广受欢迎,例如ESP8266、ESP-12E等。这些都是具有Wi-Fi功能的强大微控制器模块。还有一个ESP模块,它比以前的ESP模块更强大、更通用——它的名字是ESP32。它具有蓝牙和Wi-Fi连接,我们已经解释了ESP32的BLE功能,并在许多物联网项目中使用了ESP32。但很少有人知道ESP32是双核微控制器。

ESP32具有两个32位Tensilica Xtensa LX6微处理器,这使其成为功能强大的双核(core0和core1)微控制器。它有单核和双核两种变体。但双核版本更受欢迎,因为没有明显的价格差异。

ESP32可以使用Arduino IDE、Espressif IDF、Lua RTOS等进行编程。使用Arduino IDE进行编程时,代码只能在Core1上运行,因为Core0已经针对射频通信进行了编程。但这是本教程,我们将展示如何使用ESP32的两个内核同时执行两个操作。这里的第一个任务是闪烁板载LED,第二个任务是从DHT11传感器获取温度数据。

让我们首先看看多核处理器相对于单核的优势。

多核处理器的优势

  • 当有两个以上的进程同时工作时,多核处理器很有用。
  • 由于工作分布在不同的内核之间,它的速度会提高,并且可以同时完成多个进程。
  • 可以降低功耗,因为当任何内核处于空闲模式时,它都可以用来关闭当时未使用的外围设备。
  • 双核处理器必须比单核处理器更少地在不同线程之间切换,因为它们可以一次处理两个而不是一次处理一个。

ESP32和FreeRTOS

ESP32板上已经安装了FreeRTOS固件。FreeRTOS是一个开源实时操作系统,在多任务处理中非常有用。RTOS有助于管理资源和最大化系统性能。FreeRTOS有许多用于不同目的的API函数,使用这些API,我们可以创建任务并使它们在不同的内核上运行。

可以在此处找到FreeRTOS API的完整文档。我们将尝试在代码中使用一些API来构建将在两个内核上运行的多任务应用程序。

查找ESP32内核ID

在这里,我们将使用Arduino IDE将代码上传到ESP32中。要知道运行代码的Core ID,有一个API函数

xPortGetCoreID()

可以从void setup()和void loop()函数调用此函数,以了解运行这些函数的核心ID。您可以通过上传以下草图来测试此API:

setup() { 
  Serial.begin(115200);
  Serial.print("setup() 函数在核心上运行:"); 
  Serial.println(xPortGetCoreID()); 
} 
void loop() { 
  Serial.print("loop() 函数在核心上运行:"); 
  Serial.println(xPortGetCoreID()); 
}

上传上面的草图后,打开串口监视器,你会发现这两个功能都在core1上运行,如下图所示。

从以上观察可以得出结论,默认的Arduino草图始终在core1上运行。

ESP32双核编程

Arduino IDE支持ESP32的FreeRTOS,FreeRTOS API允许我们创建可以在两个内核上独立运行的任务。任务是在板上执行一些操作的代码,例如闪烁的LED、发送温度等。

以下函数用于创建可以在两个内核上运行的任务。在这个函数中,我们必须给出一些参数,比如优先级、核心ID等。

现在,按照以下步骤创建任务和任务功能。

  1. 首先在void setup函数中创建任务。在这里,我们将创建两个任务,一个用于每0.5秒后闪烁LED,另一个任务是每2秒后获取温度读数。

xTaskCreatePinnedToCore()函数有7个参数:

  • 实现任务的函数名(task1)
  • 任务的任何名称(“task1”等)
  • 以字为单位分配给任务的堆栈大小(1个字=2字节)
  • 任务输入参数(可以为NULL)
  • 任务的优先级(0为最低优先级)
  • 任务句柄(可以为NULL)
  • 任务将运行的核心ID(0或1)

现在,通过在xTaskCreatePinnedToCore()函数中提供所有参数来创建用于闪烁LED的Task1。

xTaskCreatePinnedToCore(Task1code, "Task1", 10000, NULL, 1, NULL, 0);

同样,为Task2创建Task2并在第7个参数中设置core id 1。

xTaskCreatePinnedToCore(Task2code, "Task2", 10000, NULL, 1, NULL, 1);

您可以根据任务的复杂性更改优先级和堆栈大小。

  1. 现在,我们将实现Task1code和Task2code函数。这些函数包含所需任务的代码。在我们的例子中,第一个任务将闪烁LED,另一个任务将获取温度。因此,在void setup函数之外为每个任务创建两个单独的函数。

Task1code功能实现了0.5秒后闪烁板载LED,如下所示。

void Task1code(void * parameter) { 
  Serial.print("Task1 在核心上运行"); 
  Serial.println(xPortGetCoreID()); 
  for(;;){//无限循环
    digitalWrite(led, HIGH); 
    delay(500);
    digitalWrite(led, LOW);
    delay(500); 
  } 
}

同样,实现获取温度的Task2code函数。

void Task2code( void * pvParameters ){ 
  Serial.print("Task2 在核心上运行"); 
  Serial.println(xPortGetCoreID()); 
  for(;;){
    float t = dht.readTemperature(); 
    Serial.print("温度:"); 
    Serial.print(t); 
    delay(2000);
  } 
}
  1. 这里的void循环函数将保持为空。我们已经知道循环和设置函数在core1上运行,因此您也可以在void循环函数中实现core1任务。

现在编码部分已经结束,所以只需在工具菜单中选择ESP32板,使用Arduino IDE上传代码。确保您已将DHT11传感器连接到ESP32的引脚D13。

现在可以在Serial Monitor或Arduino IDE上监控结果,如下所示:

通过使用ESP32的双核同时运行多个任务,可以构建像实时系统这样的复杂应用。

#include "DHT.h"
#define DHTPIN 13
#define DHTTYPE DHT11
const int led = 2;
DHT dht(DHTPIN, DHTTYPE);
setup() {
  Serial.begin(115200);
  pinMode(led, OUTPUT);
  dht.begin();
  xTaskCreatePinnedToCore(Task1code, "Task1", 10000, NULL, 1, NULL, 1);
  delay(500);
  xTaskCreatePinnedToCore(Task1code, "Task1", 10000, NULL, 1, NULL, 0);
  delay(500);
}
void Task1code(void * pvParameters ){
  Serial.print("Task1 在核心上运行");
  Serial.println(xPortGetCoreID());
  for(;;){
    digitalWrite(led, HIGH);
    delay(300);
    digitalWrite(led, LOW);
    delay(300);
  }
}
void Task2code(void * pvParameters ){
  Serial.print("Task2 在核心上运行");
  Serial.println(xPortGetCoreID());
  for(;;){
    float h = dht.readHumidity();
    float t = dht.readTemperature();
    float f = dht.readTemperature(true);
    Serial.print("温度:");
    Serial.print(t);
    Serial.print(" *C \n ");
    if (isnan(h) || isnan(t) || isnan(f)) {
      Serial.println("读取 DHT 传感器失败!");
      return;
    }
    delay(2000);
  }
}
loop() {
}
© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号