自制电子钢琴键盘:内置预设曲目、LCD菜单与电阻分压键盘
所需元件与材料
| 元件 | 数量 |
|---|---|
| Arduino UNO | 1 |
| Adafruit 标准 LCD 1602 (白字蓝底) | 1 |
| SparkFun 12mm 轻触开关 | 8 |
| 电阻 220Ω | 4 |
| 电阻 560Ω | 1 |
| 电阻 1kΩ | 1 |
| 电阻 4.7kΩ | 1 |
| 电阻 10kΩ | 3 |
| 电阻 1MΩ | 1 |
| 蜂鸣器 (无源) | 1 |
| LED (通用) | 1 |
| 单圈电位器 10kΩ | 1 |
| 跳线 (若干) | 1 包 |
| 面包板 | 1 |
项目简介
作者初涉电子领域,但有编程基础。本项目基于对压电蜂鸣器编程的学习成果,实现了一款 7 键电子钢琴,支持通过菜单按键切换预设曲目(超级马里奥主题曲、地下关音乐、危险边缘主题曲等),LCD 显示曲目名,LED 指示菜单模式。代码模块化,便于扩展新曲目或功能。
硬件接线指南
钢琴键 — 电阻分压法
7 个按键通过不同阻值电阻串联至电源,末端接 10kΩ 下拉电阻并共同连接至 Arduino A0 引脚。按键按下时分压电压不同,主程序通过 analogRead(A0) 识别是哪个键。电阻序列 (从左至右) :1MΩ、10kΩ、4.7kΩ、1kΩ、560Ω、220Ω,对应音符 C4、D4、E4、F4、G4、A4、B4。可自行修改频率或增减按键。
LCD 1602
- 按电路图接线
- 引脚 3 (Vo) 接电位器中间脚,电位器两侧接 VCC/GND,调节对比度
- 引脚 15 (背光+) 接 220Ω 电阻后接 VCC
菜单按键
一端接 VCC,另一端接 10kΩ 下拉电阻至 GND,同时接 Arduino 数字引脚 7。
LED 指示灯
阳极接 Arduino 引脚 6,阴极串联 220Ω 接 GND。进入菜单模式时点亮,提示琴键已禁用。
压电蜂鸣器
一脚接 Arduino 引脚 8,另一脚串联 220Ω 接 GND。代码中 tone(8, ...) 驱动发声。

代码工作原理
初始化 (setup)
- 引入
LiquidCrystal.h与pitches.h(音符频率定义) - 定义菜单按键引脚、输入输出模式、7 个琴键的频率数组
notes[] - 每首曲目单独建标签页 (
Song1~Song5),便于维护扩展
主循环 (loop)
- 默认 LED 熄灭,琴键激活
- 检测菜单按键:按下则熄灭琴键功能、点亮 LED、进入
LCDstart()菜单流程 - 读取 A0 电压,按阈值判断按下哪个琴键,调用
tone(8, freq)发声;无按键时noTone(8)
菜单系统
- 短按菜单键循环切换曲目标题 (LCD 显示)
- 任意琴键按下 → 播放当前显示曲目,播放完毕自动返回菜单同一位置
- 双击菜单键 (快速两次) → 重置菜单至首项
- 循环浏览完所有曲目直到 LCD 空白、LED 熄灭 → 退出菜单模式,恢复琴键演奏
完整源代码
代码分模块:Electronic Keyboard (主程序)、Song1~Song5 (五首曲目)、pitches.h (音符频率库)。完整代码请见原项目页面,核心逻辑如下:
主程序片段
#include <LiquidCrystal.h>
#include "pitches.h"
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
const int LCDswitchPin = 7;
int LCDswitchState = 0, prevLCDswitchState = 0;
int blueLED = 6, LCDswitchCounter = 0;
int notes[] = {262, 294, 330, 349, 392, 440, 494}; // C4~B4
void setup() {
Serial.begin(9600);
lcd.begin(16, 2);
pinMode(LCDswitchPin, INPUT);
pinMode(blueLED, OUTPUT);
digitalWrite(blueLED, LOW);
}
void loop() {
LCDswitchState = digitalRead(LCDswitchPin);
int keyVal = analogRead(A0);
lcd.noDisplay();
digitalWrite(blueLED, LOW);
if (LCDswitchState == HIGH) {
digitalWrite(blueLED, HIGH);
lcd.display(); lcd.clear(); LCDstart();
}
// 琴键电压阈值判断...
if (keyVal == 1023) tone(8, notes[0]);
else if (keyVal >= 990 && keyVal <= 1010) tone(8, notes[1]);
// ... 其余音符 ...
else if (keyVal <= 1) noTone(8);
}
// LCDstart(), Song1title()...Song5title() 菜单状态机函数...
曲目示例 (Song1 - 超级马里奥主题曲)
void Song1() {
int melody[] = { NOTE_E7, NOTE_E7, 0, NOTE_E7, 0, NOTE_C7, NOTE_E7, 0, NOTE_G7, 0, ... };
int noteDurations[] = { 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, ... };
lcd.clear();
lcd.setCursor(1, 0); lcd.print("Now playing...");
lcd.setCursor(0, 1); lcd.print("MARIO THEME SONG");
int size = sizeof(melody) / sizeof(int);
for (int i = 0; i < size; i++) {
int noteDuration = 1000 / noteDurations[i];
tone(8, melody[i], noteDuration);
delay(noteDuration * 1.30);
noTone(8);
}
Song1title();
}
pitches.h (音符频率定义)
#define NOTE_C4 262
#define NOTE_D4 294
#define NOTE_E4 330
#define NOTE_F4 349
#define NOTE_G4 392
#define NOTE_A4 440
#define NOTE_B4 494
#define NOTE_C5 523
// ... 含 C0~C8 全音域定义
扩展建议
- 增加更多按键扩展音域
- 添加录音/回放功能
- 接入 SD 卡存储更多乐谱
- 改用更高品质扬声器或音频放大模块
制造工艺
- TJBot 入门指南:构建、配置与语音控制您的 AI 机器人
- 智能缺水报警器 – DIY植物土壤湿度监测装置
- 意大利语单词时钟:Arduino Nano + NeoPixel 144 灯珠 + LCD + RTC 打造
- 将 MIDI 键盘变身智能钢琴导师:Arduino + LED 灯带 + MuseScore
- 自制简易红外避障传感器:IR LED + 光电二极管 + Arduino
- 基于Arduino MKR Fox 1200构建可靠Sigfox千瓦时电表
- 蓝牙温度监测仪:Arduino Nano + NTC 热敏电阻 + HC-06 无线传输
- RDA5807M 迷你立体声 FM 收音机:Arduino Nano + Nokia 5110 + PAM8403 功放
- 非接触手势门锁:APDS-9960 + Arduino 实现安全门禁
- Arduino Nano 多功能伴侣套件 —— 电阻/电容测量、二极管测试、RTC时钟一体化
- Arduino Micro/Leonardo USB MIDI 适配器套件 —— 完整元件清单与固件指南
- Arduino UNO 精准视觉反应时间测试仪