arduino 習作工坊 - lesson 3 電音之夜
DESCRIPTION
Learn how to produce various sound via Arduino, and retrieve sond file from SD card module.TRANSCRIPT
#3 聲音與檔案存取
聲音• 聲音是通過物體振動產生的聲波。是通過
介質(空氣或固體、液體)傳播並能被人或動物聽覺器官所感知的波動現象。
• 聲音的頻率一般會以赫茲表示,記為 Hz ,指每秒鐘周期性變化的次數。而分貝是用來表示聲音強度的單位,記為 dB 。
資料來源:維基百科
聲音波形
模擬波形
聲音頻率頻率 , 單位為赫茲 ( 括號內為半音距離 ,"(0)" 為中央 C)
八度 0 1 2 3 4 5 6 7 8 9
C16.352 (−48)
32.703 (−36)
65.406 (−24)
130.81 (−12)
261.63 (0)
523.25 (+12)
1046.5 (+24)
2093.0 (+36)
4186.0 (+48)
8372.0 (+60)
D18.354 (−46)
36.708 (−34)
73.416 (−22)
146.83 (−10)
293.66 (+2)
587.33 (+14)
1174.7 (+26)
2349.3 (+38)
4698.6 (+50)
9397.3 (+62)
E20.602 (−44)
41.203 (−32)
82.407 (−20)
164.81 (−8)
329.63 (+4)
659.26 (+16)
1318.5 (+28)
2637.0 (+40)
5274.0 (+52)
10548 (+64)
F21.827 (−43)
43.654 (−31)
87.307 (−19)
174.61 (−7)
349.23 (+5)
698.46 (+17)
1396.9 (+29)
2793.8 (+41)
5587.7 (+53)
11175 (+65)
G24.500 (−41)
48.999 (−29)
97.999 (−17)
196.00 (−5)
392.00 (+7)
783.99 (+19)
1568.0 (+31)
3136.0 (+43)
6271.9 (+55)
12544 (+67)
A27.500 (−39)
55.000 (−27)
110.00 (−15)
220.00 (−3)
440.00 (+9)
880.00 (+21)
1760.0 (+33)
3520.0 (+45)
7040.0 (+57)
14080 (+69)
B30.868 (−37)
61.735 (−25)
123.47 (−13)
246.94 (−1)
493.88 (+11)
987.77 (+23)
1975.5 (+35)
3951.1 (+47)
7902.1 (+59)
15804 (+71)
MIDI樂器數位介面
MIDI
• 樂器數位介面( Musical Instrument Digital Interface ,簡稱 MIDI )是一個工業標準的電子通訊協定,為電子樂器等演奏裝置(如合成器)定義各種音符或彈奏碼,容許電子樂器、電腦、手機或其它的舞台演出配備彼此連接,調整和同步,得以即時交換演奏資料。
• MIDI 不傳送聲音,只傳送像是音調和音樂強度的資料,音量,顫音和相位等參數的控制訊號,還有設定節奏的時鐘信號。在不同的電腦上,輸出的聲音也因音源器不同而有差異。
MIDI 範例EX1
電路圖
程式 EX1
void setup() {
}
void loop() { tone(6, 440, 200); delay(200);
noTone(6);}
Pin6 播放「 A 」 midi 音,持續 0.2 秒
#include ”pitches.h”void setup() {
}
新增
tone(6, NOTE_A4, 200); delay(200);
更改
MIDI 範例EX2
電路圖
程式 EX2
void setup(){ }
void loop() { int sensor = analogRead(A0); if(sensor > 500) { tone(6, 440, 200); delay(200); noTone(6); }
else if (sensor < 200){ tone(6, 660, 200); delay(200); noTone(6); } else{ tone(6, 880, 200); delay(200); noTone(6); }}//end loop
Quiz
• Input A0 電位器: 0 ~ 1023• Output 頻率: 100 ~ 2000
• int x = map(analogRead(A0), 0, 1023, 100, 2000);
• tone(6, x , 200);
• 相同概念也可再用一個電位器來控制時間
新增函式: play()void setup(){}
void loop() { int sensor = analogRead(A0); if(sensor > 500) { play(); } else if (sensor < 200){ tone(6, 660, 200); delay(200); noTone(6); }
else{ tone(6, 880, 200); delay(200); noTone(6); }}//end loop
void play(){ tone(6, 200, 200); delay(200); noTone(6);}
新增函式: play(int freq)
void setup(){}
void loop() { int sensor = analogRead(A0); if(sensor > 500) { play(440); } else if (sensor < 200){ play(660); }
else{ play(880); }}//end loop
void play(int freq){ tone(6, freq, 200); delay(200); noTone(6);}
再開一個參數 duration
void play(int freq, int duration){ tone(6, freq, duration); delay(200); noTone(6);}
play(440, 200);play(392, 500);
音樂Music
SD Shield
SPI?
串列外設介面( Serial Peripheral Interface Bus , SPI ),類似 I²C ,是一種 4 線同步序列資料協定,適用於可攜式裝置平台系統,但使用率較I²C 少。串列外設介面一般是 4 線,有時亦可為 3線,有別於 I²C 的 2 線,以及 1-Wire 。
新增函式庫• 將「 SimpleSDAudio 」移至 \arduino\libraries 裡
音樂轉檔 (WAV→AFM)
\SimpleSDAudio\tools\Arduino with 16 MHz\converted
撥放音樂EX3
電路圖
SD 卡的電源與接地
程式解說 EX3 : setup()#include <SimpleSDAudio.h>
void setup(){ Serial.begin(9600); SdPlay.setSDCSPin(10); // 如 CS 腳位接在 #10 ,則需要本行,反之如接在 #4 則請刪除 SdPlay.init(SSDA_MODE_FULLRATE | SSDA_MODE_STEREO | SSDA_MODE_AUTOWORKER); if(!SdPlay.setFile(“MIKU.AFM”)) // 如果指定檔案不存在 { Serial.println(F(" not found on card! Error code: ")); Serial.println(SdPlay.getLastError()); // 取得錯誤碼 while(1); } }
程式解說 EX3 : loop()
void loop() { Serial.println(F("found.")); SdPlay.worker(); SdPlay.play(); // 播放檔案 //delay(104*1000); while(1);}
音樂撥放器,可選歌EX4
電路圖:同 EX3
確認 SD 卡if (!SdPlay.init(SSDA_MODE_FULLRATE | SSDA_MODE_MONO | SSDA_MODE_AUTOWORKER)) { Serial.println(F("initialization failed. Things to check:")); Serial.println(F("* is a card is inserted?")); Serial.println(F("* Is your wiring correct?")); Serial.println(F("* maybe you need to change the chipSelect pin to match your shield or module?")); Serial.print(F("Error code: ")); Serial.println(SdPlay.getLastError()); while(1); }
讀取 SD 卡內部資料 Serial.println(F("Files on card:")); SdPlay.dir(&DirCallback);
選擇檔案ReEnter: count = 0; Serial.println(F("\r\nEnter filename (send newline after input):")); do { while(!Serial.available()) ; c = Serial.read();…….
if(!SdPlay.setFile(AudioFileName)) { Serial.println(F(" not found on card! Error code: "));……
選擇狀態:透過 serial monitor 來控制
Serial.println(F("Press s for stop, p for play, h for pause, f to select new file, d for deinit, v to view status.")); flag = 1; while(flag) { SdPlay.worker(); // You can remove this line if you like - worker is not necessary if(Serial.available()) { c = Serial.read();
……
接下來可以做什麼 ?
• 音頻放大器• 逛逛電子商場• 找尋有趣的專題