Try   HackMD

Arduino 教學 5:利用光敏電阻控制蜂鳴器

作者:王一哲
日期:2016/9/13

所需元件

  1. 光敏電阻1個
  2. 10kΩ電阻1個
  3. 蜂鳴器或喇叭1個
  4. 麵包板1塊
  5. Arduino Uno開發板1塊
  6. 麵包板連接線數條
Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
線路圖

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
實際的裝置照片(連接蜂鳴器)

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →
實際的裝置照片(連接喇叭)

控制蜂鳴器或喇叭發出指定頻率的聲音

方法1:由頻率算出蜂鳴器發聲、不發聲的持續時間

/* 實驗3-1:指定無源蜂鳴器發聲頻率 * * 不使用tone * * 日期:Sep. 8, 2016 * * 作者:王一哲 */ int buzzerPin = 3; int frequency = 262; // 31 Hz ~ 4978 Hz float dt = 1./(float(frequency)*2.)*1000000.; //由頻率換算延遲時間,單位為microsecond void setup() { pinMode(buzzerPin, OUTPUT); Serial.begin(9600); Serial.println(dt); } void loop() { digitalWrite(buzzerPin, HIGH); delayMicroseconds(int(dt)); digitalWrite(buzzerPin, LOW); delayMicroseconds(int(dt)); }

這是最直接但不方便的方法,由於聲音頻率較高,延遲時間極短,必須以μs(百萬分之1秒)為單位,算式如下

float dt = 1./(float(frequency)*2.)*1000000.;

延遲時間則寫為

delayMicroseconds(int(dt));

方法2:使用內建函數tone

