ESP32 入門》用程式控制 LED超簡單!

用 ESP32 NodeMCU-32S 控制 LED。教學包含歐姆定律計算限流電阻、GPIO 腳位選擇、LED 閃爍程式,以及 LEDC 硬體 PWM 模組的詳細介紹與呼吸燈效果實作。

ESP32 入門》用程式控制 LED超簡單!

這篇我們從「歐姆定律(Ohm's law)」談起,為 LED 加上適當的電阻,讓它發亮;再來我們撰寫 Arduino 程式,讓麵包板上的 LED 閃爍起來!本篇以 ESP32 NodeMCU-32S 開發板為範例。


LED 基本知識

LED 燈(LED lamp)是利用發光二極體(LED)作為光源的燈具,一般使用半導體 LED 製成。LED 燈的壽命和發光效率可達白熾燈的數倍。

請注意,LED長腳是正極,短腳是負極,千萬別接錯了!

每種顏色的 LED 所需的順向電壓(Forward Voltage)都不太一樣:

顏色 順向電壓
紅色 1.8 – 2.2V
綠色 2.0 – 3.5V
藍色 3.0 – 3.5V
白色 3.0 – 3.5V
⚠️ 重要差異: Arduino Uno 的 GPIO 輸出是 5V,而 ESP32 的 GPIO 輸出是 3.3V。這代表 ESP32 所需的限流電阻值會跟 Arduino Uno 不同,而且 ESP32 的 GPIO 不能接受超過 3.3V 的輸入,千萬不要把 5V 直接接到 ESP32 的 GPIO 腳位!

歐姆定律計算電阻值

為了避免 LED 燒掉,我們必須加上限流電阻。需要多大的電阻呢?這可以透過「歐姆定律(Ohm's law)」算出來。

歐姆定律公式:

V = I R,電壓 = 電流x電阻

  • V = 電壓(伏特,V)
  • I = 電流(安培,A)
  • R = 電阻(歐姆,Ω)

計算所需電阻值:

R= V / I,電阻 = 電壓 / 電流

以 ESP32 的 GPIO 輸出電壓 3.3V,紅色 LED 順向電壓以 2V 估算,5mm LED 需要的電流約 20mA(0.02A):

R = (3.3-2) / 0.02 = 65

計算結果是 65Ω,但一般套件中常見的電阻最小是 220Ω,用大一點的電阻是完全沒問題的(LED 只是稍微暗一些,但更安全)。所以我們就使用 220Ω 的電阻。

💡 小知識: 如果用 5V 算出來需要 150Ω ,用 3.3V 只需要 65Ω。但實務上都用 220Ω 就對了,安全又方便!

先把 LED 點亮(不寫程式)

在寫程式之前,我們先用 ESP32 開發板的 3.3V 電源,把 LED 直接點亮,練習一下接線。

所需材料

材料 數量
ESP32 NodeMCU-32S 開發板 1
麵包板 1
5mm LED(任意顏色) 1
220Ω 電阻 1
公對公杜邦線 2 條
USB 傳輸線(Micro USB) 1
NodeMCU-32S 相容版本 ESP32開發板 WiFi 藍牙 可用Arduino IDE
全腳位引出,還保持迷你的身型,插上麵包後還能插杜邦線,真的是太棒了! 和NodeMCU V2幾乎一樣尺寸! 有5V供電輸出,非常方便! 有了ESP32開發板,真的可以忘記原來的那些Arduino板子了! 可以用Arduino IDE開發,但效能更強大,還內建WiFi 傑森實測記錄,大家可以到 F 粉 絲 團 B 看貼文哦! ESP32-D0WDQ6 內置兩個低功耗 Xtensa® 32-bit LX6 MCU。片上存儲包括: • 448 KB 的 ROM,用於程序啟動和內核功能
400孔 麵包板 紅藍線 85x55mm Arduino 迷你麵包板 小麵包板
高品質麵包板 400孔,紅藍線 多次拔插也不會鬆動
5mm 超高亮度LED 紅光 10個一組
本賣場為紅光LED 10個為一個單位,本場賣售價為10個的價錢 電壓:3-3.4V 電流:18-20mA 提示:LED驅動是以電流值為準,不是以電壓為準,LED的電壓會存在一定差異,一般白光的電壓在3.0-3.6V之間, 電流的典型值為20mA,如果採用電壓驅動的朋友請確認電流是否正常,電流太低將會使亮度下降, 電流太高則會造成LED晶片擊穿或影響使用壽命,用電壓驅動一定要加限流電阻來調整電流. 如果是和別的LED對比亮度的買家請確認被對比的產品和我們產品在對比時採用的驅動電流是否相同,驅動電
10個 1/4W 220Ω 電阻DIP 插板電阻 碳膜電阻 1%
1/4W 220Ω 本賣場一個單位是20根
10cm 杜邦線 公對母 40條 12股銅絲含膠殼
★ Arduino 專用 杜邦端子 連接線 ★1P-1P雙頭本賣場是公接頭對母接頭!杜邦線線長:10cm10條10種顏色一組※ 賣場的價錢是10條的價錢哦!賣場圖為一整排,40條、4組完整Arduino套件特價供應!前往賣場: https://shopee.tw/product/20917936/339420398/

接線方式

  1. 把 LED 插到麵包板上。LED 長腳是正極(+),短腳是負極(−),別接錯了!
  2. 用杜邦線把 ESP32 的 GND 接到 LED 的負極(短腳)
  3. 電阻不分正負極,一腳接到 LED 的正極(長腳),另一腳接到 ESP32 的 3V3(3.3V 電源腳位)。

電流路徑:3V3 → 電阻 → LED 正極 → LED 負極 → GND

如果你的 ESP32 已經接上 USB 線供電,這時你就會看到 LED 亮起來囉!


用程式控制 LED 閃爍

接下來我們要寫程式,透過 ESP32 的 GPIO 腳位來控制 LED 的開關。

選擇 GPIO 腳位

ESP32 的 GPIO 腳位選擇比 Arduino Uno 複雜一些,有些腳位有特殊用途,不適合拿來做一般的數位輸出。以下是建議:

推薦使用的 GPIO: GPIO 2、4、5、16、17、18、19、21、22、23、25、26、27、32、33

避免使用的 GPIO:

  • GPIO 6–11:連接內部 Flash 記憶體,不可使用
  • GPIO 34、35、36、39:僅能作為輸入(input only),不能輸出
  • GPIO 0、12、15:啟動時有特殊功能,建議避免

本篇教學我們使用 GPIO 27 來控制 LED。

修改接線

把原本接在 3V3 的那條杜邦線(連接電阻的那端),改接到 ESP32 的 GPIO 23

ESP32 NodeMCU-32S
┌─────────────┐
│             │
│  GPIO 23 ●──┼──→ 電阻(220Ω) ──→ LED(+) ──→ LED(−) ──→ GND ●
│             │
│  GND ●──────┼─────────────────────────────────────────────┘
│             │
└─────────────┘

程式碼

在 Arduino IDE 中建立新檔案(或修改 Blink 範例),輸入以下程式碼:

// ESP32 LED 閃爍範例
// 使用 GPIO 27 控制外接 LED

const int LED_PIN = 27;  // 定義 LED 連接的 GPIO 腳位

// setup() 函式:開機或重置時執行一次
void setup() {
  pinMode(LED_PIN, OUTPUT);  // 設定 GPIO 27 為輸出模式
}

// loop() 函式:重複執行
void loop() {
  digitalWrite(LED_PIN, HIGH);  // 點亮 LED(輸出 HIGH = 3.3V)
  delay(1000);                  // 等待 1 秒
  digitalWrite(LED_PIN, LOW);   // 熄滅 LED(輸出 LOW = 0V)
  delay(1000);                  // 等待 1 秒
}

Arduino IDE 設定

上傳程式前,請先確認 Arduino IDE 的設定已完成,這部份請看我們另一篇教學哦!

在Arduino IDE中新增ESP32的開發板-以Nodemcu-32s為例
雖然Arduino Uno方便好用,如果真的需要WiFi功能,傑森一律建議直接換塊ESP32的板子,這是最直接的方法。 但Arduino IDE安裝好時並沒有ESP32開發板的選項,所以必須自行安裝,不過其實很簡單的。

設定完成後,點選左上角的「上傳(Upload)」按鈕,把程式上傳到 ESP32。

💡 提示: 部分 ESP32 開發板在上傳時需要按住板子上的 BOOT 按鈕,等到 IDE 顯示「Connecting...」時按住,出現上傳進度後就可以放開。NodeMCU-32S 通常不需要手動按,因為它有自動下載電路。

上傳成功後,你就會看到 LED 開始一秒亮、一秒滅地閃爍了!


進階:用 PWM 控制 LED 亮度

ESP32 比 Arduino Uno 強大的地方之一,就是擁有硬體 LEDC(LED Control) 模組,可以用 PWM(脈波寬度調變)來精細控制 LED 的亮度,不只是開跟關而已。

什麼是 PWM?

PWM(Pulse Width Modulation,脈波寬度調變)是一種透過快速切換「開」和「關」來模擬類比輸出的技術。想像你在快速開關電燈開關——如果開的時間長、關的時間短,燈看起來就很亮;反之則看起來很暗。只要切換的速度夠快(超過人眼可辨識的頻率),我們就會感覺亮度是「連續」變化的。

PWM 訊號有兩個關鍵參數:

  • 頻率(Frequency): 每秒切換開關的次數,單位是 Hz。頻率越高,閃爍越不明顯。控制 LED 亮度時,通常設定在 1000Hz 以上就夠了。
  • 工作週期or占空比(Duty Cycle): 在一個週期中,訊號處於「HIGH」狀態的時間比例,通常以百分比或解析度數值表示。占空比 0% 代表全暗,100% 代表全亮。
占空比 25%(暗)        占空比 75%(亮)
 ┌──┐                   ┌──────┐
 │  │                   │      │
─┘  └──────────      ───┘      └──

什麼是 LEDC?

LEDC 是 ESP32 內建的「LED 控制器」硬體模組,全名是 LED Control (LEDC)。雖然名字裡有 LED,但它本質上是一個功能強大的硬體 PWM 產生器,不只能控制 LED,也能驅動馬達、蜂鳴器等需要 PWM 訊號的裝置。

為什麼不直接用 analogWrite()

在 Arduino Uno 上,我們習慣用 analogWrite() 來產生 PWM,但那其實是靠軟體模擬的,頻率固定在約 490Hz,解析度固定 8-bit,而且只有特定腳位(標有 ~ 符號)才能使用。

ESP32 的 LEDC 則完全不同,它是硬體層級的 PWM 控制器,有以下優勢:

特性Arduino Uno(軟體 PWM)ESP32 LEDC(硬體 PWM)
通道數6 個(特定腳位)16 個獨立通道
頻率範圍固定 ~490Hz10Hz ~ 40MHz(可調)
解析度固定 8-bit(0~255)1-bit ~ 16-bit(可調)
硬體淡入淡出❌ 無✅ 支援自動漸變
可用腳位僅限標有 ~ 的腳位幾乎所有可輸出的 GPIO

LEDC 的架構:Timer 與 Channel

LEDC 內部由 Timer(計時器)Channel(通道) 兩層組成:

Timer 0 ──┬── Channel 0 ──→ GPIO 23(LED 1)
           └── Channel 1 ──→ GPIO 25(LED 2)

Timer 1 ──┬── Channel 2 ──→ GPIO 26(馬達)
           └── Channel 3 ──→ GPIO 27(蜂鳴器)
  • Timer 決定 PWM 的頻率解析度。ESP32 有 4 個 Timer,每個 Timer 可以被 2 個 Channel 共用。
  • Channel 決定 PWM 的占空比,並綁定到指定的 GPIO 腳位。共享同一個 Timer 的 Channel 頻率相同,但占空比可以各自不同。

也就是說,ESP32 最多可以同時輸出 16 組獨立的 PWM 訊號,其中可以有 8 種不同的頻率

不過要注意的是,不同型號的 ESP32 晶片,LEDC 的通道數量和支援的模式不同:

晶片型號LEDC 通道數速度模式
ESP32(經典款)16高速 + 低速各 8 個
ESP32-S28僅低速
ESP32-S38僅低速
ESP32-C36僅低速
ESP32-C66僅低速
ESP32-H26僅低速

只有經典 ESP32 支援高速模式,好處是改變 PWM 設定時,硬體會在下一個週期自動無縫切換,不會產生毛刺(glitch)。其他型號僅有低速模式,但 Arduino 函式庫已經在背後處理好了軟體觸發更新的細節,一般使用上完全不需要擔心。

頻率與解析度的取捨

頻率和解析度之間存在互相制約的關係:頻率越高,可用的解析度越低。這是因為 LEDC 的時脈(clock)資源有限,要在一個 PWM 週期內切出越多段(高解析度),週期就不能太短(低頻率)。

以下是幾組常見的搭配:

頻率最大解析度占空比階數適用場景
1 kHz16-bit65,536 階超精細亮度控制
5 kHz13-bit8,192 階LED 亮度控制(推薦)
40 kHz10-bit1,024 階馬達 PWM 控制
1 MHz6-bit64 階高速訊號產生
40 MHz1-bit2 階時脈訊號(僅開/關)

對於 LED 亮度控制,5kHz + 8-bit(256 階) 是非常實用的組合,人眼完全感覺不到閃爍,256 階的亮度變化也足夠平滑。

Arduino Core 3.x 的 LEDC API

在 ESP32 Arduino Core 3.x 版本中,LEDC 的 API 做了大幅簡化,不再需要手動管理 channel 編號,系統會自動分配:

函式說明
ledcAttach(pin, freq, resolution)設定 GPIO 腳位的 PWM 頻率與解析度(自動分配 channel)
ledcAttachChannel(pin, freq, resolution, channel)手動指定 channel(進階用法)
ledcWrite(pin, duty)設定指定腳位的占空比
ledcWriteTone(pin, freq)輸出指定頻率的方波(50% 占空比),適合蜂鳴器
ledcWriteNote(pin, note, octave)輸出音符頻率,例如 ledcWriteNote(pin, NOTE_C, 4)
ledcDetach(pin)解除腳位的 LEDC 綁定
ledcChangeFrequency(pin, freq, resolution)動態修改頻率與解析度
ledcFade(pin, startDuty, endDuty, duration)硬體自動淡入淡出
⚠️ 注意: 如果你用的是舊版 Arduino Core 2.x,API 不同,需要使用 ledcSetup(channel, freq, resolution) + ledcAttachPin(pin, channel) + ledcWrite(channel, duty) 的寫法。3.x 已經移除了這些舊函式。

呼吸燈效果

以下程式讓 LED 產生漸亮漸暗的「呼吸燈」效果:

// ESP32 呼吸燈範例
// 使用 LEDC PWM 控制 LED 亮度
// 適用於 ESP32 Arduino Core 3.x 版本

const int LED_PIN = 27;       // LED 連接的 GPIO 腳位
const int PWM_FREQ = 5000;    // PWM 頻率 5000Hz
const int PWM_RESOLUTION = 8; // 解析度 8-bit(0~255)

void setup() {
  // 設定 LEDC:直接綁定 GPIO,指定頻率與解析度
  ledcAttach(LED_PIN, PWM_FREQ, PWM_RESOLUTION);
}

void loop() {
  // 漸亮
  for (int duty = 0; duty <= 255; duty++) {
    ledcWrite(LED_PIN, duty);  // 直接對 GPIO 腳位寫入 duty
    delay(10);
  }

  // 漸暗
  for (int duty = 255; duty >= 0; duty--) {
    ledcWrite(LED_PIN, duty);
    delay(10);
  }
}
⚠️ 注意: 如果你使用的是 ESP32 Arduino Core 3.x 版本,LEDC API 有變動。上面的寫法適用於 2.x 版。3.x 版請改用 ledcAttach(LED_PIN, PWM_FREQ, PWM_RESOLUTION)ledcWrite(LED_PIN, duty) 的新語法。

ESP32 vs Arduino Uno 差異整理

項目 Arduino Uno ESP32 NodeMCU-32S
GPIO 輸出電壓 5V 3.3V
建議限流電阻 150Ω(實用 220Ω) 65Ω(實用 220Ω)
GPIO 腳位數量 14 個數位 + 6 個類比 多達 34 個 GPIO
PWM 功能 軟體模擬(analogWrite) 硬體 LEDC 模組(16 通道)
特殊限制 較少 部分 GPIO 有限制(僅輸入、啟動用途等)
上傳設定 選板即可 需另外安裝 ESP32 開發板套件
板載 LED 腳位 Pin 13(LED_BUILTIN) GPIO 2(多數開發板)

小結

這篇我們學會了:

  1. 用歐姆定律計算 ESP32 所需的限流電阻值
  2. 在麵包板上接線,用 ESP32 的 3.3V 電源直接點亮 LED
  3. 透過程式控制 GPIO 腳位,讓 LED 閃爍
  4. 用 ESP32 的 LEDC PWM 功能製作呼吸燈效果

下一篇我們會繼續探索更多 ESP32 的功能,敬請期待!