蜂鸣器模块——让 Arduino 发出声音

        上一篇我们学了 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,按下哪个键就发出对应的音符。

接线
按键功能接到
按键 1DoD2
按键 2ReD3
按键 3MiD4
按键 4FaD5
按键 5SolD6
按键 6LaD7
按键 7SiD9
蜂鸣器+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 控制高电压设备(如灯泡、风扇)!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值