zoey不种土豆 发表于 2024-11-19 10:43:26

Arduino入门教程16--音乐蜂鸣器「DFR0100」

本帖最后由 zoey不种土豆 于 2024-11-19 17:36 编辑

在之前的课程中,我们学会了如何控制蜂鸣器发出不同的声音。那么,我们是否可以通过调整声音的频率和节拍,来组合出一段完整的旋律呢?在这个项目中,我们将使用蜂鸣器演奏音乐,并学习如何创建头文件(.h文件),以导入别人已经编写好的“曲谱”。在使用Arduino IDE编程时,每创建一个项目文件被称为一个“Sketch”。一个Sketch中可以包含多个代码文件。为了避免程序代码过长且不易阅读,可以在主文件中编写程序的主要逻辑部分,而将程序的独立功能模块存放在其他文件中,以便于管理和维护。这种做法不仅提高了代码的可读性,还便于功能的复用和扩展。
元件清单
硬件连接按如下连线图连接,注意蜂鸣器引脚正(+),负(-)。标有+的引脚接到数字口8,另一个接GND。蜂鸣器的正负极通过盖子上的+符号查看。图 1 音乐蜂鸣器连线图
示例代码样例代码 - Main Sketch:
//项目 - 音乐蜂鸣器
#include "pitches.h"// 包含一个头文件

int melody[] = {
NOTE_C4, NOTE_G3, NOTE_G3, NOTE_A3, NOTE_G3, 0, NOTE_B3, NOTE_C4
};// 旋律中的音符序列

int noteTypes[] = {
4, 8, 8, 4, 4, 4, 4, 4
};// 每个音符的类型:4 = 四分音符,8 = 八分音符

void setup() {

for (int thisNote = 0; thisNote < 8; thisNote++) {
int noteDuration = 1000 / noteTypes;
// 计算音符的持续时间:1秒 / 音符类型
tone(8, melody, noteDuration);
// 在引脚8上播放音符
int pauseBetweenNotes = noteDuration * 1.30;
// 根据音符持续时间计算暂停时间,使旋律听起来更自然
    delay(pauseBetweenNotes);// 音符之间的暂停
    noTone(8);// 停止在引脚8上播放的音调
}
}

