0
点赞
收藏
分享

微信扫一扫

Arduino实验——蜂鸣器播放《致爱丽丝》


蜂鸣器,是一种可以发出单调声音的器件,在电子 DIY 领域应用广泛,因为它使用简单,不像扬声器一样需要用准确的音频信号来控制。蜂鸣器分为有源蜂鸣器和无源蜂鸣器。其中 “源” 不是指电源,而是指振荡源,有源蜂鸣器只需要通直流电压就能发出蜂鸣声;而无源蜂鸣器则需要用一定频率的信号来驱动。

Arduino实验——蜂鸣器播放《致爱丽丝》_致爱丽丝

本实验使用的是无源蜂鸣器。

工作原理

蜂鸣器输入信号的频率决定了蜂鸣器的声音频率,而 Arduino 默认的 PWM 输出频率是固定在 490.196Hz 的,所以不能简单地使用 ​​analogWrite()​​​ 函数来控制蜂鸣器。 Arduino 为蜂鸣器控制设计了一个专用函数 ​​tone(pin, frequency, duration)​​​,其中 pin 指输出引脚,frequency 指输出频率(单位 Hz),duration 是声音持续的时间(单位 ms)。最后一个参数可以不填,不填时将持续输出。对应的,还有一个 ​​noTone(pin)​​ 函数,用于停止指定引脚上的方波输出。

因此,我们使用 Arduino 中的 ​​tone()​​ 函数就可以比较精确地控制声音的频率和持续时间。但是想要输出特定的音符,则需要查频率表,比较麻烦。好在 Arduino 库中为我们提供了一个文件 —— pitches.h,该文件包含典型音符的所有音高值。例如,​​NOTE_C4​​​ 是中央 C,​​NOTE_FS4​​ 是 F#,等等。这个注释表最初是由 Brett Hagman 编写的,想制作音符时会发现它很有用!

硬件连接

将蜂鸣器输入接在 Arduino 的 8 号数字 IO 上,再接上 GND 和 VCC 即可。

乐理知识

简谱左上角通常有类似下面这样的符号,用于表示曲子的调号和拍数。调号一般是用 1 等于 A、B、C、D、E、F、G 来表示,如 1=C 表示该简谱是用 C 调来记谱的,如果要表示升降号的调,则在字母前加 # 号或者 b 号。调号后面的分数是拍号,其中分母表示以几分音符为一拍,分子表示每小节有多少拍。拍号决定了乐曲的基本节奏和强弱的循环规律。

因此,上述符号表示该简谱是 C 调来记谱的,以四分音符为一拍,每小节四拍。

再比如,这个符号表示该简谱是 D 调来记谱的,以四分音符为一拍,每小节两拍。

《致爱丽丝》原名《a小调巴加泰勒》,它的调号和拍号如下所示。其中 Am 调是建立在根音 A 上的小三和弦,由【A C E】构成。然后以八分音符为一拍,每小节三拍。

讲了那么多,其实我也不太懂。。。 😿 哭唧唧

Arduino实验——蜂鸣器播放《致爱丽丝》_Arduino_05

致爱丽丝

我将上面一小段翻译成 pitches.h 中预定义的音符,调子和拍子好像也没整对。。。不过听起来是爱丽丝的味道 😸

/*
Play a melody
*/

#include "pitches.h"

// 记录曲子的音符
int melody[] = { 0, 0, NOTE_E5, NOTE_D5, NOTE_E5, NOTE_D5, NOTE_E5, NOTE_B4, NOTE_D5, NOTE_C5,
NOTE_A4, 0, NOTE_C4, NOTE_E4, NOTE_A4, NOTE_B4, 0, NOTE_E4, NOTE_G4, NOTE_B4,
NOTE_C5, 0, NOTE_E4, NOTE_E5, NOTE_D5, NOTE_E5, NOTE_D5, NOTE_E5, NOTE_B4, NOTE_D5, NOTE_C5,
NOTE_A4, 0, NOTE_C4, NOTE_E4, NOTE_A4, NOTE_B4, 0, NOTE_E4, NOTE_C5, NOTE_B4,
NOTE_A4
};

// 音符持续时间:4为四分音符,8为八分音符
int noteDurations[] = { 4, 4, 8, 8, 8, 8, 8, 8, 8, 8,
4, 8, 8, 8, 8, 4, 8, 8, 8, 8,
4, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
4, 8, 8, 8, 8, 4, 8, 8, 8, 8,
4, 4, 8, 8, 8, 8, 8, 8, 8, 8,
4
};

void setup() {

// 遍历整个曲子的音符
for(int thisNote = 0; thisNote < sizeof(melody)/sizeof(melody[0]); thisNote++) {

// 需要根据音符类型换算音符的持续时间
int noteDuration = 1000/noteDurations[thisNote];
tone(8, melody[thisNote], noteDuration);

// 为了能辨别出不同的音调,需要在两个音调间设置一定的延时,增加30%比较合适
int pauseBetweenNotes = noteDuration * 1.30;
delay(pauseBetweenNotes);

noTone(8);
}

}

void loop() {

}

播放效果

点击视频:​​https://weibo.com/tv/v/IjgAGqoHt?fid=1034:4445920067256332​​


举报

相关推荐

0 条评论