1109 字
6 分钟
Arduino|简易音乐播放器

1. 前言
大家好,今天给大家带来一个有趣的 Arduino 小项目——使用无源蜂鸣器和 OLED 屏幕,完整播放《神のまにまに》(神的随波逐流)这首经典歌曲。
项目核心功能:
- 通过 PWM 调波技术驱动无源蜂鸣器播放音乐
- OLED 屏幕同步显示歌曲封面
- 完整乐谱数据,支持歌曲循环播放
演示视频:
2. 简介
本项目使用 Arduino 开发板驱动无源蜂鸣器播放《神のまにまに》(神的随波逐流),同时在 OLED 屏幕上显示歌曲封面图片。通过 PWM 调波技术实现音调控制,支持完整的歌曲循环播放结构。
2.1 硬件清单
| 器件 | 规格 | 数量 |
|---|---|---|
| Arduino 主控板 | ESP8266 等 | 1 |
| 无源蜂鸣器 | 3~5V 无源 | 1 |
| OLED 屏幕 | 0.96寸 I2C 128×64 SSD1306 | 1 |
| 杜邦线 | 根据开发板而定 | 若干 |
2.2 接线说明
Arduino 无源蜂鸣器 GPIO 1 ──────────── Signal
Arduino OLED屏幕 GPIO 4 ──────────── SDA GPIO 5 ──────────── SCL 3V/5V ──────────── VCC GND ──────────── GND| OLED 引脚 | Arduino 引脚 |
|---|---|
| SDA | A4 (SDA) |
| SCL | A5 (SCL) |
| VCC | 3V/5V |
| GND | GND |
2.3 软件依赖
本项目使用以下开源库:
| 库名 | 版本 | 说明 |
|---|---|---|
| Adafruit GFX Library | ≥1.10 | 图形库核心 |
| Adafruit SSD1306 | ≥2.5 | OLED 驱动库 |
| SPI | 内置 | SPI 通信库 |
| Wire | 内置 | I2C 通信库 |
2.3.1 库安装方法
在 VS Code 中的 PlatformIO 插件搜索并安装:
Adafruit GFX Libraryby AdafruitAdafruit SSD1306by Adafruit
3. 技术原理
3.1 PWM 调波发声原理
无源蜂鸣器需要外部电路提供交流脉冲信号才能发声。通过 Arduino 的 tone() 函数,我们可以:
- 生成指定频率的方波信号:不同频率对应不同音高
- PWM 占空比固定为 50%:确保信号稳定
- 音调与频率对应关系:
- 低音:262Hz (C4) ~ 494Hz (B4)
- 中音:523Hz (C5) ~ 988Hz (B5)
┌─────────────┐│ Arduino │ ──tone(440Hz)──▶ [蜂鸣器] ──▶ 发出 A4 音└─────────────┘3.2 乐谱数据结构设计
本项目采用双数组存储乐谱信息:
| 数组 | 作用 | 数据示例 |
|---|---|---|
musicSentenceTones | 音调序列 | -5, -6, 1, 2, 2, 1... |
musicSentenceTime | 时长序列 | 4, 4, 4, 3, 1... |
音调编码规则:
// 对照规则:低音 -1~-7; 中音 1~7; 高音 11~17; 2# 为 33int lowTones[8] = {0, 262, 294, 330, 349, 392, 440, 494}; // 低音频率int midTones[8] = {0, 523, 587, 659, 698, 784, 880, 988}; // 中音频率int mid2sTone = 622; // 中音 2# 频率3.3 OLED 显示原理
使用 Adafruit_SSD1306 库驱动 128×64 分辨率的 OLED 屏幕:
- 通信协议:I2C(只占用 2 个 GPIO 引脚)
- 显示方式:位图数组直接绘制
- 显存操作:双缓冲避免闪烁
OLED 引脚连接:┌─────────────┐│ Arduino ││ GPIO 5 ────▶ SCL (时钟线)│ GPIO 4 ────▶ SDA (数据线)└─────────────┘4. 代码展示
5. 算法解读
5.1 循环控制机制
本项目的循环是通过 breakPoint 变量控制歌曲的反复段:
歌曲结构:├── 前奏(0-6行)├── A段(7-14行)├── B段(15-32行)├── 反复句1(33行)→ 回到前奏├── 反复句2(34-38行)→ 回到B段└── 结束句(39-51行)断点控制逻辑:
breakPoint = 0 → 到达第33行时,反复到第6行breakPoint = 1 → 到达第38行时,反复到第19行breakPoint = 2 → 到达第32行时,进入结束句5.2 时长计算公式
thisTime = SIXTEENTH_NOTE * musicSentenceTime[rows][columns] - 40;- 基准单位:十六分音符(111ms)
- 时长修正:乘以节拍数,再减去 40ms 作为音间间隔
- 为什么要减40ms:为下一个音符的
noTone()留出间隙
5.3 音调编码映射
| 编码值 | 实际音高 | 计算方式 |
|---|---|---|
-1 ~ -7 | 低音 1~7 | lowTones[abs(编码)] |
1 ~ 7 | 中音 1~7 | midTones[编码] |
33 | 中音 2# | 特殊值,查表 mid2sTone |
0 | 休止符 | 无操作(需配合下一音判断) |
6. 总结
6.1 项目亮点
其实是没有亮点,但是博主牵强附合(
- 资源占用少:仅使用 2 个 GPIO 引脚(I2C 通信)
- 代码结构清晰:数据与逻辑分离,便于维护和扩展
- 支持循环播放:通过断点机制实现复杂的歌曲结构
6.2 硬件清单
| 器件 | 数量 | 说明 |
|---|---|---|
| ESP8266 开发板 | 1 | 主控芯片 |
| 无源蜂鸣器 | 1 | 发声元件 |
| OLED 屏幕 (SSD1306) | 1 | 128×64 I2C 接口 |
| 杜邦线 | 若干 | 连接线路 |
6.3 可扩展方向
实际情况是博主技术力不够,实现不了
- 添加按钮实现”播放/暂停”功能
- 增加音量调节
- 支持多首歌曲切换
- 添加歌词同步显示功能
Arduino|简易音乐播放器
https://luq-blog.xyz/posts/2026-05-28-beep-audio/分享文章
生成精美分享图或复制链接,与更多人分享本文。
继续阅读
换条路线
从其他文章中稳定抽取
最后更新于 ,距今已过 105 天
部分内容可能已过时
评论