void loop() {
// 不需要重复播放旋律
}要创建一个新的头文件,点击串口监视器下方的按钮,选择新建标签页,输入文件名pitches.hPitches.h:#define NOTE_B031
#define NOTE_C133
#define NOTE_CS1 35
#define NOTE_D137
#define NOTE_DS1 39
#define NOTE_E141
#define NOTE_F144
#define NOTE_FS1 46
#define NOTE_G149
#define NOTE_GS1 52
#define NOTE_A155
#define NOTE_AS1 58
#define NOTE_B162
#define NOTE_C265
#define NOTE_CS2 69
#define NOTE_D273
#define NOTE_DS2 78
#define NOTE_E282
#define NOTE_F287
#define NOTE_FS2 93
#define NOTE_G298
#define NOTE_GS2 104
#define NOTE_A2110
#define NOTE_AS2 117
#define NOTE_B2123
#define NOTE_C3131
#define NOTE_CS3 139
#define NOTE_D3147
#define NOTE_DS3 156
#define NOTE_E3165
#define NOTE_F3175
#define NOTE_FS3 185
#define NOTE_G3196
#define NOTE_GS3 208
#define NOTE_A3220
#define NOTE_AS3 233
#define NOTE_B3247
#define NOTE_C4262
#define NOTE_CS4 277
#define NOTE_D4294
#define NOTE_DS4 311
#define NOTE_E4330
#define NOTE_F4349
#define NOTE_FS4 370
#define NOTE_G4392
#define NOTE_GS4 415
#define NOTE_A4440
#define NOTE_AS4 466
#define NOTE_B4494
#define NOTE_C5523
#define NOTE_CS5 554
#define NOTE_D5587
#define NOTE_DS5 622
#define NOTE_E5659
#define NOTE_F5698
#define NOTE_FS5 740
#define NOTE_G5784
#define NOTE_GS5 831
#define NOTE_A5880
#define NOTE_AS5 932
#define NOTE_B5988
#define NOTE_C61047
#define NOTE_CS6 1109
#define NOTE_D61175
#define NOTE_DS6 1245
#define NOTE_E61319
#define NOTE_F61397
#define NOTE_FS6 1480
#define NOTE_G61568
#define NOTE_GS6 1661
#define NOTE_A61760
#define NOTE_AS6 1865
#define NOTE_B61976
#define NOTE_C72093
#define NOTE_CS7 2217
#define NOTE_D72349
#define NOTE_DS7 2489
#define NOTE_E72637
#define NOTE_F72794
#define NOTE_FS7 2960
#define NOTE_G73136
#define NOTE_GS7 3322
#define NOTE_A73520
#define NOTE_AS7 3729
#define NOTE_B73951
#define NOTE_C84186
#define NOTE_CS8 4435
#define NOTE_D84699
#define NOTE_DS8 4978
代码回顾在这个项目中,我们新建了pitches.h文件,并复制了一段代码。从项目【温度报警器】中我们了解到,不同的频率会产生不同的音调。而我们复制的这段代码是最初由 Brett Hagman 编写的音符表,包含了所有典型音符所对应的频率。比如,NOTE_C4 是中央C音,对应的频率是262。有了这张音符表,我们就可以通过输入音符的名称来编写旋律了。在Main Sketch中使用了#include语法来导入了新建的文件或外部库,将不同的文件关联起来。在程序中,我们首先创建了两个数组来按顺序储存音调与节奏。int melody[] = {
NOTE_C4, NOTE_G3, NOTE_G3, NOTE_A3, NOTE_G3, 0, NOTE_B3, NOTE_C4
};
int noteTypes[] = {
4, 8, 8, 4, 4, 4, 4, 4
};上面这个数组noteTypes[] 定义了每个音符的持续时间。这里使用的是一种简化的表示方法,其中数字代表音符的“类型”,而不是确切的毫秒数。例如,4代表四分音符,8代表八分音符。实际的持续时间将在setup()函数中计算得出。
数组是一个变量的集合,可以通过索引号来找到数组中的元素。可以看出我们创建的数组中分别有8个元素。数组是从0开始索引的,因此数组中的8个元素的索引号是0~7。
在本程序中旋律只会播放一次,因此我们在setup里编写播放音符的程序。
通过一个for循环,来遍历数组中的每一个元素,通过变量thisNote表示目前的元素索引号。
for (int thisNote = 0; thisNote < 8; thisNote++) {
int noteDuration = 1000 / noteTypes;
// 计算音符的持续时间:1秒 / 音符类型
tone(8, melody, noteDuration);
// 在引脚8上播放音符
int pauseBetweenNotes = noteDuration * 1.30;
// 根据音符持续时间计算暂停时间,使旋律听起来更自然

    delay(pauseBetweenNotes);// 音符之间的暂停
    noTone(8);// 停止在引脚8上播放的音调
}在循环中,首先计算了音符的持续时间。在音乐的定义中,四分音符占一个小节的1/4,因此可以通过小节时间(这里设置的是1秒)除以4来计算每个音符的持续时间。
然后使用tone()函数设置引脚,frequency和duration,来播放音符。
每个音符中间需要有一定的间隔才能够让我们方便区分,因此需要在音符之间设置延迟。间隔时间根据音符持续时间调整会让旋律更加流畅,用noteDuration * 1.30会得到不错的效果,你也可以试试设置delay(200) 的固定时间,来看看效果会有什么不一样。
在音符播放完,使用noTone让声音停止。

硬件回顾
Arduino开发板通常都配备了一个复位键(Reset Button),这个按键在多个方面都非常有用,特别是在编程、调试和重新启动Arduino时。复位键的主要功能是使Arduino板上的微控制器(如ATmega系列)重置其状态,类似于计算机上的重启操作,但针对的是微控制器本身。
Arduino UNO的复位键通常位于开发板的左上角(如图2),靠近USB接口或其他I/O接口。它是一个小按钮,旁边标有“RESET”字样。同样,你也可以使用扩展板上的复位按键来重启Arduino里面的程序。
图 2 Arduino UNO 复位键位置
图 3 扩展板复位键位置
示例代码
课后练习
你有没有熟悉的旋律想要通过蜂鸣器来播放呢?比如小星星或者玛丽有只小羊羔?来试试改变数组中的音符和节奏吧。别忘了改变for循环中的数量哦。
下一课:Arduino入门教程17--DJ调音台
页: [1]
查看完整版本: Arduino入门教程16--音乐蜂鸣器「DFR0100」