Arduino - 音调库
Arduino - 使用 tone() 进行现代声音生成
Section titled “Arduino - 使用 tone() 进行现代声音生成”本章探讨如何使用Arduino的内置tone()函数生成声音和旋律。tone()函数可以在任何数字引脚上产生指定频率的方波。这是为您的项目添加听觉反馈的绝佳方式,从简单的蜂鸣声到复杂的音乐曲调。您可以将输出引脚连接到压电蜂鸣器或小型扬声器以听到声音。
安全警告: Arduino引脚发出的信号是5V(或3.3V)方波。请勿将其直接连接到声卡或放大器等标准音频输入端,因为这种高电压可能导致永久性损坏。如果您需要与音频设备接口,请使用分压电路和耦合电容来安全地降低电压并消除直流偏置。
要完成本教程,您将需要:
- 1 × Arduino UNO开发板(或任何其他Arduino开发板)
- 1 × 压电蜂鸣器或一个8欧姆扬声器
- 1 × 100欧姆电阻(用于扬声器限流)
- 跳线
电路很简单。我们将声音产生组件连接到数字引脚8。
使用压电蜂鸣器:
将正极(通常较长的一条腿)连接到Arduino的数字引脚8。将负极连接到Arduino的GND。
使用8欧姆扬声器:
将扬声器的一个接线端通过一个100欧姆电阻连接到Arduino的数字引脚8。将另一个接线端连接到Arduino的GND。电阻器可保护Arduino引脚免受过大电流的损害。
以下是电路的文本表示:
Arduino Component GND ---------------- (-) Piezo Buzzer / Speaker Terminal 2 PIN 8 -------------- (+) Piezo Buzzer / (Resistor) -> Speaker Terminal 1现代Arduino草图
Section titled “现代Arduino草图”原始教程使用了单独的pitches.h文件。虽然这可行,但现代C++实践允许我们在主草图内清晰地定义这些常量,使其自包含。我们还将使用现代技术使代码更健壮和高效。
打开Arduino IDE,创建一个新的草图(文件 > 新建),然后粘贴以下代码。
Arduino代码
Section titled “Arduino代码”/* * 现代旋律播放器 * * 此草图使用 tone() 函数播放简单旋律。 * 它演示了使用 PROGMEM 进行高效内存使用和健壮的数组处理。 */
// 包含 PROGMEM 头文件以优化内存#include <avr/pgmspace.h>
// --- 音符定义 ---// 这些是赫兹(Hz)的频率#define NOTE_C4 262#define NOTE_G3 196#define NOTE_A3 220#define NOTE_B3 247#define NOTE_C5 523#define REST 0 // 一个休止/暂停
// --- 引脚配置 ---const int buzzerPin = 8;
// --- 旋律和持续时间 ---// PROGMEM 将此数据存储在闪存中,节省宝贵的RAM。const int melody[] PROGMEM = { NOTE_C4, NOTE_G3, NOTE_G3, NOTE_A3, NOTE_G3, REST, NOTE_B3, NOTE_C4};
// 音符持续时间:4 = 四分音符,8 = 八分音符等。const int noteDurations[] PROGMEM = { 4, 8, 8, 4, 4, 4, 4, 4};
void setup() { // tone() 不需要 setup,但设置引脚模式是良好实践。 pinMode(buzzerPin, OUTPUT);
// 获取旋律中的音符总数。 // 使用 sizeof() 使代码适用于任何长度的旋律。 int numNotes = sizeof(melody) / sizeof(melody[0]);
// 遍历旋律中的音符 for (int thisNote = 0; thisNote < numNotes; thisNote++) { // 节奏(例如,一个四分音符长 1000ms) int tempo = 1000;
// 从 PROGMEM 读取音符持续时间 int durationType = pgm_read_word_near(¬eDurations[thisNote]); int noteDuration = tempo / durationType;
// 从 PROGMEM 读取音符频率 int frequency = pgm_read_word_near(&melody[thisNote]);
// 使用 tone(pin, frequency, duration) 播放音符 tone(buzzerPin, frequency, noteDuration);
// 为了让音符播放完毕并在音符之间添加短暂的停顿, // 我们计算一个停顿。30% 的停顿通常听起来不错。 int pauseBetweenNotes = noteDuration * 1.30; delay(pauseBetweenNotes);
// 停止音调以确保它不与下一个音调重叠。 noTone(buzzerPin); }}
void loop() { // 旋律在 setup() 中播放一次。loop 是空的。 // 您可以在此处添加代码以在按钮按下时重播旋律。}代码解释与最佳实践
Section titled “代码解释与最佳实践”tone(pin, frequency, duration): 这是核心函数。它在给定pin上以指定的frequency(赫兹)生成一个方波,持续duration(毫秒)。duration是可选的;如果省略,音调将一直播放直到您调用noTone(pin)。
PROGMEM: 这对于像Arduino Uno这样内存受限的设备来说是一个关键特性。它告诉编译器将melody和noteDurations数组存储在更大的闪存程序存储器中,而不是非常有限的SRAM(RAM)中。这为您的变量和其他运行时需求留下了更多RAM,从而防止了大型程序中的崩溃。
sizeof(melody) / sizeof(melody[0]): 这是计算数组元素数量的标准、健壮的C++方法。它比硬编码数字(如8)更好,因为如果您从melody数组中添加或删除音符,此计算将自动更新,从而防止错误。
调试与深入学习
Section titled “调试与深入学习”- 没有声音? 检查您的接线。蜂鸣器/扬声器是否连接到正确的引脚(8)和GND?如果使用扬声器,您是否包含了电阻器?
- 声音失真? 小型扬声器可能在抖动。确保它已固定。压电蜂鸣器通常产生更清晰(尽管更“数字化”)的声音。
- 深入学习: 尝试通过更改音符和持续时间来创建自己的旋律。您可以在
loop()函数中添加一个按钮,以便按需触发旋律。或者,将电位器连接到模拟引脚,并使用其读数来控制音乐的节奏。
上传草图后,Arduino将立即通过连接的蜂鸣器或扬声器播放预编程的旋律。旋律将播放一次,然后程序将在loop()函数中保持空闲。