上一篇我们学了 LCD1602,让 Arduino 有了"脸面"来显示信息。今天给它加上"嗓子"——蜂鸣器,让 Arduino 能发出声音,从简单的"滴滴"提示音,到播放一首完整的歌曲。
学完这篇,你会完成三个项目:
- 基础发声:让蜂鸣器发出不同频率的声音
- 警报器效果:模拟救护车/警笛的变调声音
- 综合项目:按键电子琴:用 7 个按键弹奏 Do Re Mi Fa Sol La Si
一、蜂鸣器是什么?
蜂鸣器是一种电子发声元件,通过振动产生声音。Arduino 项目中常用的有两种:
有源蜂鸣器 vs 无源蜂鸣器
| 对比项 | 有源蜂鸣器 | 无源蜂鸣器 |
|---|---|---|
| 内部结构 | 自带振荡电路 | 没有振荡电路 |
| 发声方式 | 通电就响,频率固定 | 需要 Arduino 提供方波信号 |
| 音调控制 | 不能改变音调 | 可以改变音调 |
| 适用场景 | 简单的提示音/报警 | 播放音乐、变调效果 |
我们主要使用无源蜂鸣器,因为它可以控制频率,实现播放音乐的功能。有源蜂鸣器只能发出固定频率的声音,功能有限。
如何区分?
- 看外观:有源蜂鸣器底部通常有封胶覆盖电路板,无源的能看到绿色电路板
- 测电压:直接接 5V,响的是有源,不响(或只有"嗒"一声)的是无源
- 看标注:有些蜂鸣器上会标注 "ACTIVE" 或 "PASSIVE"
二、发声原理
蜂鸣器发声的核心是 频率。Arduino 通过 tone() 函数向蜂鸣器引脚输出指定频率的方波信号,蜂鸣器振动发声。
- 频率越高 → 音调越高(声音越尖)
- 频率越低 → 音调越低(声音越沉)
人耳能听到的频率范围大约是 20Hz ~ 20000Hz。
音符与频率对照表
| 音符 | 频率 (Hz) |
|---|---|
| Do (C4) | 262 |
| Re (D4) | 294 |
| Mi (E4) | 330 |
| Fa (F4) | 349 |
| Sol (G4) | 392 |
| La (A4) | 440 |
| Si (B4) | 494 |
| Do (C5) | 523 |
三、接线方式
蜂鸣器的接线非常简单,只需要 2 根线:
| 蜂鸣器引脚 | 接到 |
|---|---|
| 正极(+,长脚) | Arduino D8(或其他数字引脚) |
| 负极(-,短脚) | GND |
无源蜂鸣器通常不需要串联电阻,直接接即可。如果担心电流过大,可以串联一个 100Ω 左右的电阻。
四、实验一:基础发声
让蜂鸣器发出 1kHz 的声音,响 1 秒,停 1 秒,循环。
#define BUZZER 8 // 蜂鸣器接 D8
void setup() {
pinMode(BUZZER, OUTPUT);
}
void loop() {
tone(BUZZER, 1000); // 发出 1000Hz 的声音
delay(1000); // 持续 1 秒
noTone(BUZZER); // 停止发声
delay(1000); // 静音 1 秒
}
代码解读
tone(pin, frequency):在指定引脚输出指定频率的方波,蜂鸣器开始发声noTone(pin):停止指定引脚的方波输出,蜂鸣器停止发声tone(pin, frequency, duration):第三种用法,发声指定毫秒后自动停止(不需要手动调用noTone)
试试改变频率值,感受音调的变化:
tone(BUZZER, 200); // 低沉的声音
tone(BUZZER, 1000); // 中等音调
tone(BUZZER, 5000); // 尖锐的声音
五、实验二:警报器效果
模拟救护车"呜——呜——"的变调声音。
#define BUZZER 8
void setup() {
pinMode(BUZZER, OUTPUT);
}
void loop() {
// 从低频到高频,模拟"呜——"的上升
for (int freq = 400; freq <= 1200; freq += 10) {
tone(BUZZER, freq);
delay(5);
}
// 从高频到低频,模拟"呜——"的下降
for (int freq = 1200; freq >= 400; freq -= 10) {
tone(BUZZER, freq);
delay(5);
}
}
原理
通过 for 循环逐步改变频率,实现平滑的音调变化:
- 上升阶段:频率从 400Hz 逐步增加到 1200Hz,声音越来越尖
- 下降阶段:频率从 1200Hz 逐步降低到 400Hz,声音越来越沉
- 循环往复:形成类似警笛的效果
可以调整
freq的起始值、终止值和步长(+= 10),来改变警报声的效果。步长越小,声音越平滑。
六、综合项目:按键电子琴
用 7 个按键对应 Do Re Mi Fa Sol La Si,按下哪个键就发出对应的音符。
接线
| 按键 | 功能 | 接到 |
|---|---|---|
| 按键 1 | Do | D2 |
| 按键 2 | Re | D3 |
| 按键 3 | Mi | D4 |
| 按键 4 | Fa | D5 |
| 按键 5 | Sol | D6 |
| 按键 6 | La | D7 |
| 按键 7 | Si | D9 |
| 蜂鸣器 | + | D8 |
| 蜂鸣器 | - | GND |
每个按键的另一端接 GND,使用
INPUT_PULLUP模式(按下为 LOW)。
代码
#define BUZZER 8
// 按键引脚定义
#define KEY_DO 2
#define KEY_RE 3
#define KEY_MI 4
#define KEY_FA 5
#define KEY_SOL 6
#define KEY_LA 7
#define KEY_SI 9
// 音符频率定义
#define NOTE_DO 262
#define NOTE_RE 294
#define NOTE_MI 330
#define NOTE_FA 349
#define NOTE_SOL 392
#define NOTE_LA 440
#define NOTE_SI 494
void setup() {
pinMode(BUZZER, OUTPUT);
// 设置所有按键为内部上拉模式
pinMode(KEY_DO, INPUT_PULLUP);
pinMode(KEY_RE, INPUT_PULLUP);
pinMode(KEY_MI, INPUT_PULLUP);
pinMode(KEY_FA, INPUT_PULLUP);
pinMode(KEY_SOL, INPUT_PULLUP);
pinMode(KEY_LA, INPUT_PULLUP);
pinMode(KEY_SI, INPUT_PULLUP);
Serial.begin(9600);
Serial.println("Arduino Piano Ready!");
}
void loop() {
// 检测哪个按键被按下,播放对应音符
if (digitalRead(KEY_DO) == LOW) {
tone(BUZZER, NOTE_DO);
Serial.println("Do");
} else if (digitalRead(KEY_RE) == LOW) {
tone(BUZZER, NOTE_RE);
Serial.println("Re");
} else if (digitalRead(KEY_MI) == LOW) {
tone(BUZZER, NOTE_MI);
Serial.println("Mi");
} else if (digitalRead(KEY_FA) == LOW) {
tone(BUZZER, NOTE_FA);
Serial.println("Fa");
} else if (digitalRead(KEY_SOL) == LOW) {
tone(BUZZER, NOTE_SOL);
Serial.println("Sol");
} else if (digitalRead(KEY_LA) == LOW) {
tone(BUZZER, NOTE_LA);
Serial.println("La");
} else if (digitalRead(KEY_SI) == LOW) {
tone(BUZZER, NOTE_SI);
Serial.println("Si");
} else {
// 没有按键按下,停止发声
noTone(BUZZER);
}
}
代码解读
- 音符频率用
#define定义:方便维护和阅读,修改频率只需改一处 - 按键检测:使用
INPUT_PULLUP模式,按下时引脚为 LOW if-else if链:依次检测每个按键,只响应第一个被按下的键else分支:没有按键按下时调用noTone()停止发声,实现"松手即停"
效果
按下对应按键,蜂鸣器发出该音符的声音;松开按键,声音立即停止。就像一台迷你电子琴!
七、进阶:播放一首完整的曲子
把音符和节拍存储在数组中,用循环自动播放。以《小星星》为例:
#define BUZZER 8
// 音符频率(0 表示休止符)
#define NOTE_DO 262
#define NOTE_RE 294
#define NOTE_MI 330
#define NOTE_FA 349
#define NOTE_SOL 392
#define NOTE_LA 440
#define NOTE_SI 494
#define REST 0 // 休止符
// 《小星星》旋律:音符数组
int melody[] = {
NOTE_DO, NOTE_DO, NOTE_SOL, NOTE_SOL, NOTE_LA, NOTE_LA, NOTE_SOL,
NOTE_FA, NOTE_FA, NOTE_MI, NOTE_MI, NOTE_RE, NOTE_RE, NOTE_DO,
NOTE_SOL, NOTE_SOL, NOTE_FA, NOTE_FA, NOTE_MI, NOTE_MI, NOTE_RE,
NOTE_SOL, NOTE_SOL, NOTE_FA, NOTE_FA, NOTE_MI, NOTE_MI, NOTE_RE,
NOTE_DO, NOTE_DO, NOTE_SOL, NOTE_SOL, NOTE_LA, NOTE_LA, NOTE_SOL,
NOTE_FA, NOTE_FA, NOTE_MI, NOTE_MI, NOTE_RE, NOTE_RE, NOTE_DO
};
// 对应的节拍(4 = 全音符, 2 = 二分音符, 1 = 四分音符)
int durations[] = {
1, 1, 1, 1, 1, 1, 2,
1, 1, 1, 1, 1, 1, 2,
1, 1, 1, 1, 1, 1, 2,
1, 1, 1, 1, 1, 1, 2,
1, 1, 1, 1, 1, 1, 2,
1, 1, 1, 1, 1, 1, 2
};
void setup() {
pinMode(BUZZER, OUTPUT);
}
void loop() {
int noteCount = sizeof(melody) / sizeof(melody[0]);
for (int i = 0; i < noteCount; i++) {
int duration = 500 / durations[i]; // 根据节拍计算持续时间
if (melody[i] == REST) {
delay(duration); // 休止符:只等待,不发声
} else {
tone(BUZZER, melody[i], duration); // 播放音符
delay(duration); // 等待音符播放完毕
}
// 音符之间加短暂间隔,让音符更清晰
delay(duration / 10);
}
// 播放完毕后暂停 3 秒再重播
delay(3000);
}
代码解读
- 数组存储旋律:
melody[]存音符频率,durations[]存对应节拍,两个数组一一对应 - 节拍计算:
500 / durations[i],以 500ms 为基准,全音符(4)= 125ms,二分音符(2)= 250ms,四分音符(1)= 500ms - 休止符处理:频率为 0 时不发声,只等待对应时长
- 音符间隔:
delay(duration / 10)在每个音符后加短暂停顿,避免音符粘连
想播放其他歌曲?只需要修改
melody[]和durations[]数组的内容即可!
八、tone() 函数注意事项
tone()会占用定时器:Arduino Uno 的定时器 2 被tone()占用,会影响analogWrite()在 D3 和 D11 引脚上的 PWM 输出- 同时只能
tone()一个引脚:如果需要同时发出不同频率的声音,需要更复杂的方案 noTone()释放定时器:调用后定时器恢复可用
九、本篇小结
回顾一下今天学到的核心知识:
- 蜂鸣器分类:有源(通电就响)和无源(需要方波驱动),无源蜂鸣器可以控制音调
tone()函数:tone(pin, freq)发声,tone(pin, freq, duration)定时发声,noTone(pin)停止- 频率与音调:频率越高音调越高,音符对应特定频率
- 警报器效果:用
for循环渐变频率,实现变调效果 - 按键电子琴:按键检测 + 对应频率播放,松手即停
- 播放完整曲子:用数组存储旋律和节拍,循环播放
蜂鸣器让 Arduino 项目有了声音反馈,可以制作门铃、报警器、电子琴、音乐盒等有趣的项目。下一篇,我们学习继电器模块——让 Arduino 控制高电压设备(如灯泡、风扇)!

7852

被折叠的 条评论
为什么被折叠?



