搜尋此網誌

2018/08/09

Arduino 蜂鳴器發聲


第5章       蜂鳴器

5-1        功能簡介

    本次實驗主要介紹發聲元件-蜂鳴器,希望透過Arduino 開發環境的Serial Monitor,輸入不同的音階代碼,讓蜂鳴器發出我們指定的單一音階聲音,或是連續的音階聲音;本實驗系統方塊圖如 91所示。   

91 系統方塊圖

5-2        電路說明

一、  相關知識
喇叭(Speaker)與蜂鳴器(Buzzer)是一種將電氣信號轉換為聲音的轉換裝置,是電子產品中常用的發聲元件,例如音響喇叭、主機板上的蜂鳴器等。喇叭的基本動作原理,主要是利用電流通過線圈時的磁極物理作用,作反磁或相吸運動讓音盆進行往復運動,當音盆振動空氣時,即會以空氣為媒介傳遞至人類耳膜而感受到聲音,其中通過線圈的電流大小決定聲音的大小、往復運動的快慢(次/秒;Hz)決定聲調的高低,振動聲波持續的時間決定聲音的音長
蜂鳴器與喇叭的發聲原理很像,但使用不同的材質;蜂鳴器分為電磁式及壓電式二大類,在耗電流、尺寸、頻率、驅動方式上有些不同,本實驗使用電磁式蜂鳴器,所使用的工作電壓為3V ~ 7.5V,其原理是通電時將金屬振動膜吸下,不通電時依振動膜的彈力彈回的電磁原理,耗電量較壓電式大,但使用較低的電壓即可工作。

蜂鳴器只要給定頻率即能發出聲音,例如要發出低音La的聲音(440Hz,週期2.27ms),我們只要送半週期高準位、半週期低準位,並持續輸出的方波給蜂鳴器即可發聲,如 92所示。
92 低音La440Hz)的聲音頻率示意圖
但要如何計算其它音階的頻率呢?首先以低音ALa)頻率440Hz為基準,然後每隔半度音之頻率是前一個音的1.059463倍為原則來計算即可, 91為音階與頻率表;其中需注意的是MiFaSiDo為半度音,其餘皆為一個全音,例如LaSi為一個全音,因此Si的頻率為440×1.059×1.059494HzSiDo為半音,因此Do的頻率為494×1.059523Hz,比對 93鋼琴上所示的鍵盤便可清晰了解,黑鍵為半度音。

【註】每個八度音共有12個半音,故每個半音的差值倍率為
93 鋼琴鍵盤示意圖(MiFaSiDo為半度音,餘為一個全音)

91 音階與頻率表

92 第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
二、  電路圖
94為本實習的電路圖,只要將蜂鳴器的正端接至ArduinoD10,負端接地即可進行實驗。
94 電路圖

三、  材料清單
92 零件清單與規格表
零件名稱
規格型號
數量
備註
微電腦控制板
Arduino LeonardoUNOOZONE
1

蜂鳴器
3-7V電磁式蜂鳴器MB12A05
1
Arminno多功能實驗板已配接
按鈕開關
Tack switchPush Button
1

四、  注意事項
    本實驗使用的蜂鳴器工作電壓為3V ~ 7.5V,以Arduino輸出的電壓5V,可順利推動蜂鳴器。如果選用的蜂鳴器(或喇叭)驅動電壓或電流過大時,請務必在蜂鳴器前接上電晶體或達靈頓電路,才能順利推動蜂鳴器。另外請注意蜂鳴器接腳上的正負端,有註明十字符號者為正端與D10相接,另一端則接地,如果蜂鳴器未標示正負,則接腳較長端為正端。
95 蜂鳴器正視圖與底視圖



五、  實體接線圖(MEB實驗板):


5-1        程式設計

  本章實驗主要學習蜂鳴器的發聲控制,以及在Serial Monitor偵錯視窗中,如何逐字讀入資料並發聲的控制。
一、  流程圖
  本實驗的程式主要是處理字串,依據Serial Monitor中所傳送的文字列進行逐字判斷,其中文字列的17代表要讓蜂鳴器發出第4八度音的DoSi,字母CDEFGAB代表要發出第5八度音的DoSi,每個單字音的音長固定為200ms,所有單字發聲完畢後停止發聲,回至等待使用者輸入的狀態,整個程序如下圖所示。
98 程式流程圖
二、  程式碼
本程式分為二個檔案,底下分別介紹。
(一)    音調標頭檔(程式\9\chap9_1 \pitches.h
音調標頭檔中定義了8個八度音所有音調的音名及頻率,例如NOTE_C4代表第4八度音的CDo),頻率為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中,點選SketchAdd File,將此檔案加入即可,加入後可看到Arduino IDE中增加一個檔案頁籤。

99 標頭檔pitches.h的檔案頁籤
(三)    #include:引入標頭檔
一個專案的常數或定義通常都很多,而且是主程式、副程式共同使用,因此可將這些常數或定義儲存在一個標頭檔中(副屬檔名為.h),方便主副程式使用。當標頭檔建立完成,要引入使用,只要在Arduino IDE中點選SketchAdd 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)指令時關閉。
四、  程式說明
(一)    字元資料型態的運算:程式中宣告了chrindex為字元資料型態,chr變數儲存從串列埠緩衝區讀取下一個有效的單一字元資料,在運算上,我們可利用ASCII的特性進行加減運算,即可判斷chr是否為'1''7'間的字元,或是'A''G'間的字元,其中'?'代表某字元的ASCII碼。例如chr='0',其ASCII48'1'ASCII49'7'ASCII55,代入底下的判斷式可知(chr-'1')>=0不成立,因此可知chr='0'未介於'1''7'間。
if ((chr-'1')>=0 && (chr-'7')<=0)
(二)    行號2226tone發聲長度為200ms,理論上行號31delay應也是200ms,但經由實驗測試,若同樣為200ms,各音調間連在一起並不好聽,多30%delay,可讓各音調間有些斷音,聽起來比較正常。

5-2        實驗成果

一切準備就緒後,即可開始進行編譯程式以及下載、燒錄、測試的工作;燒錄成功後,請點選ToolsSerial Monitor,並開始底下的測試:
1.   單音測試:在Serial Monitor輸入1,按Enter鍵或按Send,應可聽到單音的Do,且在Serial Monitor上顯示Tone 1,接著可試試輸入2,按EnterSend,可聽到Re,如下圖所示。
2.   連續音調測試:在Serial Monitor輸入CDEFGAB,然後按Enter,聽聽程式是否會依續發出第5八度音的DoSi;由於Serial Monitor具有串列緩衝區,因此不管我們在Serial Monitor中輸入多少字元,程式皆會逐一讀入字元,並逐一處理並發聲。
3.   輸入音調以外的字元測試:在Serial Monitor輸入533x422x1234555,然後按Enter,聽聽程式中指定字元'1''7''A''G'外的字元是如何處理的,其實由程式即可看得很清楚,指定字元外的字元是不發聲,但延遲一樣時間,故變成靜音。試一下底下這二個字串,你可以聽出是什麼歌嗎?雖然沒進行音長控制,但還是可聽出個大概。
(1) 533x422x1234555x533x422x13551
(2) 11135555666C5x4446333322225x511135555666C5x4446333322231

沒有留言: