【ESP32專欄】善用ESP32雙核心,平行處理提昇效能

作者:尤濬哲(夜市小霸王)

ESP32是一款具有WiFi及低功率藍牙BLE的晶片,相容於Arduino架構,可使用Arduino IDE來開發,不僅程式與Arduino UNO幾乎相同,感測器也完全相容,因此非常適合用來取代現有國、高中UNO的教材。

ESP32腳位定義圖

ESP32雖然擁有兩個核心,不過以平常Arduino的程式寫法都只會用到一個核心,這樣是不是很浪費?我們如何善用增加效能呢?或者如何使用平行處理呢?本篇文章將介紹ESP32的雙核心架構,並分為三個部份解說。

1. 多核心概念

我們常聽到說我的手機有4核心,電腦有8核心,所謂的多核心(Multi-core)簡單的說就是CPU能同時處理較多的任務且不會互相干擾;另外一種虛擬的多核心稱為多執行緒(Thread)則是CPU的分時多工,非本篇的討論範圍。由於ESP32有著240/160MHz的雙核心CPU,因此本篇將要說明是能將任務指定給核心執行的「xTaskCreatePinnedToCore」函數。

ESP32功能方塊圖中可看出它為雙核心架構(Source

雙核心執行有什麼好處?例如可以增加效能,或者平行處理。舉例而言,我們有一個工作是要偵測現場溫濕度並上傳資料庫存檔,每20秒感測上傳一次,假定這項規定很嚴格,必須準時上傳不能有延遲,在以往程式的撰寫流程下,感測與網路上傳是寫在同一個程序內,也就是讀取溫濕度→上傳資料庫→等候20秒,但是上傳資料庫須看網路是否擁塞,假設上傳時間花了3秒,再加上等候20秒後,等於是23秒過了,長久下來就會延遲越來越多。

也許你會想說我們可以將等候時間改成17秒,這樣上傳時間3秒加起來剛好20秒,不過你也知道網路不是那麼好預估,有時候鄰居下載迷片,速度就慢了,而半夜時沒人速度又變得飛快,這樣我們總是沒辦法找到一個時間來補回。

而多核心在這裡就非常適用,也就是一個核心負責讀取溫濕度資料,另外一個核心則將資料送到資料庫,平行處理兩者互不相干,就可以固定總時間不變,而這就是雙核心CPU時的好處。


2. 顯示執行核心

一般我們的程式都僅在ESP32的核心1執行(核心編號1),所以根本沒用到第二個核心(核心編號0),為了證明,我們可以透過xPortGetCoreID()函數來顯示現在使用到哪一個核心,例如我們寫一個簡單的HelloWorld,來測試看看。

上圖可以知道,在未特別指定執行核心前,程序都在核心1中執行,我們稱為單線程,而未使用到另外一個核心,我們拿ThingSpeak的一個範例來演練看看,順便了解執行的時間變化。

為了計算網路傳送的延遲時間,我們可以開啟顯示時間戳記Show timestamp來觀察每次的傳輸時間,我們比較上圖2與3之間的時間差異發現,經過五次的傳送,時間已經慢了約4秒鐘,同時我們觀察執行核心也都是在編號1上執行。

3. 雙核心執行

了解概念後,我們先來實做ESP32多核心的寫法,步驟是這樣的。

1. 宣告任務變數:TaskHandle_t Task1;//宣告Task1任務
2. 設定並執行任務://設定任務
xTaskCreatePinnedToCore(
Task1code, //本任務實際對應的Function
“Task1”, //任務名稱(自行設定)
10000, //所需堆疊空間(常用10000)
NULL, //輸入值
0, //優先序:0代表最優先執行,1次之,以此類推
&Task1, //對應的任務handle變數
0) //指定執行核心編號(0、1或tskNO_AFFINITY:系統指定)

為了測試,我們將原本ThinkSpeak的流程改為多核心架構,核心1執行主流程loop()監控DHT11的溫溼度,將數值存放在公用變數區,並設定上傳旗標=True,核心0執行Task1,主要工作是將資料上傳,當發現上傳旗標=True後就執行上傳,並在完成上傳後修改上傳旗標=False,等待下次任務啟動。

此時我們以上圖方式加入多核心架構後,程式如下:

經由將程式修改為多核心執行後,可以發現,儘管網路會有延遲,但是每次開始傳送的時間都不會相差太多,多次執行後,仍能保持在0.1秒內的誤差。

讀者了解多核心的優點後,可以思考要如何應用在不同的議題上喔。

(作者為本刊共筆作者,其專欄文章同步發表於作者部落格原文連結;責任編輯:王姵文)

尤濬哲

Author: 尤濬哲

身兼助理教授/專欄作家/知名部落客,以及點點滴滴科技研發總監等身份,專長包括人工智慧、多媒體互動(Unity)、智慧互動裝置(APP、Arduino)、虛擬實境與擴增實境互動、IoT 實做開發。 學歷:中山大學資訊管理研究所 博士

Share This Post On

Submit a Comment

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *