天天看點

Arduino實驗——蜂鳴器播放《緻愛麗絲》

蜂鳴器,是一種可以發出單調聲音的器件,在電子 DIY 領域應用廣泛,因為它使用簡單,不像揚聲器一樣需要用準确的音頻信号來控制。蜂鳴器分為有源蜂鳴器和無源蜂鳴器。其中 “源” 不是指電源,而是指振蕩源,有源蜂鳴器隻需要通直流電壓就能發出蜂鳴聲;而無源蜂鳴器則需要用一定頻率的信号來驅動。

Arduino實驗——蜂鳴器播放《緻愛麗絲》

本實驗使用的是無源蜂鳴器。

工作原理

蜂鳴器輸入信号的頻率決定了蜂鳴器的聲音頻率,而 Arduino 預設的 PWM 輸出頻率是固定在 490.196Hz 的,是以不能簡單地使用 ​

​analogWrite()​

​​ 函數來控制蜂鳴器。 Arduino 為蜂鳴器控制設計了一個專用函數 ​

​tone(pin, frequency, duration)​

​​,其中 pin 指輸出引腳,frequency 指輸出頻率(機關 Hz),duration 是聲音持續的時間(機關 ms)。最後一個參數可以不填,不填時将持續輸出。對應的,還有一個 ​

​noTone(pin)​

​ 函數,用于停止指定引腳上的方波輸出。

是以,我們使用 Arduino 中的 ​

​tone()​

​ 函數就可以比較精确地控制聲音的頻率和持續時間。但是想要輸出特定的音符,則需要查頻率表,比較麻煩。好在 Arduino 庫中為我們提供了一個檔案 —— pitches.h,該檔案包含典型音符的所有音高值。例如,​

​NOTE_C4​

​​ 是中央 C,​

​NOTE_FS4​

​ 是 F#,等等。這個注釋表最初是由 Brett Hagman 編寫的,想制作音符時會發現它很有用!

硬體連接配接

将蜂鳴器輸入接在 Arduino 的 8 号數字 IO 上,再接上 GND 和 VCC 即可。

樂理知識

簡譜左上角通常有類似下面這樣的符号,用于表示曲子的調号和拍數。調号一般是用 1 等于 A、B、C、D、E、F、G 來表示,如 1=C 表示該簡譜是用 C 調來記譜的,如果要表示升降号的調,則在字母前加 # 号或者 b 号。調号後面的分數是拍号,其中分母表示以幾分音符為一拍,分子表示每小節有多少拍。拍号決定了樂曲的基本節奏和強弱的循環規律。

是以,上述符号表示該簡譜是 C 調來記譜的,以四分音符為一拍,每小節四拍。

再比如,這個符号表示該簡譜是 D 調來記譜的,以四分音符為一拍,每小節兩拍。

《緻愛麗絲》原名《a小調巴加泰勒》,它的調号和拍号如下所示。其中 Am 調是建立在根音 A 上的小三和弦,由【A C E】構成。然後以八分音符為一拍,每小節三拍。

講了那麼多,其實我也不太懂。。。 😿 哭唧唧

Arduino實驗——蜂鳴器播放《緻愛麗絲》

緻愛麗絲

/*
 Play a melody
*/

#include "pitches.h"

// 記錄曲子的音符
int melody[] = { 0, 0, NOTE_E5, NOTE_D5, NOTE_E5, NOTE_D5, NOTE_E5, NOTE_B4, NOTE_D5, NOTE_C5, 
                 NOTE_A4, 0, NOTE_C4, NOTE_E4, NOTE_A4, NOTE_B4, 0, NOTE_E4, NOTE_G4, NOTE_B4, 
                 NOTE_C5, 0, NOTE_E4, NOTE_E5, NOTE_D5, NOTE_E5, NOTE_D5, NOTE_E5, NOTE_B4, NOTE_D5, NOTE_C5,
                 NOTE_A4, 0, NOTE_C4, NOTE_E4, NOTE_A4, NOTE_B4, 0, NOTE_E4, NOTE_C5, NOTE_B4,
                 NOTE_A4
               };

// 音符持續時間:4為四分音符,8為八分音符
int noteDurations[] = { 4, 4, 8, 8, 8, 8, 8, 8, 8, 8, 
                        4, 8, 8, 8, 8, 4, 8, 8, 8, 8, 
                        4, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 
                        4, 8, 8, 8, 8, 4, 8, 8, 8, 8,
                        4, 4, 8, 8, 8, 8, 8, 8, 8, 8, 
                        4
                      };

void setup() {

  // 周遊整個曲子的音符
  for(int thisNote = 0; thisNote < sizeof(melody)/sizeof(melody[0]); thisNote++) {

    // 需要根據音符類型換算音符的持續時間
    int noteDuration = 1000/noteDurations[thisNote];
    tone(8, melody[thisNote], noteDuration);

    // 為了能辨識出不同的音調,需要在兩個音調間設定一定的延時,增加30%比較合适
    int pauseBetweenNotes = noteDuration * 1.30;
    delay(pauseBetweenNotes);

    noTone(8);
  }
  
}

void loop() {
  
}      

播放效果