上次Arduino小车无果而终之后,决定整点好玩的。没错,它来了,它来了,蜂鸣器带着它好听的音乐走来了。

所用材料

  1. Adruino uno一块
  2. 面包板一个
  3. 无源蜂鸣器一个
  4. 杜邦线若干

硬件接线

arduino 蜂鸣器
5V VCC
GND GND
8 I/O

image-20210403160903354

发出声音

前面我们已经把数字IO连接到了蜂鸣器的正极,让蜂鸣器响起来只需要在数字IO上放入方波即可。

1
2
3
4
digitalWrite(buzzerPin,HIGH); //高电平
delay(100);
digitalWrite(buzzerPin,LOW); //低电平
delay(100);

其中的100指的是发声后延时100ms

唱出旋律

如果只是发出响声的话,那也太鸡肋了吧?如果要发出精确的不同频率的乐音怎么办?难道还要算?(下面是一张乐音频率图)

音符表

算是不可能啦,这里直接把大佬们“翻译”好的代码搬了过来,感谢分享!下面三首“歌曲”可以试着听一下~

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#define NOTE_D0 -1
#define NOTE_D1 294
#define NOTE_D2 330
#define NOTE_D3 350
#define NOTE_D4 393
#define NOTE_D5 441
#define NOTE_D6 495
#define NOTE_D7 556

#define NOTE_DL1 147
#define NOTE_DL2 165
#define NOTE_DL3 175
#define NOTE_DL4 196
#define NOTE_DL5 221
#define NOTE_DL6 248
#define NOTE_DL7 278

#define NOTE_DH1 589
#define NOTE_DH2 661
#define NOTE_DH3 700
#define NOTE_DH4 786
#define NOTE_DH5 882
#define NOTE_DH6 990
#define NOTE_DH7 112
//以上部分是定义是把每个音符和频率值对应起来,其实不用打这么多,但是都打上了,后面可以随意编写D调的各种歌,我这里用NOTE_D+数字表示音符,NOTE_DH+数字表示上面有点的那种音符,NOTE_DL+数字表示下面有点的那种音符。这样后面写起来比较好识别。
#define WHOLE 1
#define HALF 0.5
#define QUARTER 0.25
#define EIGHTH 0.25
#define SIXTEENTH 0.625
//这部分是用英文对应了拍子,这样后面也比较好看
int tune[] =
{
NOTE_DH1,NOTE_D6,NOTE_D5,NOTE_D6,NOTE_D0,
NOTE_DH1,NOTE_D6,NOTE_D5,NOTE_DH1,NOTE_D6,NOTE_D0,NOTE_D6,
NOTE_D6,NOTE_D6,NOTE_D5,NOTE_D6,NOTE_D0,NOTE_D6,
NOTE_DH1,NOTE_D6,NOTE_D5,NOTE_DH1,NOTE_D6,NOTE_D0,

NOTE_D1,NOTE_D1,NOTE_D3,
NOTE_D1,NOTE_D1,NOTE_D3,NOTE_D0,
NOTE_D6,NOTE_D6,NOTE_D6,NOTE_D5,NOTE_D6,
NOTE_D5,NOTE_D1,NOTE_D3,NOTE_D0,
NOTE_DH1,NOTE_D6,NOTE_D6,NOTE_D5,NOTE_D6,
NOTE_D5,NOTE_D1,NOTE_D2,NOTE_D0,
NOTE_D7,NOTE_D7,NOTE_D5,NOTE_D3,
NOTE_D5,
NOTE_DH1,NOTE_D0,NOTE_D6,NOTE_D6,NOTE_D5,NOTE_D5,NOTE_D6,NOTE_D6,
NOTE_D0,NOTE_D5,NOTE_D1,NOTE_D3,NOTE_D0,
NOTE_DH1,NOTE_D0,NOTE_D6,NOTE_D6,NOTE_D5,NOTE_D5,NOTE_D6,NOTE_D6,
NOTE_D0,NOTE_D5,NOTE_D1,NOTE_D2,NOTE_D0,
NOTE_D3,NOTE_D3,NOTE_D1,NOTE_DL6,
NOTE_D1,
NOTE_D3,NOTE_D5,NOTE_D6,NOTE_D6,
NOTE_D3,NOTE_D5,NOTE_D6,NOTE_D6,
NOTE_DH1,NOTE_D0,NOTE_D7,NOTE_D5,
NOTE_D6,
};//这部分就是整首曲子的音符部分,用了一个序列定义为tune,整数

