《ESP32 入門》NodeMCU-32S搞定 有源蜂鳴器、無源蜂鳴器
用 ESP32 NodeMCU-32S 學習有源與無源蜂鳴器。有源蜂鳴器用 HIGH/LOW 控制開關,無源蜂鳴器透過 LEDC 產生不同頻率播放旋律,含完整接線、程式碼與常見問題。
前幾篇我們讓 ESP32 控制了 LED 和 LCD 螢幕,都是視覺上的效果,這篇我們來玩玩聲音吧!讓 ESP32 發出聲音最簡單的方法就是利用蜂鳴器(Buzzer)。
蜂鳴器基本上分兩類:有源蜂鳴器和無源蜂鳴器。有源蜂鳴器內建了振盪電路,只要接通電源就會發出固定的音調。無源蜂鳴器則不同,它本身不會產生聲音,我們必須透過程式提供特定頻率的訊號,才能讓它發出對應的音調,但也因為這樣,我們可以利用它來播放簡單的旋律!
怎麼分辨有源和無源?
有源蜂鳴器和無源蜂鳴器的外型很像,一般可以從這幾個地方分辨:

- 有源蜂鳴器上方通常會貼一張白色貼紙,底部有膠封住。
- 無源蜂鳴器的底部可以直接看到綠色的電路板。
- 最直接的方式:接上電源,如果直接發出聲音就是有源,沒聲音就是無源。
準備材料
| 材料 | 數量 | 備註 |
|---|---|---|
| NodeMCU-32S 開發板 | 1 | |
| 有源蜂鳴器 | 1 | 接 GPIO 16 |
| 無源蜂鳴器 | 1 | 接 GPIO 17 |
| 杜邦線 / 麵包板跳線 | 若干 | |
| 麵包板 | 1(選用) |



如果第一次接觸ESP32,建議先看入門篇哦!

有源蜂鳴器
我們先來試試簡單的有源蜂鳴器。蜂鳴器上會有 + 和 - 的符號,分別代表正極和負極。我們把有源蜂鳴器的 - 接到 GND,+ 接到 GPIO 16。然後順便也把無源蜂鳴器接到 GPIO 17和GND。

接線
| 有源蜂鳴器 | |
|---|---|
| + | GPIO 16 |
| - | GND |
| 無源蜂鳴器 | |
|---|---|
| + | GPIO 17 |
| - | GND |
⚠️ 注意:ESP32 的 GPIO 最大輸出電流約 40mA(建議不超過 20mA),大部分小型蜂鳴器在這個範圍內可以正常運作。但如果你的蜂鳴器比較大顆或額定電流較高,建議加一顆電晶體(如 S8050)來驅動,避免直接從 GPIO 拉太多電流損壞 ESP32。
程式碼
程式非常簡單,digitalWrite(16, HIGH) 就能讓蜂鳴器發出聲音,要持續多久就用 delay() 來控制,再用 digitalWrite(16, LOW) 讓聲音停止。
這個例子讓蜂鳴器叫 1 秒鐘後,停 2 秒,然後不斷重複。有源蜂鳴器的程式就這樣而已,非常容易。
const int buzzerPin = 16;
void setup() {
pinMode(buzzerPin, OUTPUT);
}
void loop() {
digitalWrite(buzzerPin, HIGH); // 蜂鳴器響
delay(1000); // 持續 1 秒
digitalWrite(buzzerPin, LOW); // 蜂鳴器停
delay(2000); // 安靜 2 秒
}
無源蜂鳴器
無源蜂鳴器因為要處理聲音的頻率和節拍,所以比有源蜂鳴器還要麻煩一點。不過別擔心,我們參考 Arduino IDE 內建的「toneMelody」範例來改寫,就能快速理解運作原理。
這次我們把無源蜂鳴器接到 GPIO 17,和前面有源蜂鳴器的 GPIO 16 分開,這樣兩個蜂鳴器可以同時接在麵包板上,不用換線。
ESP32 的 tone() 問題
如果你直接把 Arduino 的 tone() 函式搬到 ESP32 上,會發現編譯失敗,因為 ESP32 的 Arduino 核心並沒有內建 tone() 函式。不過沒關係,ESP32 有 LEDC(LED Control)功能可以產生 PWM 訊號,我們可以用它來代替。
音調對照表 pitches.h
在 Arduino IDE 的 toneMelody 範例中有提供一個 pitches.h 檔案,裡面定義了各音符對應的頻率。如果你是從空白專案開始寫,需要自己建立這個檔案。
在 Arduino IDE 中,點選右上角的「...」按鈕,選擇「新增標籤」,命名為 pitches.h,然後貼上以下常用的音符定義:
#define NOTE_B0 31
#define NOTE_C1 33
#define NOTE_CS1 35
#define NOTE_D1 37
#define NOTE_DS1 39
#define NOTE_E1 41
#define NOTE_F1 44
#define NOTE_FS1 46
#define NOTE_G1 49
#define NOTE_GS1 52
#define NOTE_A1 55
#define NOTE_AS1 58
#define NOTE_B1 62
#define NOTE_C2 65
#define NOTE_CS2 69
#define NOTE_D2 73
#define NOTE_DS2 78
#define NOTE_E2 82
#define NOTE_F2 87
#define NOTE_FS2 93
#define NOTE_G2 98
#define NOTE_GS2 104
#define NOTE_A2 110
#define NOTE_AS2 117
#define NOTE_B2 123
#define NOTE_C3 131
#define NOTE_CS3 139
#define NOTE_D3 147
#define NOTE_DS3 156
#define NOTE_E3 165
#define NOTE_F3 175
#define NOTE_FS3 185
#define NOTE_G3 196
#define NOTE_GS3 208
#define NOTE_A3 220
#define NOTE_AS3 233
#define NOTE_B3 247
#define NOTE_C4 262
#define NOTE_CS4 277
#define NOTE_D4 294
#define NOTE_DS4 311
#define NOTE_E4 330
#define NOTE_F4 349
#define NOTE_FS4 370
#define NOTE_G4 392
#define NOTE_GS4 415
#define NOTE_A4 440
#define NOTE_AS4 466
#define NOTE_B4 494
#define NOTE_C5 523
#define NOTE_CS5 554
#define NOTE_D5 587
#define NOTE_DS5 622
#define NOTE_E5 659
#define NOTE_F5 698
#define NOTE_FS5 740
#define NOTE_G5 784
#define NOTE_GS5 831
#define NOTE_A5 880
#define NOTE_AS5 932
#define NOTE_B5 988
#define NOTE_C6 1047
#define NOTE_CS6 1109
#define NOTE_D6 1175
#define NOTE_DS6 1245
#define NOTE_E6 1319
#define NOTE_F6 1397
#define NOTE_FS6 1480
#define NOTE_G6 1568
#define NOTE_GS6 1661
#define NOTE_A6 1760
#define NOTE_AS6 1865
#define NOTE_B6 1976
#define NOTE_C7 2093
#define NOTE_CS7 2217
#define NOTE_D7 2349
#define NOTE_DS7 2489
#define NOTE_E7 2637
#define NOTE_F7 2794
#define NOTE_FS7 2960
#define NOTE_G7 3136
#define NOTE_GS7 3322
#define NOTE_A7 3520
#define NOTE_AS7 3729
#define NOTE_B7 3951
#define NOTE_C8 4186
#define NOTE_CS8 4435
#define NOTE_D8 4699
#define NOTE_DS8 4978
完整檔案也可以從 Arduino IDE 的範例中取得:檔案 → 範例 → 02.Digital → toneMelody,開啟後切換到 pitches.h 分頁即可複製。
程式碼
以下程式改寫自 toneMelody 範例,使用 ESP32 的 LEDC 來產生音調。旋律放在 setup() 中只播放一次,因為這段示範曲只是用來測試蜂鳴器是否正常運作。如果你想讓它重複播放,把程式碼搬到 loop() 裡就行了。
#include "pitches.h"
const int buzzerPin = 17;
// 旋律:小星星前兩句
int melody[] = {
NOTE_C4, NOTE_C4, NOTE_G4, NOTE_G4,
NOTE_A4, NOTE_A4, NOTE_G4, 0,
NOTE_F4, NOTE_F4, NOTE_E4, NOTE_E4,
NOTE_D4, NOTE_D4, NOTE_C4, 0
};
// 每個音的拍子,4:4分音符,8:8分音符
int noteDurations[] = {
4, 4, 4, 4,
4, 4, 2, 4,
4, 4, 4, 4,
4, 4, 2, 4
};
void setup() {
for (int i = 0; i < 16; i++) {
// 計算每個音的長度,4分音符:1000/4=250ms
int noteDuration = 1000 / noteDurations[i];
if (melody[i] == 0) {
// 音符為 0 代表休止符,不發聲
ledcDetach(buzzerPin);
} else {
// 用 LEDC 產生對應頻率的 PWM 訊號
ledcAttach(buzzerPin, melody[i], 8); // 8-bit 解析度
ledcWrite(buzzerPin, 128); // 50% duty cycle
}
// 每個音之間停一小段時間,拍子長度的 130%
int pauseBetweenNotes = noteDuration * 1.30;
delay(pauseBetweenNotes);
// 停止播放
ledcDetach(buzzerPin);
}
}
void loop() {
// 旋律只播放一次,不需要重複
}
上傳程式後,你應該會聽到蜂鳴器播出「一閃一閃亮晶晶」的前兩句旋律。

ESP32 GPIO 使用注意事項
和前幾篇一樣,提醒一下 ESP32 有些 GPIO 要避開:
- GPIO 0、2、12、15:Strapping Pins,影響開機模式,避免使用。
- GPIO 6~11:連接內部 SPI Flash,不能使用。
- GPIO 34、35、36、39:純輸入腳位(Input Only),無法輸出 PWM 訊號。
本範例使用的 GPIO 16 和 GPIO 17 都是安全的通用腳位,可以放心使用。
常見問題
Q:無源蜂鳴器編譯時出現 tone() 找不到的錯誤? ESP32 的 Arduino 核心沒有內建 tone() 函式,請改用本篇教學中的 LEDC 寫法。
Q:有源蜂鳴器接上去沒聲音? 確認正負極有沒有接反,+ 要接 GPIO、- 要接 GND。也可以先把 + 直接接到 3V3 腳位測試,如果有聲音代表蜂鳴器是好的,問題出在程式或腳位設定。
Q:聲音很小聲? ESP32 的 GPIO 輸出為 3.3V,比 Arduino Uno 的 5V 低,驅動蜂鳴器的音量會稍微小一些。如果需要更大音量,可以用電晶體搭配 5V 電源來驅動蜂鳴器。
Q:可以同時讓兩個蜂鳴器發出不同的音嗎? 可以!ESP32 的 LEDC 有 16 個通道(0~15),每個通道可以獨立設定不同頻率,分別接不同的 GPIO 和蜂鳴器就能做到。這是 ESP32 比 Arduino Uno 強大的地方之一。
小結
這篇我們學會了用 ESP32 NodeMCU-32S 驅動有源蜂鳴器和無源蜂鳴器。有源蜂鳴器只要 HIGH/LOW 就能控制開關;無源蜂鳴器則需要透過 LEDC 產生特定頻率的 PWM 訊號來發出不同音調。有了這個基礎,你可以試著把自己喜歡的旋律編寫成音符陣列,讓 ESP32 幫你演奏!



