數字制造講義01-成為數字世界的建造者
數字制造講義02-Arduino入門
數字制造講義03-電路基礎
數字制造講義04-負責輸入和輸出的智能元件
數字制造講義05-軟硬件數據通信
數字制造講義06-MIDI 和 OSC 數據傳輸練習
數字制造講義07-Arduino聲音應用
(本系列為 00 在星海音樂學院的課程講義)
回顧
還記得上一周 完成的三個練習嗎:
- 讓蜂鳴器發聲
- 蜂鳴器發出交替的報警聲
- 用按鍵觸發聲音
這一周我們繼續來完善,做出一個簡單的旋律控制器。
挑戰4:用電位計控制音高
既然蜂鳴器可以發出不同的音高,那我們可不可以用旋鈕控制音高,做一個 mini 的極簡控制器呢?
在之前第四周的課程中,我們已經建立起比較完整的輸入輸出元件的概念。在項目練習時就可以慢慢養成習慣:在動手之前,先構想出輸入部分是什么、輸出部分是什么、從輸入到輸出要完成什么樣的轉換。
這里,輸入部分是電位計(的位置),輸出部分是蜂鳴器(的音高),中間的連接就是電位計的數值轉換為蜂鳴器的音高。
接線部分,使用的元件包括:蜂鳴器,電位計。
當我們還是編程新手,每次要開始自己寫代碼時,容易兩眼一抹黑,不知道該從哪里下手。
其實,每次寫代碼時,并不是直接打開 Arduino IDE 就開始噼里啪啦敲代碼了。在這之前,我們需要現在腦子里構思這個代碼要做什么,怎么做到。
大家會想一下,怎么把大象放進冰箱里呢?
不要笑,這就是所謂的「算法」:做一件事情的步驟。
所以在還沒有清晰思路的時候,我們可以先把程序要完成的大致步驟寫下來:
- 需要用一個模擬端口讀取電位計的數值
- 需要用一個數字(輸出)端口給蜂鳴器發出指令
- 找一個辦法讓蜂鳴器發出不同音高
- 將電位計數值控制音高
接著,我們再想辦法把每一個步驟都轉化成對應的變量、語法、庫。所以學會搜索和查看官方文檔就很重要的了。
代碼如下:
// connect a potentiometer to pin A0
int buzzerPin=8;
int potPin=A0;
void setup() {
pinMode(buzzerPin, OUTPUT);
}
void loop() {
int freq = analogread(A0);
freq = map (freq,0,1023,20,20000); //map the value read from the potentiometer into the audible range
tone (buzzerPin,freq);
}
上面的代碼中,最核心的一行,是把從電位計讀取的模擬信號數值(范圍是 01023),映射到人耳可感知的聲音的頻率范圍(2020000):freq = map (freq,0,1023,20,20000);
其中 map() 函數的作用就是數值映射。
挑戰5:播放連續音高
這個挑戰一定會更吸引你:用蜂鳴器播放一段旋律。
這個挑戰的難度主要在代碼上,從這里開始,我們會開始接觸并深入理解函數、循環、頭文件、庫等概念。
比較復雜的代碼不可能一下子就能寫出來。所以我們要經歷一個重要的練習:看懂別人的代碼。
我們在官方網站上找到教程 Arduino - ToneMelody。仔細研讀它給出的代碼,尤其是代碼的注釋:
/*
Melody
Plays a melody
circuit:
- 8 ohm speaker on digital pin 8
created 21 Jan 2010
modified 30 Aug 2011
by Tom Igoe
This example code is in the public domain.
http://www.arduino.cc/en/Tutorial/Tone
*/
#include "pitches.h"
// notes in the melody:
int melody[] = {
NOTE_C4, NOTE_G3, NOTE_G3, NOTE_A3, NOTE_G3, 0, NOTE_B3, NOTE_C4
};
// note durations: 4 = quarter note, 8 = eighth note, etc.:
int noteDurations[] = {
4, 8, 8, 4, 4, 4, 4, 4
};
void setup() {
// iterate over the notes of the melody:
for (int thisNote = 0; thisNote < 8; thisNote++) {
// to calculate the note duration, take one second divided by the note type.
//e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc.
int noteDuration = 1000 / noteDurations[thisNote];
tone(8, melody[thisNote], noteDuration);
// to distinguish the notes, set a minimum time between them.
// the note's duration + 30% seems to work well:
int pauseBetweenNotes = noteDuration * 1.30;
delay(pauseBetweenNotes);
// stop the tone playing:
noTone(8);
}
}
void loop() {
// no need to repeat the melody.
}
把注釋部分全部替換成自己的理解,這個代碼看起來就不再那么復雜和難懂了。但是這個過程一定要自己完成。
當在代碼里看到不熟悉的函數,例如 delay()
, noTone()
,就可以到官方文檔中搜索并閱讀,一般文檔都會給出例子,這些例子就是最好的學習材料。
最后,留給大家的作業,是用兩個壓電片觸發兩段不同的旋律,大家動手試試吧!
<iframe frameborder="0" src="https://v.qq.com/txp/iframe/player.html?vid=p08632k4vzj" allowFullScreen="true"></iframe>