float duration[]=
{
1,1,0.5,0.5,1,
0.5,0.5,0.5,0.5,1,0.5,0.5,
0.5,1,0.5,1,0.5,0.5,
0.5,0.5,0.5,0.5,1,1,

1,1,1+1,
0.5,1,1+0.5,1,
1,1,0.5,0.5,1,
0.5,1,1+0.5,1,
0.5,0.5,0.5,0.5,1+1,
0.5,1,1+0.5,1,
1+1,0.5,0.5,1,
1+1+1+1,
0.5,0.5,0.5+0.25,0.25,0.5+0.25,0.25,0.5+0.25,0.25,
0.5,1,0.5,1,1,
0.5,0.5,0.5+0.25,0.25,0.5+0.25,0.25,0.5+0.25,0.25,
0.5,1,0.5,1,1,
1+1,0.5,0.5,1,
1+1+1+1,
0.5,1,0.5,1+1,
0.5,1,0.5,1+1,
1+1,0.5,0.5,1,
1+1+1+1
};//这部分是整首曲子的接拍部分,也定义个序列duration,浮点(数组的个数和前面音符的个数是一样的,一一对应么)
int length;//这里定义一个变量,后面用来表示共有多少个音符
int tonePin=8;//蜂鸣器的pin

void setup()
{
pinMode(tonePin,OUTPUT);//设置蜂鸣器的pin为输出模式
length = sizeof(tune)/sizeof(tune[0]);//这里用了一个sizeof函数,可以查出tone序列里有多少个音符
}

