第5章 蜂鳴器
5-1
功能簡介
本次實驗主要介紹發聲元件-蜂鳴器,希望透過Arduino 開發環境的Serial Monitor,輸入不同的音階代碼,讓蜂鳴器發出我們指定的單一音階聲音,或是連續的音階聲音;本實驗系統方塊圖如圖 9‑1所示。
5-2
電路說明
一、 相關知識
喇叭(Speaker)與蜂鳴器(Buzzer)是一種將電氣信號轉換為聲音的轉換裝置,是電子產品中常用的發聲元件,例如音響喇叭、主機板上的蜂鳴器等。喇叭的基本動作原理,主要是利用電流通過線圈時的磁極物理作用,作反磁或相吸運動讓音盆進行往復運動,當音盆振動空氣時,即會以空氣為媒介傳遞至人類耳膜而感受到聲音,其中通過線圈的電流大小決定聲音的大小、往復運動的快慢(次/秒;Hz)決定聲調的高低,振動聲波持續的時間決定聲音的音長。
蜂鳴器與喇叭的發聲原理很像,但使用不同的材質;蜂鳴器分為電磁式及壓電式二大類,在耗電流、尺寸、頻率、驅動方式上有些不同,本實驗使用電磁式蜂鳴器,所使用的工作電壓為3V ~ 7.5V,其原理是通電時將金屬振動膜吸下,不通電時依振動膜的彈力彈回的電磁原理,耗電量較壓電式大,但使用較低的電壓即可工作。
蜂鳴器只要給定頻率即能發出聲音,例如要發出低音La的聲音(440Hz,週期2.27m s),我們只要送半週期高準位、半週期低準位,並持續輸出的方波給蜂鳴器即可發聲,如圖 9‑2所示。
但要如何計算其它音階的頻率呢?首先以低音A(La)頻率440Hz為基準,然後每隔半度音之頻率是前一個音的≒1.059463倍為原則來計算即可,表 9‑1為音階與頻率表;其中需注意的是Mi到Fa、Si到Do為半度音,其餘皆為一個全音,例如La到Si為一個全音,因此Si的頻率為440×1.059×1.059≒494Hz,Si到Do為半音,因此Do的頻率為494×1.059≒523Hz,比對圖 9‑3鋼琴上所示的鍵盤便可清晰了解,黑鍵為半度音。
【註】每個八度音共有12個半音,故每個半音的差值倍率為。
表 9‑2 第4個八度音域的音階頻率計算表
C 261.63×1.059 = 277.18 = C#
C# 277.18×1.059 = 293.66 = D
D 293.66×1.059 = 311.12 = D#
D# 311.13×1.059 = 329.62 = E
E 329.63×1.059 = 349.23 = F
F 349.23×1.059 = 369.99 = F#
F# 369.99×1.059 = 391.99 = G
G 392.00×1.059 = 415.30 = G#
G# 415.30×1.059 = 440.00 = A
A 440.00×1.059 = 466.16 = A#
A# 466.16×1.059 = 493.88 = B
B 493.88×1.059 = 523.25 = C
|
二、 電路圖
圖
9‑4為本實習的電路圖,只要將蜂鳴器的正端接至Arduino的D10,負端接地即可進行實驗。
三、 材料清單
表 9‑2 零件清單與規格表
零件名稱
|
規格型號
|
數量
|
備註
|
微電腦控制板
|
Arduino Leonardo(UNO或OZONE)
|
1
|
|
蜂鳴器
|
3-7V電磁式蜂鳴器MB
|
1
|
Arminno多功能實驗板已配接
|
按鈕開關
|
Tack switch(Push Button)
|
1
|
四、 注意事項
本實驗使用的蜂鳴器工作電壓為3V ~ 7.5V,以Arduino輸出的電壓5V,可順利推動蜂鳴器。如果選用的蜂鳴器(或喇叭)驅動電壓或電流過大時,請務必在蜂鳴器前接上電晶體或達靈頓電路,才能順利推動蜂鳴器。另外請注意蜂鳴器接腳上的正負端,有註明十字符號者為正端與D10相接,另一端則接地,如果蜂鳴器未標示正負,則接腳較長端為正端。
圖 9‑5 蜂鳴器正視圖與底視圖
五、 實體接線圖(MEB實驗板):
5-1
程式設計
本章實驗主要學習蜂鳴器的發聲控制,以及在Serial Monitor偵錯視窗中,如何逐字讀入資料並發聲的控制。
一、 流程圖
本實驗的程式主要是處理字串,依據Serial Monitor中所傳送的文字列進行逐字判斷,其中文字列的1~7代表要讓蜂鳴器發出第4八度音的Do~Si,字母C、D、E、F、G、A、B代表要發出第5八度音的Do~Si,每個單字音的音長固定為200m s,所有單字發聲完畢後停止發聲,回至等待使用者輸入的狀態,整個程序如下圖所示。
圖 9‑8 程式流程圖
二、 程式碼
本程式分為二個檔案,底下分別介紹。
(一)
音調標頭檔(程式\第9章\chap9_1 \pitches.h)
音調標頭檔中定義了8個八度音所有音調的音名及頻率,例如NOTE_C4代表第4八度音的C(Do),頻率為262Hz,方便在主程式中引用;由於pitches.h內容很多,底下僅列出第4及第5八度音的定義。
1
2
3
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
|
/*************************************************
* Public Constants
*************************************************/
省略
#define NOTE_C4 262 // Do 第4八度音
#define NOTE_CS4 277 // Do#
#define NOTE_D4 294 // Re
#define NOTE_DS4 311 // Re#
#define NOTE_E4 330 // Mi
#define NOTE_F4 349 // Fa
#define NOTE_FS4 370 // Fa#
#define NOTE_G4 392 // So
#define NOTE_GS4 415 // So#
#define NOTE_A4 440 // La
#define NOTE_AS4 466 // La#
#define NOTE_B4 494 // Si
#define NOTE_C5 523 // Do 第5八度音
#define NOTE_CS5 554 // Do#
#define NOTE_D5 587 // Re
#define NOTE_DS5 622 // Re#
#define NOTE_E5 659 // Mi
#define NOTE_F5 698 // Fa
#define NOTE_FS5 740 // Fa#
#define NOTE_G5 784 // So
#define NOTE_GS5 831 // So#
#define NOTE_A5 880 // La
#define NOTE_AS5 932 // La#
#define NOTE_B5 988 // Si
|
(二)
主程式(檔名:程式\第9章\chap9_1 \chap9_1.inb)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
/* Beep + Serial Monitor 的發聲控制 */
#include
"pitches.h" // 引入音調的標頭檔 (包含8個八度音)
const byte
Buzzer = 10; //
蜂鳴器的接腳 D10
char chr,
index;
// 宣告一個字元 1~7 對應到第4八度音
Do~Si 的音調陣列
int notes4[] =
{ NOTE_C4,NOTE_D4,NOTE_E4,NOTE_F4,NOTE_G4,NOTE_A4,NOTE_B4 };
// 宣告字元 A~G 對應到第5八度音La,Si,Do,Re,Mi,Fa,So的音調陣列
int notes5[] =
{ NOTE_A5,NOTE_B5,NOTE_C5,NOTE_D5,NOTE_E5,NOTE_F5,NOTE_G5 };
void setup() {
pinMode(Buzzer,OUTPUT);
}
void loop() {
// 判斷串列埠緩衝區有無資料
if (Serial.available()) {
chr=Serial.read(); // 從串列埠緩衝區讀取下一個有效的字元資料
if ((chr-'1')>=0 &&
(chr-'7')<=0) { // 判斷讀入的字元是否介於'1'~'7'
index=chr-'1'; // 取得音調陣列中的索引值
tone(Buzzer, notes4[index], 200); // 發出指定音調, 維持200ms
}
else if ((chr-'A')>=0 &&
(chr-'G')<=0) { // 判斷讀入的字元是否介於'A'~'G'
index=chr-'A'; // 取得音調陣列中的索引值
tone(Buzzer, notes5[index], 200); // 發出指定音調, 維持200ms
}
Serial.print("Tone "); // 在
Serial Monitor 中顯示訊息
Serial.println(chr); //
delay(200*1.3); // 延遲
200*1.3 ms
}
}
|
三、 指令介紹
(一)
#define:定義宣告
#define是一個很有用的指令,它允許程式在編譯前,賦予一個名稱對應一個恆定值或計算式的功能,此命令與常數宣告指令const功能很像,適合定義一些在執行期間數值不會變動的常數;不同於const指令的是#define為定義,不需指定資料型態,使用上彈性較大。
(二)
標頭檔pitches.h
標頭檔pitches.h可在書籍光碟→程式→第9章\chap9_1 \中找到,可在開啟的Arduino IDE中,點選Sketch→Add File,將此檔案加入即可,加入後可看到Arduino IDE中增加一個檔案頁籤。
圖 9‑9 標頭檔pitches.h的檔案頁籤
(三)
#include:引入標頭檔
一個專案的常數或定義通常都很多,而且是主程式、副程式共同使用,因此可將這些常數或定義儲存在一個標頭檔中(副屬檔名為.h),方便主副程式使用。當標頭檔建立完成,要引入使用,只要在Arduino IDE中點選Sketch→Add File加入標頭檔,然後在主程式中,利用#include指令即可引用。
#include
"pitches.h" // 引入位於同一專案資料夾下的檔案pitches.h
#include // 引入位於libraries資料夾下的Servo函式庫
(四)
tone(pin, frequency, duration):音調產生指令
此指令可在指定的pin腳輸出一個工作週期50%,頻率為frequency Hz的方波,持續輸出duration(單位ms)後自動關閉(tone指令的音調產生為背景動作,執行tone指令後主控權會立即交回主程式,並非等待duration後才交回);其中參數duration可省略,代表會持續發聲,直到執行noTone(pin)指令時關閉。
四、 程式說明
(一)
字元資料型態的運算:程式中宣告了chr及index為字元資料型態,chr變數儲存從串列埠緩衝區讀取下一個有效的單一字元資料,在運算上,我們可利用ASCII的特性進行加減運算,即可判斷chr是否為'1'~'7'間的字元,或是'A'~'G'間的字元,其中'?'代表某字元的ASCII碼。例如chr='0',其ASCII為48,'1'的ASCII為49,'7'的ASCII為55,代入底下的判斷式可知(chr-'1')>=0不成立,因此可知chr='0'未介於'1'~'7'間。
if ((chr-'1')>=0
&& (chr-'7')<=0)
(二)
行號22、26的tone發聲長度為200m s,理論上行號31的delay應也是200m s,但經由實驗測試,若同樣為200m s,各音調間連在一起並不好聽,多30%的delay,可讓各音調間有些斷音,聽起來比較正常。
5-2
實驗成果
一切準備就緒後,即可開始進行編譯程式以及下載、燒錄、測試的工作;燒錄成功後,請點選Tools→Serial
Monitor,並開始底下的測試:
1. 單音測試:在Serial Monitor輸入1,按Enter鍵或按Send,應可聽到單音的Do,且在Serial Monitor上顯示Tone 1,接著可試試輸入2,按Enter或Send,可聽到Re,如下圖所示。
2. 連續音調測試:在Serial Monitor輸入CDEFGAB,然後按Enter,聽聽程式是否會依續發出第5八度音的Do~Si;由於Serial
Monitor具有串列緩衝區,因此不管我們在Serial Monitor中輸入多少字元,程式皆會逐一讀入字元,並逐一處理並發聲。
3. 輸入音調以外的字元測試:在Serial Monitor輸入533x422x1234555,然後按Enter,聽聽程式中指定字元'1'~'7','A'~'G'外的字元是如何處理的,其實由程式即可看得很清楚,指定字元外的字元是不發聲,但延遲一樣時間,故變成靜音。試一下底下這二個字串,你可以聽出是什麼歌嗎?雖然沒進行音長控制,但還是可聽出個大概。
(1) 533x422x1234555x533x422x13551
(2) 11135555666C 5x4446333322225x511135555666C 5x4446333322231