這篇文章來源于DevicePlus.com英語網(wǎng)站的翻譯稿。
不久前,我們研究了如何使用Raspberry Pi的I2C總線來控制Arduino Uno,以及如何使用它來輸出模擬電壓。
令人興奮的是,完成這些項(xiàng)目后,您就已經(jīng)掌握構(gòu)建一個(gè)簡單合成器的大部分方法了。
并且一家名叫dzl的制造商已經(jīng)發(fā)布了一組名為the_synth的Arduino庫,我們可以馬上安裝并使用該庫。
那么,就讓我們來一起完成這個(gè)項(xiàng)目吧!現(xiàn)在,我們來構(gòu)建一個(gè)波表合成器。
“波表”合成器是什么意思?
一個(gè)波表合成器可以將一系列簡單波形以不同電壓電平波表文件的形式存儲(chǔ)在存儲(chǔ)器中。
合成器將這些電壓以不同的速率輸出,來產(chǎn)生相應(yīng)頻率的音調(diào)。
我們只需要存儲(chǔ)每種波形的一個(gè)周期,這是一種可以高效節(jié)省內(nèi)存的方法,因此非常適用于內(nèi)存有限的簡單微控制器。
在the_synth里,您可以在tables.h文件中找到波表。您也可以通過編輯該文件來創(chuàng)建自己的波表。
然后,我們通過把Arduino Uno的PWM硬件連接到低通濾波器,將內(nèi)存中的這些數(shù)值轉(zhuǎn)換為模擬電壓,如之前的項(xiàng)目中所描述的那樣。
所需部件
Raspberry Pi | |
一個(gè)GPIO擴(kuò)展板 | |
一個(gè)無焊面包板 | |
一個(gè)Arduino Uno | |
一個(gè)1k歐姆電阻 | |
一個(gè)10nF電容 | |
一個(gè)220uF電容 | |
一個(gè)有源揚(yáng)聲器 |
最好不要使用昂貴的有源揚(yáng)聲器來構(gòu)建和測試DIY合成器或音頻項(xiàng)目。雖然這樣的電路不一定會(huì)損壞您的東西,但是為什么要冒險(xiǎn)呢?
我一直使用的都是從二手商店花5美元購買的大型舊固態(tài)高保真音響。一些舊的電腦揚(yáng)聲器也是不錯(cuò)的選擇。
安裝示例
The_synth附帶了許多示例用于演示其使用方法,我們可以直接使用它們。在深入研究代碼之前,我們先試一下其中一個(gè)示例。
如果想要在您的Arduino IDE中安裝庫和其中的示例,請(qǐng)前往 https://github.com/dzlonline/the_synth并點(diǎn)擊在頁面右上方標(biāo)有Code.的綠色按鈕。
點(diǎn)擊Download ZIP,并保存該文件。
現(xiàn)在打開Arduino IDE。在Sketch菜單中,將光標(biāo)放在Include Library處,然后點(diǎn)擊Add .ZIP library…。
找到我們之前保存的.zip文件,選擇它并點(diǎn)擊“OK”。
您現(xiàn)在已經(jīng)成功將the_synth安裝到了您的IDE中,并且可以從菜單中訪問庫和示例了。讓我們?cè)囋嘺ny_hertz示例,它可以循環(huán)遍歷四種不同的頻率。
您可以打開“File”菜單,將鼠標(biāo)停留在Examples處,然后滾動(dòng)到底部至the_synth-master.找到該示例。將鼠標(biāo)停留在該選擇上,并點(diǎn)擊any_hertz來打開草圖。
現(xiàn)在通過USB連接Arduino Uno,請(qǐng)?jiān)俅未_認(rèn)您選擇了Arduino Uno,確認(rèn)后上傳草圖。
接線
現(xiàn)在,我們需要將Arduino Uno連接到一個(gè)簡單的低通濾波器,就像之前構(gòu)建項(xiàng)目中所做的那樣,然后將它連接到我們的揚(yáng)聲器。
首先,從連接電源引腳開始:
將引腳11(即PWM引腳)連接到面包板的中間。我們還需要接地來構(gòu)建低通濾波器,因此將接地引腳連接到負(fù)電源軌。
現(xiàn)在構(gòu)建低通濾波器。將1k電阻連接到PWM引腳,然后將10nF電容連接到電阻的另一端和接地軌,如下所示:
現(xiàn)在我們需要一個(gè)耦合電容器,以確保不會(huì)通過任何直流電。需要記住的一點(diǎn)是電解電容器是有極性的,因此請(qǐng)將陽極(較長端)連接到低通濾波器,另一端連接到面包板下方。
將揚(yáng)聲器連接到耦合電容器的陰極,如有需要可以接地。
如果您已經(jīng)正確完成了所有連接,您現(xiàn)在將會(huì)聽到一組包含四種音調(diào)的聲音。
使用I2C 和Raspberry Pi控制合成器
您現(xiàn)在可以聽到自己所構(gòu)建的波表合成器所發(fā)出的聲音了,是不是很酷?
但只是一遍又一遍地聽著這四種音調(diào)并不是很有趣。我們想要能夠使用Raspberry Pi對(duì)其進(jìn)行控制。
我們可以在I2C總線上使用Arduino的Wire庫和Python中的SMBus模塊(我們之前介紹過)來完成此操作。
對(duì)Arduino Uno編程
我們真正需要做的是將這個(gè)any_hertz示例和之前編寫的I2C程序整合在一起,以播放我們發(fā)送的音符。
我們先導(dǎo)入I2C和synth庫。
#include
#include
每個(gè)Arduino草圖都需要一個(gè)設(shè)置函數(shù),在我們的設(shè)置函數(shù)中,需要完成三件事情:作為從機(jī)加入I2C總線;初始化我們的合成器;以及在收到I2C指令時(shí)調(diào)用另一個(gè)函數(shù)。
我們可以按照如下所示編寫:
void setup() {
edgar.begin(); //-Start up a synth
edgar.setupVoice(0,TRIANGLE,60,ENVELOPE1,127,64); //-Set up voice 0
Wire.begin(0x8); // Join the I2C Bus as a slave at address 0x8
Wire.onReceive(readInstruction); // On
}
現(xiàn)在我們需要編寫readInstruction()函數(shù)。該函數(shù)用于從I2C總線讀取一個(gè)數(shù)字。如果讀取了0,那么將不播放任何東西。如果讀取了1到8之間的數(shù)字,那么將會(huì)播放A1到A2之間的一個(gè)音符。
void readInstruction(int bitstream) {
byte option = Wire.read();
switch (option) {
case 0:
edgar.setFrequency(0, 0.0); // Play nothing
edgar.trigger(0);
break;
case 1:
edgar.setFrequency(0, 55.0); // Play A1
edgar.trigger(0);
break;
case 2:
edgar.setFrequency(0, 61.74); // Play B1
edgar.trigger(0);
break;
case 3:
edgar.setFrequency(0, 65.41); // Play C2
edgar.trigger(0);
break;
case 4:
edgar.setFrequency(0, 73.42); // Play D2
edgar.trigger(0);
break;
case 5:
edgar.setFrequency(0, 82.41); // Play E2
edgar.trigger(0);
break;
case 6:
edgar.setFrequency(0, 87.31); // Play F2
edgar.trigger(0);
break;
case 7:
edgar.setFrequency(0, 98.0); // Play G2
edgar.trigger(0);
break;
case 8:
edgar.setFrequency(0, 110.0); // Play A2
edgar.trigger(0);
break;
}
}
最后,每個(gè)Arduino草圖都需要一個(gè)循環(huán)函數(shù)。但實(shí)際上我們沒有需要循環(huán)運(yùn)行的工作,所以我們只在其中寫入一個(gè)sleep函數(shù)。
void loop() {
sleep(10000);
}
保存該草圖,并將其上傳到您的Arduino Uno。
連接I2C總線
這部分內(nèi)容與我們?cè)谥暗奈恼轮兴榻B的完全相同:將Raspberry Pi的SDA引腳連接到Arduino Uno的A4引腳,將SCL引腳連接到A5引腳。
播放一首簡單的歌曲
現(xiàn)在讓我們用該項(xiàng)目來播放歌曲《Mary Had a Little Lamb》。
這首歌有兩種不同長度的音符:四分音符和半音符(或二分音符)。我們現(xiàn)在來編寫兩個(gè)快速函數(shù)來播放這些音符。
我們需要計(jì)時(shí)功能,因此在這里導(dǎo)入sleep函數(shù)。
from time import sleep
但是中間需要暫停多久?我們的歌曲是每分鐘122拍。根據(jù)該數(shù)值,我們可以計(jì)算出每個(gè)音符需要多少秒:四分音符是492微秒。我們?cè)诮Y(jié)尾處設(shè)置一段非常短的暫停,以便能夠在播放相同音調(diào)時(shí)分辨這些音符。
def playCrotchet(int pitch):
i2cbus.write_byte(pitch)
sleep(0.472)
i2cbus.write_byte(arduino, 0)
sleep(0.02)
現(xiàn)在我們來寫一個(gè)半音符函數(shù):
def playMinim(int pitch):
i2cbus.write_byte(pitch)
sleep(0.964)
i2cbus.write_byte(arduino, 0)
sleep(0.02)
然后:
def playMary():
playCrotchet(E2)
playCrotchet(D2)
playCrotchet(C2)
playCrotchet(D2)
playCrotchet(E2)
playCrotchet(E2)
playMinim(E2)
playCrotchet(D2)
playCrotchet(D2)
playMinim(D2)
playCrotchet(E2)
playCrotchet(G2)
playMinim(G2)
playCrotchet(E2)
playCrotchet(D2)
playCrotchet(C2)
playCrotchet(D2)
playCrotchet(E2)
playCrotchet(E2)
playCrotchet(E2)
playCrotchet(E2)
playCrotchet(D2)
playCrotchet(D2)
playCrotchet(E2)
playCrotchet(D2)
playMinim(C2)
想要播放該歌曲,請(qǐng)輸入:
playMary()
多嘗試一些內(nèi)容,看看有沒有什么新的想法。
下一步該做什么?
這是探索合成器構(gòu)建方法的一個(gè)很好的開端:您還可以基于該內(nèi)容制作一些很酷的低音線。
但是將所有音樂都寫成代碼是相當(dāng)麻煩的,而且我們目前只有有限的音符和簡單的波形。
接下來如果可以使用圖形界面以及改變音符的音色不是會(huì)更好么?
請(qǐng)繼續(xù)關(guān)注我們——我們將會(huì)很快進(jìn)行這些內(nèi)容的探索。
DevicePlus 編輯團(tuán)隊(duì)
設(shè)備升級(jí)版適用于所有熱愛電子和機(jī)電一體化的人。
審核編輯黃宇
-
合成器
+關(guān)注
關(guān)注
0文章
273瀏覽量
25356 -
Arduino
+關(guān)注
關(guān)注
188文章
6468瀏覽量
186956 -
Raspberry Pi
+關(guān)注
關(guān)注
2文章
558瀏覽量
22196
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論