这篇文章来源于DevicePlus.com英语网站的翻译稿。不久前,我们研究了如何使用Raspberry Pi的I2C总线来控制Arduino Uno,以及如何使用它来输出模拟电压。
令人兴奋的是,完成这些项目后,您就已经掌握构建一个简单合成器的大部分方法了。
并且一家名叫dzl的制造商已经发布了一组名为the_synth的Arduino库,我们可以马上安装并使用该库。
那么,就让我们来一起完成这个项目吧!现在,我们来构建一个波表合成器。
“波表”合成器是什么意思?
一个波表合成器可以将一系列简单波形以不同电压电平波表文件的形式存储在存储器中。
合成器将这些电压以不同的速率输出,来产生相应频率的音调。
我们只需要存储每种波形的一个周期,这是一种可以高效节省内存的方法,因此非常适用于内存有限的简单微控制器。
在the_synth里,您可以在tables.h文件中找到波表。您也可以通过编辑该文件来创建自己的波表。
然后,我们通过把Arduino Uno的PWM硬件连接到低通滤波器,将内存中的这些数值转换为模拟电压,如之前的项目中所描述的那样。
所需部件
Raspberry Pi |
|
一个GPIO扩展板 |
|
一个无焊面包板 |
|
一个Arduino Uno |
|
一个1k欧姆电阻 |
|
一个10nF电容 |
|
一个220uF电容 |
|
一个有源扬声器 |
|
我一直使用的都是从二手商店花5美元购买的大型旧固态高保真音响。一些旧的电脑扬声器也是不错的选择。
安装示例
The_synth附带了许多示例用于演示其使用方法,我们可以直接使用它们。在深入研究代码之前,我们先试一下其中一个示例。
如果想要在您的Arduino IDE中安装库和其中的示例,请前往 https://github.com/dzlonline/the_synth并点击在页面右上方标有Code.的绿色按钮。
点击Download ZIP,并保存该文件。
现在打开Arduino IDE。在Sketch菜单中,将光标放在Include Library处,然后点击Add .ZIP library…。
找到我们之前保存的.zip文件,选择它并点击“OK”。
您现在已经成功将the_synth安装到了您的IDE中,并且可以从菜单中访问库和示例了。让我们试试any_hertz示例,它可以循环遍历四种不同的频率。
您可以打开“File”菜单,将鼠标停留在Examples处,然后滚动到底部至the_synth-master.找到该示例。将鼠标停留在该选择上,并点击any_hertz来打开草图。
现在通过USB连接Arduino Uno,请再次确认您选择了Arduino Uno,确认后上传草图。
接线
现在,我们需要将Arduino Uno连接到一个简单的低通滤波器,就像之前构建项目中所做的那样,然后将它连接到我们的扬声器。
首先,从连接电源引脚开始:
将引脚11(即PWM引脚)连接到面包板的中间。我们还需要接地来构建低通滤波器,因此将接地引脚连接到负电源轨。
现在构建低通滤波器。将1k电阻连接到PWM引脚,然后将10nF电容连接到电阻的另一端和接地轨,如下所示:
现在我们需要一个耦合电容器,以确保不会通过任何直流电。需要记住的一点是电解电容器是有极性的,因此请将阳极(较长端)连接到低通滤波器,另一端连接到面包板下方。
将扬声器连接到耦合电容器的阴极,如有需要可以接地。
如果您已经正确完成了所有连接,您现在将会听到一组包含四种音调的声音。
使用I2C 和Raspberry Pi控制合成器
您现在可以听到自己所构建的波表合成器所发出的声音了,是不是很酷?
但只是一遍又一遍地听着这四种音调并不是很有趣。我们想要能够使用Raspberry Pi对其进行控制。
我们可以在I2C总线上使用Arduino的Wire库和Python中的SMBus模块(我们之前介绍过)来完成此操作。
对Arduino Uno编程
我们真正需要做的是将这个any_hertz示例和之前编写的I2C程序整合在一起,以播放我们发送的音符。
我们先导入I2C和synth库。
- #include <Wire.h>
- #include <synth.h>
我们可以按照如下所示编写:
- 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
- }
- 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;
- }
- }
- void loop() {
- sleep(10000);
- }
连接I2C总线
这部分内容与我们在之前的文章中所介绍的完全相同:将Raspberry Pi的SDA引脚连接到Arduino Uno的A4引脚,将SCL引脚连接到A5引脚。
播放一首简单的歌曲
现在让我们用该项目来播放歌曲《Mary Had a Little Lamb》。
这首歌有两种不同长度的音符:四分音符和半音符(或二分音符)。我们现在来编写两个快速函数来播放这些音符。
我们需要计时功能,因此在这里导入sleep函数。
- from time import sleep
- def playCrotchet(int pitch):
- i2cbus.write_byte(pitch)
- sleep(0.472)
- i2cbus.write_byte(arduino, 0)
- sleep(0.02)
- 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)
- playMary()
下一步该做什么?
这是探索合成器构建方法的一个很好的开端:您还可以基于该内容制作一些很酷的低音线。
但是将所有音乐都写成代码是相当麻烦的,而且我们目前只有有限的音符和简单的波形。
接下来如果可以使用图形界面以及改变音符的音色不是会更好么?
请继续关注我们——我们将会很快进行这些内容的探索。
来源:techclass.rohm