/* 實驗3-2:指定無源蜂鳴器發聲頻率 * * 使用tone * * 日期:Sep. 8, 2016 * * 作者:王一哲 */ int buzzerPin = 3; void setup() { pinMode(buzzerPin, OUTPUT); Serial.begin(9600); } void loop() { tone(buzzerPin, 262); //31Hz ~ 4978Hz }

Arduino有內建的聲音函數tone,但要將蜂鳴器的正極接腳接在支援PWM的腳位3或11,詳細的說明請參考Arduino的說明文件。寫法如下

tone(pin, 頻率)tone(pin, 頻率, 持續時間)

利用光敏電阻控制蜂鳴器

這裡所使用的光敏電阻是最常見、最便宜的規格,當光敏電阻照到光時電阻值減少,沒照到光時則電阻值增加,範圍約為2kΩ ~ 980kΩ。若將光敏電阻串聯1個10kΩ的固定電阻,兩端接上+5V的電壓,就是一個簡單的分壓電路。由於我將+5V先接到光敏電阻再接到固定電阻,當光敏電阻照到光時電阻值減少,固定電阻分到的電壓增加;反之則降低。我們可以先寫一個最簡單的程式來測試一下。

/* 3-5:利用光敏電阻的分壓電路 * * 日期:Sep. 8, 2016 * * 作者:王一哲 */ int potPin = 0; //定義讀取電壓值的接腳 int val = 0 ; //定義讀取數值暫存用的變數 //光敏電阻範圍約2kOhm ~ 980kOhm //串聯10kOhm固定電阻 void setup() { pinMode(potPin, INPUT); //定義讀取電壓值的接腳為輸入 Serial.begin(9600); } void loop() { val = analogRead(potPin); //val = 0 ~ 1023 Serial.println(val); }

當我們確定光敏電阻及蜂鳴器都能正常運作後,就能將兩個部分結合起來,利用光敏電阻照光的程度控制蜂鳴器的發聲頻率。

/* 實驗3-6:光敏電阻控制無源蜂鳴器發聲頻率 * * 日期:Sep. 8, 2016 * * 作者:王一哲 */ int buzzerPin = 3; //定義連接蜂鳴器的接腳 int potPin = 0; //定義讀取電壓值的接腳 int val = 0 ; //定義讀取數值暫存用的變數 int frequency; //發聲頻率,31Hz ~ 4978Hz //光敏電阻範圍約2kOhm ~ 980kOhm //串聯10kOhm固定電阻 void setup() { pinMode(buzzerPin, OUTPUT); pinMode(potPin, INPUT); //定義讀取電壓值的接腳為輸入 Serial.begin(9600); } void loop() { val = analogRead(potPin); frequency = map(val, 200, 1000, 31, 4978); tone(buzzerPin, frequency, 200); Serial.print("val = "); Serial.print(val); Serial.print(" frequency = "); Serial.println(frequency); }

pitches.h及演奏曲子

由於每個音高會對應到特定的頻率,但這些頻率並不好記,因此就有熱心人士將兩者對應的關係寫成 pitches.h ,我們可以從Arduino官網上找到(https://www.arduino.cc/en/Tutorial/ToneMelody)。開啟文字編輯器,將該頁面的內容複製、貼上,存成 pitches.h ,再建立一個名為 pitches 的新資料夾,將 pitches.h 移到資料夾內,最後將資料夾移到Arduino開發程式的資料夾內即可。可能的路徑為

  1. Windows環境 C:\Program Files (x86)\Arduino\libraries\
  2. Linux環境 home/<user name>/Arduino/libraries 或 home/<user name>/sketchbook/libraries

接下來在程式碼的開頭只要加上 #include "pitches.h" 即可引用。之前我為了某次研習寫了一個小程式,當盒蓋打開時讓蜂鳴器或喇叭演奏一小段曲子,當時就是利用了 pitches.h,有興趣的同學可以參考。

/* 實驗3-4(示範用):用無源蜂鳴器演奏曲子 * * 使用pitches.h * * 日期:Sep. 8, 2016 * * 作者:王一哲 */ #include "pitches.h" #define NOTE_ 0 int buzzerPin = 3; //設定曲子 int tempo = 30; //每分鐘幾拍 float dt = 1000.0*60.0/float(tempo); //換算1拍的時間長度單位為ms //The prelude of Final Fantasy 3 int melody[]={NOTE_AS3, NOTE_C3, NOTE_D3, NOTE_F3, NOTE_AS3, NOTE_C4, NOTE_D4, NOTE_F4, NOTE_AS4, NOTE_C5, NOTE_D5, NOTE_F5, NOTE_AS5, NOTE_C6, NOTE_D6, NOTE_F6, NOTE_AS6, NOTE_F6, NOTE_D6, NOTE_C6, NOTE_AS5, NOTE_F5, NOTE_D5, NOTE_C5, NOTE_AS4, NOTE_F4, NOTE_D4, NOTE_C4, NOTE_AS3, NOTE_F3, NOTE_D3, NOTE_C3, NOTE_F3, NOTE_A3, NOTE_AS3, NOTE_D3, NOTE_F3, NOTE_A3, NOTE_AS3, NOTE_D4, NOTE_G4, NOTE_A4, NOTE_AS4, NOTE_D5, NOTE_G5, NOTE_A5, NOTE_AS5, NOTE_D6}; int noteDurations[] = {16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}; // 計算陣列長度,sizeof 是回傳陣列所佔的 bytes 而非長度,要算出真正的長度要再除以 sizeof(DataType) int arrayLen = sizeof(melody)/sizeof(int); // 設定函數,讀陣列 melody 及 noteDrations 並輸入到 tone void play(int *melody, int *noteDurations) { for(int i=0; i < arrayLen; i++) { int noteDuration = int(dt/float(noteDurations[i])); Serial.print(melody[i]); Serial.println(noteDurations[i]); tone(buzzerPin, melody[i], noteDuration); int pauseBetweenNotes = int(noteDuration * 1.30); delay(pauseBetweenNotes); noTone(buzzerPin); } } void setup() { pinMode(buzzerPin, OUTPUT); Serial.begin(9600); } void loop() { play(melody, noteDurations); noTone(buzzerPin); delay(2000); }


tags:Arduino