《ESP32 入門》NodeMCU-32S搞定 有源蜂鳴器、無源蜂鳴器

用 ESP32 NodeMCU-32S 學習有源與無源蜂鳴器。有源蜂鳴器用 HIGH/LOW 控制開關,無源蜂鳴器透過 LEDC 產生不同頻率播放旋律,含完整接線、程式碼與常見問題。

《ESP32 入門》NodeMCU-32S搞定 有源蜂鳴器、無源蜂鳴器

前幾篇我們讓 ESP32 控制了 LED 和 LCD 螢幕,都是視覺上的效果,這篇我們來玩玩聲音吧!讓 ESP32 發出聲音最簡單的方法就是利用蜂鳴器(Buzzer)。

蜂鳴器基本上分兩類:有源蜂鳴器和無源蜂鳴器。有源蜂鳴器內建了振盪電路,只要接通電源就會發出固定的音調。無源蜂鳴器則不同,它本身不會產生聲音,我們必須透過程式提供特定頻率的訊號,才能讓它發出對應的音調,但也因為這樣,我們可以利用它來播放簡單的旋律!


怎麼分辨有源和無源?

有源蜂鳴器和無源蜂鳴器的外型很像,一般可以從這幾個地方分辨:

  • 有源蜂鳴器上方通常會貼一張白色貼紙,底部有膠封住。
  • 無源蜂鳴器的底部可以直接看到綠色的電路板。
  • 最直接的方式:接上電源,如果直接發出聲音就是有源,沒聲音就是無源。

準備材料

材料 數量 備註
NodeMCU-32S 開發板 1
有源蜂鳴器 1 接 GPIO 16
無源蜂鳴器 1 接 GPIO 17
杜邦線 / 麵包板跳線 若干
麵包板 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,用於程序啟動和內核功能
無源蜂鳴器 5v 電磁式蜂鳴器 阻抗16歐姆
無源蜂鳴器,電阻16歐。 驅動方式與工作原理與普通揚聲器相同。 無源蜂鳴器意思是需要加音頻驅動信號才能使其發出聲音,與有源蜂鳴器相對應。有源蜂鳴器只需要通上直流電即會發出蜂鳴聲,有源蜂鳴器內部自帶振盪器!
有源蜂鳴器 5v 電磁式蜂鳴器 阻抗16歐姆 採用SOT塑封管
有源蜂鳴器,電阻16歐。 驅動方式與工作原理與普通揚聲器相同。 無源蜂鳴器意思是需要加音頻驅動信號才能使其發出聲音,與有源蜂鳴器相對應。有源蜂鳴器只需要通上直流電即會發出蜂鳴聲,有源蜂鳴器內部自帶振盪器!

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

在Arduino IDE中新增ESP32的開發板-以Nodemcu-32s為例
雖然Arduino Uno方便好用,如果真的需要WiFi功能,傑森一律建議直接換塊ESP32的板子,這是最直接的方法。 但Arduino IDE安裝好時並沒有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 幫你演奏!