void loop()
{
for(int x=0;x<length;x++)//循环音符的次数
{
tone(tonePin,tune[x]);//此函数依次播放tune序列里的数组,即每个音符
delay(400*duration[x]);//每个音符持续的时间,即节拍duration,400是调整时间的越大,曲子速度越慢,越小曲子速度越快,自己掌握吧
noTone(tonePin);//停止当前音符,进入下一音符
}
delay(5000);//等待5秒后,循环重新开始
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#define A0 0
#define A1 441
#define A2 495
#define A3 556
#define A4 589
#define A5 661
#define A6 742

#define AL1 221
#define AL2 248
#define AL3 278
#define AL4 294
#define AL5 330
#define AL6 371
#define AL7 416

#define AH1 882
#define AH2 990
#define AH3 1112
#define AH4 1178
#define AH5 1322
#define AH6 1484
#define AH7 1665
/******************************************/

/********** 这部分是用英文对应了拍子 **********/
#define WHOLE 1
#define HALF 0.5
#define QUARTER 0.25
#define EIGHTH 0.25
#define SIXTEENTH 0.625
/******************************************/

/* 这部分就是整首曲子的音符部分,用了一个序列定义为tune,整数 */
int tune[] = {
A0,A0,A0,A3,A5,
A6,A0,A0,A5,A6,A0,A0,A5,
A6,AH1,A5,A6,A3,A0,A3,A5,
A6,A0,A0,A5,A6,A0,A0,A5,
A6,AH3,AH1,AH2,A6,A0,A3,A5,
A6,A0,A0,A5,A6,A0,A0,A5,
A6,AH1,A5,A6,A3,A5,A1,A2,
A3,AH1,A6,AH3,
AH2,AH3,AH2,AH1,AH2,A6,A0,
A6,A6,A6,A6,AH1,AH2,AH3,
A6,A6,A6,A5,A5,A6,
A6,A6,A6,A6,AH1,AH2,AH3,
A6,A6,A6,AH4,AH4,AH3,
A6,A6,A6,A6,AH1,AH2,AH3,
A6,A6,A6,A5,A5,A6,
A6,A6,A6,A6,AH1,AH2,AH3,
AH6,A5,A5,A6,A6
};
/****************************************************/

/* 这部分是整首曲子的接拍部分,也定义个序列duration,浮点(数组的个数和前面音符的个数是一样的) */
float duration[]= {
1,1,1,0.5,0.5,
0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,
0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,
0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,
0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,
0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,
0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,
1,1,1,1,
0.5,0.25,0.25,0.5,0.5,1,1,
1,1,1,0.25,0.25,0.25,0.25,
1,1,0.5,0.5,0.5,0.5,
1,1,1,0.25,0.25,0.25,0.25,
1,1,0.5,0.5,0.5,0.5,
1,1,1,0.25,0.25,0.25,0.25,
1,1,0.5,0.5,0.5,0.5,
1,1,1,0.25,0.25,0.25,0.25,
1+0.5,0.5,0.5,0.5,1
};
/**********************************************************************************/

int length; /* 这里定义一个变量,后面用来表示共有多少个音符 */
int tonePin=8; /* 蜂鸣器的pin */

void setup()
{
/* 设置蜂鸣器的pin为输出模式 */
pinMode(tonePin,OUTPUT);
/* 这里用了一个sizeof函数,可以查出tone序列里有多少个音符 */
length = sizeof(tune)/sizeof(tune[0]);
}

void loop()
{
/* 循环音符的次数 */
for(int x=0;x<length;x++){
/* 此函数依次播放tune序列里的数组,即每个音符 */
tone(tonePin,tune[x]);
/* 每个音符持续的时间,即节拍duration,450是调整时间的越大,曲子速度越慢 */
delay(450*duration[x]);
/* 停止当前音符,进入下一音符 */
noTone(tonePin);
}
/* 等待5秒,重新开始循环 */
delay(5000);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
#define NTC0 -1
#define NTC1 262
#define NTC2 294
#define NTC3 330
#define NTC4 350
#define NTC5 393
#define NTC6 441
#define NTC7 495
#define NTCL1 131
#define NTCL2 147
#define NTCL3 165
#define NTCL4 175
#define NTCL5 196
#define NTCL6 221
#define NTCL7 248
#define NTCH1 525
#define NTCH2 589
#define NTCH3 661
#define NTCH4 700
#define NTCH5 786
#define NTCH6 882
#define NTCH7 990

//列出全部C调的频率

#define WHOLE 1

#define HALF 0.5

#define QUARTER 0.25

#define EIGHTH 0.25

#define SIXTEENTH 0.625

//列出所有节拍

int tune[]= //根据简谱列出各频率

{

NTC5,NTC5,NTC6,

NTCH1,NTC6,NTC5,NTC6,NTCH1,NTC6,NTC5,

NTC3,NTC3,NTC3,NTC5,

NTC6,NTC6,NTC5,NTCH3,NTCH3,NTCH2,NTCH1,

NTCH2,NTCH1,NTCH2,

NTCH3,NTCH3,NTCH2,NTCH3,NTCH2,NTCH1,NTCH2,NTCH1,NTC6,



NTCH2,NTCH2,NTCH2,NTCH1,NTC6,NTC5,

NTC6,NTC5,NTC5,NTCH1,NTC6,NTC5,NTC1,NTC3,

NTC2,NTC1,NTC2,

NTC3,NTC5,NTC5,NTC3,NTCH1,NTC7,

NTC6,NTC5,NTC6,NTCH1,NTCH2,NTCH3,



NTCH3,NTCH2,NTCH1,NTC5,NTCH1,NTCH2,NTCH3,



NTCH2,NTC0,NTCH3,NTCH2,

NTCH1,NTC0,NTCH2,NTCH1,NTC6,NTC0,



NTCH2,NTC6,NTCH1,NTCH1,NTCH1,NTC6,NTC5,NTC3,

NTC5,

NTC5,NTC6,NTCH1,NTC7,NTC6,

NTCH3,NTCH3,NTCH3,NTCH3,NTCH2,NTCH2,NTCH1,

NTC6,NTCH3,NTCH2,NTCH1,NTCH2,NTCH1,NTC6,

NTCH1,

};

float durt[]= //根据简谱列出各节拍

{

0.5,0.25,0.25,

1.5,0.5,0.5,0.25,0.25,0.5,0.5,

1+1+1,0.5,0.25,0.25,

1.5,0.5,0.5,0.5,0.25,0.25,0.5,

1+1+1,0.5,0.5,

0.5,0.5,0.5,0.25,0.25,0.5,0.25,0.25,0.5,

0.5,0.5,0.5,0.25,0.25,1+1,

0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,

1+1+1,0.5,0.5,





1.5,0.5,0.5,0.5,0.5,0.5,

1.5,0.5,1,0.5,0.25,0.25,

1.5,0.5,0.5,0.5,0.5,0.25,0.25,

1+1+1,0.5,0.25,0.25,

1,0.5,0.25,0.25,1,1,

0.5,0.5,0.5,0.5,1,0.25,0.25,0.5,

1+1+1+1,

0.5,0.5,0.5,0.5,1+1,

0.5,0.5,0.5,0.5,1.5,0.25,0.25,

1.5,0.5,1,0.25,0.25,0.25,0.25,1+1+1+1,



};

int length;

int tonepin=8; //得用8号接口

void setup()

{

pinMode(tonepin,OUTPUT);

length=sizeof(tune)/sizeof(tune[0]); //计算长度

}

void loop()

{

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

{

tone(tonepin,tune[x]);

delay(500*durt[x]); //这里用来根据节拍调节延时,500这个指数可以自己调整,在该音乐中,我发现用500比较合适。

noTone(tonepin);

}
delay(5000);
}

美妙的音乐总是那么短暂,试听结束!

参考资料

[1] Arduino+蜂鸣器制作有趣的小音乐

[2] Arduino学习笔记—超简单制作音乐

[3] Arduino 蜂鸣器播放音乐