ESP32 晶片內部有兩個處理器:「32 位元雙核心處理器」和「8 位元低功耗處理器(簡稱:ULP)」。其中 ESP32 主處理器的兩個核心分別叫做 PRO_CPU 和 APP_CPU:
- PRO_CPU:代表 Protocol CPU,負責處理和操控 WiFi、藍芽和其他介面(I2C、SPI...等)。
- APP_CPU:代表 Application CPU,執行主程式碼。
規格比較
型號 | ESP32 | ESP8266 |
---|---|---|
處理器 | Xtensa 雙核心或單核心 32 位元 LX6 | Xtensa 單核心 32 位元 L106 |
工作時脈 | 160/240 MHz | 80 MHz |
協同處理器 | ULP | 無 |
SRAM 主記憶體 | 520 KB | 120 KB |
外部 Flash 快閃記憶體 | 最高支援 16MB | 最高支援 16 MB |
RTC(即時鐘)記憶體 | 16 KB | 無 |
WiFi | 2.4 GHz 頻段的 802.11 b/g/n | 2.4 GHz 頻段的 802.11 b/g/n |
藍芽 | 4.2 版 BR/EDR/BLE | 無 |
乙太網路 | 10/100 Mbps | 無 |
CAN 介面 ① | 2.0 | 無 |
GPIO | 34 | 16 |
UART 序列埠 | 3 | 1.5(其中一組僅有傳送腳) |
I2C 介面 | 2 | 1 |
I2S 介面 | 2 | 2 |
SPI 介面 | 4 | 2 |
ADC(類比轉數位) | 18 個(12 位元),最大輸入電壓 3.6V | 1 個(10 位元),最大輸入電壓 1.1V |
DAC(數位轉類比) | 2個(8 位元) | 2個(8 位元) |
PWM 輸出 | 16 | 8 |
觸控介面 | 10 | 無 |
溫度感測器 | 有,用於測量晶片溫度 | 無 |
霍爾感測器 | 有,用於檢測磁力變化 | 無 |
安全性 | 安全啟動 Flash 加密 1024 OTP | 無 |
加密(crypto) | AES、SHA-2、RSA、ECC、ENG | 無 |
功耗 | 深度睡眠 10 uA | 深度睡眠 2 uA |
訊較多的場所。
ESP32 圖例
NodeMCU-32S
NodeMCU-32S Pins MAP
ESP32的功能接腳與限制
- Serial:
硬體接腳 UART 0:TX(GPIO1)、RX(GPIO3)
硬體接腳 UART 1:TX(GPIO9)、RX(GPIO10) ②
硬體接腳 UART 2:TX(GPIO17)、RX(GPIO16)
軟體模擬接腳:事實上,ESP32 軟體模擬序列埠,可以使用在任意接腳,其宣告語法為「Seria2.begin(9600,SERIAL_8N1,18,19)」,其中:
Serial2:類別變數名
9600:鮑率
SERIAL_8N1:代表沒有同位檢查
18:GPIO18 為 RX
19:GPIO19 為 TX - I2C:
SDA:GPIO22
SCL:GPIO21 - SPI:
CLK:GPIO14
MISO:GPIO12
MOSI:GPIO13
SS:GPIO15 - VSPI:
SCK:GPIO18
MISO:GPIO19
MOSI:GPIO23
SS:GPIO5 - 接腳的限制:
(1)接腳的最大輸入電壓為 3.6V
(2)不支援上拉電阻(INPUT_PULLUP)的接腳:32、35、34、39、36
(3)不支援下拉電阻(INPUT_PULLDOWN)的接腳:0、1、2、3
(4)接腳 34、35、36、39 只支援輸入
(5)接腳 0、5、14、15 不建議設為 INPUT
(6)接腳 1、3、12 不建議設為 OUTPUT
(7)接腳 CLK、SD0、SD1、SD3、CMD 用於上傳程式至晶片,不能使用
(8)接腳定額的電流為 6mA,最大電流為 12mA
RX(GPIO9)、TX(GPIO10)無法使用程式控制,是專門用來與記憶體溝通的接腳
ESP32 的 printf() 格式化輸出
雖然 Arduino 不支援 printf(),但基於 ESP-IDF 工具的 ESP32 跟 C 語言一樣,可以支援這個萬用的格式化輸出工具。
符號 | 說明 |
---|---|
%c | 單一字元(char) |
%s | 字串(string) |
%u | 無正負號(unsigned)整數 |
%d | 整數(integer) |
%lu | 無正負長整數(unsigned long) |
%ld | 長整數(long) |
%x | 16 進位(hexadecimal)整數 |
%f | 浮點數(float),輸出全部整數部分,6 位小數部分,超過 6 位則四捨五入 |
%.nf | 輸出小數點後 n 位數字的浮點數,請留意 n 前面有個點「.」。例如:3.14159 用 %.3f 輸出為 3.142 |
%% | 顯示 % |
數位輸出/輸入
接觸新的開發板時,最先要留意的是它的工作電壓規格。
ESP32 開發版的工作電壓(VDD)是 3.3V。 數位及類比腳的最大容許輸入電壓是 VDD+0.3V,也就是 3.6V。
pinMode(pin,mode);
mode 可能的值:
- INPUT:當接腳設成「數位輸入」時,部分接腳會因以下的事件而不建議使用。
(1) TX(GPIO1)連接 USB 埠,開機時會輸出除錯訊息。
(3) RX(GPIO1)連接 USB 埠,開機時會處於高電位狀態。
(12) GPIO1 開機時須維持在低電為,否則不能開機。
- OUTPUT:當接腳設成「數位輸出」時,部分接腳會因以下的事件而不建議使用。
(1) GPIO0、GPIO5、GPIO14、GPIO15 開機時會輸出短暫 PWM 訊號,不建議使用。
(1) GPIO1、GPIO3 連接 USB 埠。
(1) GPIO34、GPIO35、GPIO36、GPIO39 僅具備數位輸入功能。
- INPUT_PULLUP:GPIO32~GPIO39 不具備上拉電阻之功能。
- INPUT_PULLDOWN:GPIO0~GPIO3 不具備下拉電阻之功能。
讀取電容觸控接腳
ESP32 有 10 個接腳具備電容觸控感應功能,可以當除觸控開關,觸控腳的感測值是類比值,會因接線形式(觸控面積大小)、距離等因素而不同。讀取觸控感測值的語法為:
int touchValue(pin);
可使用的觸控接腳如下表:T0(GPIO4) | T1(GPIO0) | T2(GPIO2) | T3(GPIO5) | T4(GPIO13) |
T5(GPIO12) | T6(GPIO14) | T7(GPIO27) | T8(GPIO33) | T9(GPIO32) |
範例:底下程式將在使用者碰接腳 T3(GPIO15)時,會點亮開發版內建的 LED。
#include LED LED_BUILTIN const byte touchPin = 15; const int thresHold = 20; int touchValue ; void setup() { pinMode(LED_BUILTIN, OUTPUT); } void loop() { touchValue = touchRead(touchPin); if(touchValue < thresHold) { digitalWrite(LED, LOW); } else { digitalWrite(LED, HIGH); } delay(1000); }
程式的執行效果:
ESP32 的類比輸入
ESP32 類比輸入電壓的上限是 3.6V,正常最高值為 3.3V,讀取類比輸入值的指令同樣是 analogRead(),接腳可用 A0(GPIO36)、A3(GPIO39)、A4(GPIO32)、A5(GPIO33)、A6(GPIO34)、A7(GPIO35) 等編號。
Arduino UNO 的類比數位轉換器(ADC)採 10 位元取藥,所以量化值介於 0~1023,ESP32 的 ADC 預設採 12 位元取樣,量化值介於 0~4095。
設定 ESP32 的 ADC 類比輸入電壓範圍與取樣位元的方法:
- analogSetAttenuation(衰減值):其中衰減值可能為
- ADC_0db:0db 衰減,電壓輸入上限為 1.00V。
- ADC_2_5db:2.5db 衰減,電壓輸入上限為 1.34V。
- ADC_6db:6db 衰減,電壓輸入上限為 2.00V。
- ADC_11db:11db 衰減,電壓輸入上限為 3.6V。
- analogSetWidth(寬度):設定 ADC 的取樣位元
- analogSetWidth(9):取樣寬度為 0~511。
- analogSetWidth(10):取樣寬度為 0~1023。
- analogSetWidth(12):取樣寬度為 0~4095。
- analogRead(pin)::可用的類比輸入接腳為
- A0:GPIO36,只有輸入功能。
- A3:GPIO39,只有輸入功能。
- A6:GPIO34,只有輸入功能。
- A7:GPIO35,只有輸入功能。
- A4:GPIO32。
- A5:GPIO33。
由於 ESP32 類比輸入的最高電壓是 3.6V,但如果類比感測器的輸出電壓是 5V,直接將感測器 5V 的輸出接到 ESP32 的類比輸入接腳,很可能會造成 ESP32 的損壞,所以我們需要將 5V 轉為 3V3。
透過右圖的接線方式,我們可以順利達成這個目標。
ESP32 內建的霍爾感應器
ESP32 晶片內建一個可以偵測磁場變化的「霍爾效應③」感測器,霍爾感測器的輸出電壓和磁場的強度與距離成正比。
霍爾感測器普遍應用在檢測物體移動、馬達轉速、開闔等。例如:無刷馬達的轉子包覆著磁石,在馬達內部裝設霍爾感測器,透過偵測磁石南北極的變化便可以測量馬達的轉速。在手機、平板電腦內部裝設霍爾感測器,同時在保護蓋說這一個磁石,便可以達成偵測保護蓋開闔的動作。
會因受力而偏向一邊,繼而產生電壓。
讀取霍爾感測值的函式叫做 hallRead(),它將傳回帶正負號的整數值。
ESP32 的類比輸出
ESP32 的 PWM 解析度不是固定值,而是跟頻率設定息息相關,根據樂鑫公司的 ESP32 官方技術文件(http://bit.ly/39wGPa5)指出:PWM 解析度隨著頻率提高而降低,解析度範圍介於 1~16 位元,頻率上限為 40MHz,解析度的計算公式請參考下圖。
設定 ESP32 的 PWM 輸出指令
設置 ESP32 的 PWM 輸出、頻率,須透過兩個函式來達成,韓式名字開頭的 ledc 代表 LED Control(LED 控制,簡稱 LEDC)。
- ledcSetup(通道,頻率,解析度):設置 PWM 產生器
- ledcAttachPin(接腳編號,通道)
通道相當於 PWM 產生器,ESP32 內部共有 16 個 PWM 通道(0~15),每個通道的輸出都可設定給任一個數位輸出接腳。所以 ESP32 最多同時擁有 16 個 PWM 輸出腳。PWM 設定完畢,就可以執行 ledcWrite() 輸出 PWM 訊號。
- ledcWrite(通道,PWM 輸出):參閱以下範例
ledcSetup(0,5000,10); //--- 為通道 0 設定一個 5KHz、10 位元取樣頻率的 PWM 產生器 ledcAttachPin(5,10); //--- 把 GPIO5 指定給通道 0 使用 ledcWrite(0,614); //--- 在通道 0 輸出 614 的 PWM 訊號
利用 PWM 輸出完成調光器
實驗電路:利用一個 10K 的便電阻連接在 A4 接腳,接線示範圖如下
程式碼如下:
#define BITS 10 void setup() { pinMode(LED_BUILTIN,OUTPUT); analogSetAttenuation(ADC_11db); analogSetWidth(BITS); ledcSetup(0,5000,BITS); ledcAttachPin(LED_BUILTIN,0); } void loop() { int val=1023-analogRead(A4); ledcWrite(0,val); }
調控 PWM 訊號的頻率發出聲音
ESP32 不支援 Arduino 的 tone() 函式,但 Arduino 的 tone() 本質上是用 PWM 來調控輸出波形(聲音)的頻率,所以 ESP32 也同樣可以用 PWM 訊號來驅動發音元件。透過改變訊號的「工作週期」來調整輸出電壓,以達成在揚聲器上發出不同音高的聲音。
在 ESP32 上改變 PWM 頻率的函式語法:
- ledcWriteTone(通道,頻率);
- ledcWriteNote(通道,音名常數,音階編號);
音名、音階編號與頻率的對應表:
音名 | 音名常數 | 音階編號 | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | ||
C | NOTE_C | 16 | 33 | 65 | 131 | 262 | 523 | 1046 | 2093 | 4186 |
C# | NOTE_Cs | 17 | 35 | 69 | 139 | 277 | 554 | 1109 | 2217 | 4435 |
D | NOTE_D | 18 | 37 | 73 | 147 | 294 | 587 | 1175 | 2349 | 4699 |
D# | NOTE_Eb | 19 | 39 | 78 | 156 | 311 | 622 | 1245 | 2489 | 4978 |
E | NOTE_E | 21 | 41 | 82 | 165 | 330 | 659 | 1319 | 2637 | 5274 |
F | NOTE_F | 22 | 44 | 87 | 175 | 349 | 698 | 1397 | 2794 | 5588 |
F# | NOTE_Fs | 23 | 46 | 93 | 185 | 370 | 740 | 1480 | 2960 | 5920 |
G | NOTE_G | 25 | 49 | 98 | 196 | 392 | 784 | 1568 | 3136 | 6272 |
G# | NOTE_Gs | 26 | 52 | 104 | 208 | 415 | 831 | 1661 | 3322 | 6645 |
A | NOTE_A | 28 | 55 | 110 | 220 | 440 | 880 | 1760 | 3520 | 7040 |
A# | NOTE_Bb | 29 | 58 | 117 | 233 | 466 | 932 | 1864 | 3729 | 7459 |
B | NOTE_Bb | 31 | 62 | 123 | 247 | 493 | 988 | 1976 | 3951 | 7902 |
下面的兩行程式碼都可以在通道 0 產生中央 C 音:
ledcWriteTone(0,262); //--- 在通道 0 產生 262Hz 的頻率 ledcWriteNote(0,NOTE_C,4)
另,Arduino 有個停止音頻輸出的 noTone(); 函式,在 ESP32 中可用底下這行敘述達成:
ledcWriteTone(0,0); //--- 把通道 0 的頻率設為 0
其他 LEDC 控制函式:
- ledcRead(通道):傳回指定通道的工作週期(佔空比)值。
- ledcReadFreq(通道):傳回指定通道的頻率值(若佔空比為 0 則傳回 0)。
- ledcDetachPin(接腳):解除指定接腳的 LEDC 功能,即取消 PWM 輸出。
最後,我們用一段程式來展示控制 ESP32 讓蜂鳴器發出聲音救護車警示音,接線法請參閱下圖。
#define BITS 10 #define BUZZER 22 //--- 蜂鳴器接腳 void setup() { ledcSetup(0,2000,BITS); //--- PWM 設定為:通道 0、頻率 20KHz、解析度 10 位元 ledcAttachPin(BUZZER,0); } void loop() { ledcWriteNote(0,NOTE_E,5); delay(500); ledcWriteNote(0,NOTE_A,4); delay(500); }