arduino实验–音乐演奏

之前用有源蜂鸣器做了一个警报器,但是警报器实在不太悦耳,接下来我们只做一个音乐演奏器。

需要的元器件(我从破旧玩具里面拆了一个喇叭来当做扬声器):

塑胶玩具喇叭

使用电路:

456221947722664314

代码如下:

#define NOTE_C3  262
#define NOTE_CS3 277
#define NOTE_D3  294
#define NOTE_DS3 311
#define NOTE_E3  330
#define NOTE_F3  349
#define NOTE_FS3 370
#define NOTE_G3  392
#define NOTE_GS3 415
#define NOTE_A3  440
#define NOTE_AS3 466
#define NOTE_B3  494
#define NOTE_C4  523
#define NOTE_CS4 554
#define NOTE_D4  587
#define NOTE_DS4 622
#define NOTE_E4  659
#define NOTE_F4  698
#define NOTE_FS4 740
#define NOTE_G4  784
#define NOTE_GS4 831
#define NOTE_A4  880
#define NOTE_AS4 932
#define NOTE_B4  988

#define WHOLE 1
#define HALF 0.5
#define QUARTER 0.25
#define EIGHTH 0.125
#define SIXTEENTH 0.0625

int tune[] = { NOTE_F3, NOTE_F3, NOTE_F3, NOTE_C3, NOTE_A3,NOTE_A3,NOTE_A3,NOTE_F3, NOTE_F3, NOTE_A3, NOTE_C4, NOTE_C4, NOTE_AS3, NOTE_A3, NOTE_G3, NOTE_G3, NOTE_A3, NOTE_AS3, NOTE_AS3, NOTE_A3, NOTE_G3, NOTE_A3, NOTE_F3, NOTE_F3, NOTE_A3, NOTE_G3, NOTE_C3, NOTE_E3, NOTE_G3, NOTE_F3};


float duration[] = {EIGHTH+SIXTEENTH, SIXTEENTH, QUARTER, QUARTER, EIGHTH+SIXTEENTH, SIXTEENTH, QUARTER, QUARTER, EIGHTH+SIXTEENTH, SIXTEENTH, QUARTER+EIGHTH, EIGHTH, EIGHTH, EIGHTH, HALF, EIGHTH, SIXTEENTH, QUARTER, QUARTER, EIGHTH+SIXTEENTH, SIXTEENTH, QUARTER, QUARTER, EIGHTH+SIXTEENTH, SIXTEENTH, QUARTER+EIGHTH, EIGHTH, EIGHTH, SIXTEENTH, HALF};

int length;

void setup() {
  	pinMode(8, OUTPUT);
  	length = sizeof(tune) / sizeof(tune[0]);
}

void loop() {
  	for (int x=0; x<length; x++) {
    		tone(8, tune[x]);
    		delay(1500 * duration[x]);
    		noTone(8);
  	}
  	delay(5000);
}

上传代码后,扬声器就可以开始演奏音乐了。

代码解释:

上面代码有一长串define命令。#define仅仅是定义一个值和它的替代符号,例如:

#define PI 3.14159265358979323846264338327950288419716939937510

定义完后,就允许在任何计算中使用字符“PI”代替圆周率,而不用输入圆周率的50位有效数字。而在本项目中,我们创建了一系列的define指令,它代替的是从C3到B4这些产生声音所需要的频率值。在下面的音乐中的第一个音符为F3,它对应的频率是349Hz,这是音节中的低音4.(音符对应的频率可以百度)

下面5个define指令定义音符的长度。音符按长度分为整拍,半拍,1/4拍,1/8拍和1/16拍。我们将用这些数字乘以拍的长度(以毫秒为单位)去获得每个音符的长度。例如1/4拍音符的数字是0.25,因此0.25乘以拍长度获得1/4音符:

1500*0.25=.75ms

接下来定义了一个叫tune[]的整型数组,并用“新年好”的音调初始化该数组,如下:

int tune[] = { NOTE_F3, NOTE_F3, NOTE_F3, NOTE_C3, NOTE_A3,NOTE_A3,NOTE_A3,NOTE_F3, NOTE_F3, NOTE_A3, NOTE_C4, NOTE_C4, NOTE_AS3, NOTE_A3, NOTE_G3, NOTE_G3, NOTE_A3, NOTE_AS3, NOTE_AS3, NOTE_A3, NOTE_G3, NOTE_A3, NOTE_F3, NOTE_F3, NOTE_A3, NOTE_G3, NOTE_C3, NOTE_E3, NOTE_G3, NOTE_F3};

之后定义另一个数组和一个浮点数,它存储每个音符演奏时所持续的时间:

float duration[] = {EIGHTH+SIXTEENTH, SIXTEENTH, QUARTER, QUARTER, EIGHTH+SIXTEENTH, SIXTEENTH, QUARTER, QUARTER, EIGHTH+SIXTEENTH, SIXTEENTH, QUARTER+EIGHTH, EIGHTH, EIGHTH, EIGHTH, HALF, EIGHTH, SIXTEENTH, QUARTER, QUARTER, EIGHTH+SIXTEENTH, SIXTEENTH, QUARTER, QUARTER, EIGHTH+SIXTEENTH, SIXTEENTH, QUARTER+EIGHTH, EIGHTH, EIGHTH, SIXTEENTH, HALF};

通过观察这些数组可以看到,使用define指令定义音调和音调长度比直接用数字表示更容易理解。

在setup函数中我们使用sizeof()函数获得数组的音符数。用数组中的音符数初始化整型数length:

length = sizeof(tune) / sizeof(tune[0]);

sizeof函数返回传递给他的参数的字节数。在Arduino中,一个整数由两个字节组成,一个字节由8个比特组成。我们的tunes[]中有30个元素,通过以下计算可以得到整个数组的大小(以字节为单位)。

sizeof(tune)

并且初一个元素的字节数

sizeof(tune[0])

在这里,它相当于

60/2=30

如果你用字节的音调数组代替这个项目里的音调数组,length的值则等于你的音调数组中音符的数目。

sizeof()函数在计算不同数据类型的数据长度方面是非常有用的,尤其是需要输出代码给另一个设备而这个设备数据类型长度可能与arduino中的不同的时候。

在主循环中,设置了一个for循环,它的循环次数为音乐中的音符数:

for (int x=0; x<length; x++)

之后通过数字引脚8演奏tune[]数组中的下一个音符:

tone(8, tune[x]);

最后延时适当的时间,让音乐继续演奏:

 delay(1500 * duration[x]);

延时时间是1500ms乘以音符的长度,在演奏下一个音符之前,停止引脚8上产生的声音:

noTone(8);

这可以保证两个相同的音符连续演奏时能区分每一个。没有noTone()函数,两个相同的音符就会混合成一个拉长的音符。

最后,for循环完成之后,在再次演奏音乐之前延时5s:

delay(5000);

为了产生这首音乐,我在百度上找了新年好的乐谱。然后输入tune[]数组中,音符的长度存入duration[]数组中。你可以按照自己的爱好,输入其他的音乐。

如果想要加快或者放慢曲谱节奏,只要改变延时函数中1500这个数值,将它变大或变小即可。

0 Comments
Leave a Reply