1. 项目概述从激光竖琴到红外空气竖琴的创意实现几年前我在一个电子音乐现场第一次看到激光竖琴的表演演奏者双手在数道彩色光束间挥动便能奏出空灵的音符那种将无形的光转化为可听音乐的过程让我着迷。然而激光设备成本高昂调试复杂且存在一定的安全风险这让许多爱好者望而却步。于是我开始思考能否用更常见、更安全的元件实现类似的无接触演奏体验这就是Aetherharp空气竖琴项目的起点。它的核心目标是构建一个成本可控、易于复现、且能输出标准MIDI信号的“空气乐器”让任何对电子制作和音乐感兴趣的人都能亲手搭建并演奏自己的数字乐器。这个项目放弃了激光方案转而采用了八颗SHARP GP2Y0A41SK0F红外距离传感器。你可能在扫地机器人或自动感应水龙头里见过它们的身影。它们的工作原理是发射一束红外光并测量从物体反射回来的光强度从而计算出距离。我们将这八颗传感器排成一排通过编程让它们分别对应一个音符。当你的手在传感器上方特定高度范围内挥过时就相当于“拨动”了那根无形的琴弦微控制器会立即将这个动作转换成一个MIDI音符信号通过USB发送给电脑由电脑里的软音源发出声音。为了实现更丰富的演奏效果我们还加入了一个游戏摇杆用于在演奏时实时控制弯音为音乐增添表情。整个系统的“大脑”是一块Teensy 3.5开发板。选择它而非普通的Arduino Uno有两个关键原因一是其ARM Cortex-M4内核处理速度远超AVR芯片能实时处理八个传感器的数据并进行复杂的噪声滤波计算二是它原生支持USB-MIDI协议可以即插即用地被电脑识别为一个标准MIDI输入设备省去了我们额外制作MIDI接口电路的麻烦。整个项目从硬件焊接、软件调试到最终封装涉及了嵌入式编程、信号处理、MIDI协议和基础木工是一个综合性很强的创客项目。无论你是想为乐队增添一个酷炫的交互乐器还是单纯想深入理解传感器与声音的联动这个指南都将为你提供一条清晰的路径。2. 核心硬件选型与设计思路解析2.1 传感器选型为什么是SHARP GP2Y0A41SK0F在决定使用红外距离传感器后市面上有多种选择比如超声波传感器、TOF飞行时间激光传感器等。最终锁定SHARP的这款红外传感器是经过多方面权衡的。首先超声波传感器虽然成本低但波束角通常较大容易在密集排列时产生串扰你的手可能会同时触发两个相邻的“琴弦”。TOF传感器精度高、响应快但价格昂贵不适合需要多个单元的项目。SHARP GP2Y0A41SK0F属于模拟输出型红外测距传感器。它的测量范围是4到30厘米这个距离对于将手自然悬空演奏来说非常合适——太近了局促太远了需要大幅度动作容易疲劳。其输出是模拟电压与测量距离成反比Teensy的ADC模数转换器可以轻松读取。最重要的是它的光束非常狭窄指向性好。这意味着当我们将八个传感器以10厘米以上的间距排开时每颗传感器基本上只对其正上方的区域敏感极大降低了误触相邻传感器的可能性这是实现清晰、独立音符触发的物理基础。注意SHARP这个系列的传感器外观几乎一模一样但后缀型号不同测量范围差异巨大。例如GP2Y0A21YK0F的测量范围是10到80厘米。务必确认你购买的是GP2Y0A41SK0F否则整个演奏区域的高度设计都需要推倒重来。购买时最好在可靠的元器件分销商处下单避免二手或混料的风险。2.2 主控板选型Teensy 3.5的优势与考量为什么不用更常见的Arduino Uno核心矛盾在于性能和功能集成度。Aetherharp需要实时监控八个模拟传感器和一个摇杆两个模拟轴并进行大量的软件滤波计算。Arduino Uno的ATmega328P芯片只有16MHz主频和2KB RAM在同时处理多路模拟输入和复杂算法时会非常吃力可能导致音符响应延迟或丢失。Teensy 3.5基于120MHz的ARM Cortex-M4内核拥有192KB RAM和1MB Flash。这为我们施展复杂的滤波算法提供了充足的算力空间。更重要的是Teensy系列由PJRC公司开发其固件和Arduino IDE插件原生集成了USB-MIDI库。这意味着你只需在代码中调用几行简单的函数就能让电脑将Teensy识别为一个专业的MIDI键盘或控制器无需任何额外的驱动程序在主流操作系统上。这种“开箱即用”的体验对于音乐应用来说至关重要。此外Teensy 3.5的3.3V逻辑电平与SHARP传感器的工作电压完美匹配简化了电源设计。2.3 系统供电与结构设计思路整个系统采用USB总线供电这是一个极简且可靠的设计。Teensy通过Micro USB线从电脑获取5V电源其板载稳压器可输出稳定的3.3V直接供给所有八颗传感器和摇杆模块。这避免了引入额外的电池或电源适配器减少了复杂度和成本也使得设备便携性大增——只需一台笔记本电脑即可演奏。结构上我们将所有元件固定在一块长约1米的木板上。这个长度是为了给八颗传感器提供足够的间距每颗约12.5厘米同时也符合人体工程学让演奏者双臂有自然的舒展空间。传感器用螺丝直接固定在木板表面而Teensy、摇杆模块和线缆则通过扎带、热熔胶或3D打印的支架固定在木板背面或侧面最终呈现一个整洁的“演奏面”。上方的透明红色亚克力板主要起装饰和保护作用实测对红外传感器的性能影响微乎其微只要避免在强烈的直射阳光下使用即可环境红外噪声会剧增。3. 硬件搭建与电路连接详解3.1 传感器阵列的安装与布线首先准备一块长度约1米、宽度足以并排安装八颗传感器约15-20厘米宽的木板。表面打磨光滑避免毛刺损伤线材。用尺子标记出八个等距的点间距务必大于10厘米我推荐12.5厘米这是经过实测在避免手部误触和最大化利用木板长度之间的最佳平衡点。使用小号自攻螺丝将每个传感器固定在其标记位置上。固定时注意传感器前端的红外发射/接收窗口朝上且前方没有遮挡。接下来是最需要耐心的一步布线。每个传感器有三根线红色VCC电源正极、黑色GND电源负极、黄色Vo模拟信号输出。为了整洁和可靠建议使用不同颜色的排线或彩虹排线。电源线的并联连接将所有八个传感器的红色线焊接在一起最终引出一根较粗的导线连接到Teensy 3.5板上标有“3.3V”的输出引脚。同样将所有八个传感器的黑色线焊接在一起引出一根导线连接到Teensy上任意的“GND”引脚。这种星型或总线型的并联接法确保了每个传感器都能获得稳定的电压。信号线的独立连接每颗传感器的黄色信号线必须独立连接到Teensy的一个模拟输入引脚。Teensy 3.5有大量的模拟引脚我们可以依次使用A0, A1, A2, A3, A4, A5, A6, A7。请务必在代码中记录好每个物理传感器对应的引脚号后续的校准和音符映射都依赖这个顺序。焊接完成后用扎带将线束整齐地捆扎在木板背面。3.2 摇杆模块的连接与功能定义我们选用的是常见的双轴模拟摇杆模块内部是两个10k欧姆的电位器。在这个项目中我们只使用其中一个轴比如X轴来控制弯音Pitch Bend。MIDI协议的弯音信息范围通常是-8192到8191中心值为0无弯音。摇杆的模拟读数正好可以映射到这个范围。连接摇杆模块的三根线VCC连接到Teensy的另一个“3.3V”引脚。虽然可以和传感器共用电源但单独连接能减少一点电源噪声。GND连接到Teensy的“GND”。X轴信号输出连接到Teensy的模拟引脚A9即数字引脚23。在代码中我们将持续读取这个引脚的值。为了提升手感并方便安装我为摇杆设计了一个简单的3D打印外壳将其固定在木板侧方伸手可及的位置。你也可以用现成的塑料盒或直接固定。确保摇杆在自然状态下能回中这样弯音值才能归零。3.3 最终集成与USB连接加固将所有元件Teensy主板、线束接头、摇杆用扎带或热熔胶牢固地固定在木板背面。此时将Micro USB数据线的Micro端插入Teensy。这是一个关键加固点Micro USB接口的物理强度不高反复插拔或演奏时线缆晃动可能导致接口损坏或接触不良。我的做法是在Teensy插座旁边的木板上钻两个小孔用扎带将USB线缆紧紧绑在木板上形成一个“应力消除”结构确保拉力由木板承担而不是脆弱的焊接点。最后将USB线的A端插入电脑。如果一切正常Teensy上的指示灯会亮起电脑会发出识别新USB设备的提示音。在Windows的设备管理器或macOS的“系统信息”中你应该能看到一个名为“Teensy MIDI”或类似的设备。4. 核心软件逻辑与噪声滤波算法4.1 程序主框架与MIDI输出设置项目的所有智能都蕴含在上传到Teensy的Arduino代码中。代码的核心逻辑是一个循环快速读取所有传感器和摇杆的值 - 进行滤波和状态判断 - 触发或停止对应的MIDI音符 - 发送弯音信息。首先必须在Arduino IDE中安装Teensyduino插件并在“工具”菜单下正确选择板卡类型为“Teensy 3.5”端口选择对应的串口。最关键的一步是在“工具”菜单的“USB类型”中选择“Serial MIDI”。这个选项使得Teensy既能通过串口打印调试信息又能作为一个标准的MIDI设备运行。代码开头需要包含必要的库#include Bounce.h用于软件消抖虽然我们主要用模拟滤波但数字消抖作为二次保险而USB-MIDI功能由Teensyduino核心库自动提供。我们定义音符数组将八个传感器映射到特定的MIDI音符编号上例如从C4MIDI编号60开始的一个八度音阶。// 定义传感器对应的MIDI音符编号 (C4到C5) int noteNumber[8] {60, 62, 64, 65, 67, 69, 71, 72}; // 定义传感器连接的模拟引脚 int sensorPin[8] {A0, A1, A2, A3, A4, A5, A6, A7}; // 存储每个传感器当前是否正在触发音符的状态 bool noteActive[8] {false, false, false, false, false, false, false, false};主循环loop()中我们会依次处理每个传感器流程是读取原始模拟值 - 应用滤波算法 - 判断手是否进入“触发区” - 若状态改变则发送MIDI音符开或关消息。4.2 模拟信号滤波应对噪声的关键策略SHARP传感器的原始输出并非绝对稳定即便在没有物体时读数也会因环境光、电源纹波和传感器自身热噪声而有微小波动。如果不处理这些波动会导致音符意外触发或“鬼叫”。因此滤波是软件中最核心的部分。我采用了多重滤波策略移动平均滤波这是最简单有效的第一道防线。我们不只取单次读数而是维护一个小的读数数组例如最近10次每次取平均值。这能平滑掉高频的随机尖峰。// 示例简单的移动平均计算 long sum 0; for(int i0; i10; i) { sum analogRead(sensorPin[n]); } int filteredValue sum / 10;阈值迟滞比较这是防止振荡的关键。我们定义两个阈值一个较低的“触发阈值”和一个较高的“释放阈值”。当滤波后的值低于触发阈值时认为手进入只有当值高于释放阈值时才认为手离开。这两个阈值之间形成一个“迟滞区间”只有当信号明确穿越这个区间时状态才会改变有效避免了在阈值边缘的抖动。#define TRIGGER_THRESHOLD 300 // 低于此值触发音符 #define RELEASE_THRESHOLD 350 // 高于此值释放音符 if(!noteActive[n] filteredValue TRIGGER_THRESHOLD) { // 发送音符开启消息 noteActive[n] true; } if(noteActive[n] filteredValue RELEASE_THRESHOLD) { // 发送音符关闭消息 noteActive[n] false; }动态基线校准可选进阶环境光会缓慢变化。我们可以让程序在启动后几秒钟内记录每个传感器在没有手干扰时的读数作为动态的“基线”。后续的触发判断基于与这个基线的差值而不是固定的绝对阈值适应性更强。4.3 弯音控制与MIDI消息发送弯音的处理相对直接。在主循环中我们读取摇杆X轴的模拟值analogRead(A9)其范围是0-1023。我们需要将其映射到MIDI弯音范围-8192到8191。注意摇杆的中间位置模拟值约512应映射为弯音值0。int joystickValue analogRead(A9); // 将0-1023映射到-8192到8191 long pitchBendValue map(joystickValue, 0, 1023, -8192, 8191); // 为了防止频繁发送消息造成MIDI堵塞可以设置一个死区或发送间隔 if(abs(pitchBendValue - lastPitchBend) 10) { // 变化超过10才发送 usbMIDI.sendPitchBend(pitchBendValue, 1); // 发送到MIDI通道1 lastPitchBend pitchBendValue; }发送音符消息则使用usbMIDI.sendNoteOn(noteNumber, velocity, channel)和usbMIDI.sendNoteOff(noteNumber, velocity, channel)函数。力度velocity可以固定为一个值如100也可以根据手距离传感器的远近进行映射实现力度感应这需要更精细的传感器校准。5. 软件合成器配置与演奏实践5.1 电脑端软件合成器DAW的选择与设置Teensy发出的MIDI信号本身不产生声音它只是指令需要由软件合成器或数字音频工作站来“翻译”并播放。对于初学者我强烈推荐VMPKVirtual MIDI Piano Keyboard。它免费、开源、体积小巧几乎不占用系统资源且设置极其简单。下载安装VMPK后打开软件。首先进入“Edit - Preferences”或类似设置菜单。在“MIDI Connections”或“MIDI设置”选项卡中将“MIDI Input”设置为你的“Teensy MIDI”设备。然后在“Channel”中选择一个通道需与Teensy代码中发送的通道一致默认为1。关闭设置现在你在空气竖琴前挥手应该就能在VMPK的虚拟键盘上看到对应的琴键被点亮并听到默认的钢琴音色。如果你想使用更专业的音色可以将VMPK作为MIDI输入源路由到更强大的DAW软件如Ableton Live、FL Studio、Logic Pro甚至是免费的Cakewalk by BandLab或LMMS。在这些DAW中创建一个MIDI轨道将其输入设置为“Teensy MIDI”然后加载任何你喜欢的虚拟乐器插件VSTi比如一个优质的弦乐、管风琴或合成器音色。这样你的空气竖琴就能演奏出任何你能想象到的声音。5.2 演奏技巧与多层次音符触发逻辑Aetherharp设计为三个层次这是通过软件逻辑实现的而非额外的硬件。我们为每个传感器定义了三个距离区间对应三个不同的音符。例如当手在距离传感器10-15厘米时触发低音区的音符如C2在5-10厘米时触发中音区音符如C3在2-5厘米时触发高音区音符如C4。这通过在代码中为每个传感器设置多组阈值来实现。// 示例单传感器的三层次逻辑 if(filteredValue 200 filteredValue 300) { // 区域1触发低音音符 currentNote baseNote; } else if(filteredValue 100 filteredValue 200) { // 区域2触发中音音符 currentNote baseNote 12; // 提高一个八度 } else if(filteredValue 100) { // 区域3触发高音音符 currentNote baseNote 24; // 提高两个八度 }演奏时你需要练习控制手的高度来精确选择音区。从低音区缓慢抬手至高音区可以奏出滑音效果。同时另一只手操作摇杆进行弯音可以模拟吉他推弦或小提琴揉弦的效果大大增强了音乐表现力。建议从简单的音阶和琶音开始练习逐渐熟悉这种无形的“琴弦”位置感。5.3 系统校准与个性化调整每颗传感器都有微小的个体差异环境光线也不同因此上电后的首次校准至关重要。我通常在代码中设计一个简单的校准模式上电后前5秒不演奏程序自动读取每个传感器在无触发状态下的基准值并据此动态计算触发阈值。你也可以通过串口监视器进行手动校准。将代码中读取到的每个传感器的原始值和滤波值打印出来观察当手在不同高度时数值的变化范围。然后根据这些数据微调代码中的TRIGGER_THRESHOLD和RELEASE_THRESHOLD直到触发和释放反应灵敏且准确。你甚至可以为每个传感器设置独立的阈值以达到最均匀的演奏手感。实操心得校准最好在最终的使用环境下进行。光照条件的改变如打开或关闭顶灯会影响传感器读数。如果设备需要在不同场合使用可以考虑在木板上增加一个“校准按钮”。按下按钮后系统进入10秒的校准周期自动学习当前环境下的基准值并保存到Teensy的EEPROM中下次开机自动加载。6. 常见问题排查与进阶优化6.1 问题排查速查表在制作和调试过程中你可能会遇到以下典型问题。这里提供一个快速排查指南问题现象可能原因排查步骤与解决方案电脑无法识别Teensy为MIDI设备1. USB线仅支持充电不支持数据。2. Arduino IDE中USB类型未设置正确。3. 驱动程序问题。1. 更换为可靠的数据线。2. 确认“工具-USB类型”为“Serial MIDI”。3. 重启电脑或重新安装Teensyduino驱动。传感器无反应或读数始终不变1. 电源未接通或接反。2. 信号线接触不良或接错引脚。3. 传感器损坏。1. 用万用表检查传感器VCC和GND间是否有3.3V电压。2. 检查每根信号线是否焊接牢固引脚定义是否正确。3. 单独测试传感器用手靠近测量信号线电压是否变化。音符意外触发或“粘音”1. 噪声滤波不足阈值设置不当。2. 传感器间距过小手部同时遮挡多个。3. 环境光干扰太强如太阳直射。1. 加强移动平均滤波增大迟滞区间释放阈值-触发阈值。2. 确保传感器间距大于10厘米并练习垂直挥动手掌。3. 在室内使用或为传感器阵列增加遮光罩。弯音控制不灵敏或不回中1. 摇杆模拟引脚接触不良。2. 摇杆本身物理损坏无法回中。3. 代码中映射范围或死区设置不当。1. 检查摇杆三根线的焊接。2. 更换摇杆模块。3. 检查代码中map函数参数并增加中心死区如511-513映射为0。演奏有延迟1. 主循环执行太慢滤波算法过重。2. 软件合成器或DAW缓冲区设置过大。3. 电脑性能不足。1. 优化代码减少不必要的计算和打印。确保使用int而非float进行运算。2. 在DAW或软音源设置中降低音频缓冲区大小如调到128或256采样。3. 关闭不必要的后台程序。连接iPad等移动设备无声移动设备USB口输出功率不足。这是最常见原因。必须为Teensy提供外部供电。方案使用带充电功能的USB HUB或用移动电源通过Teensy的VIN引脚供电需5V。6.2 性能优化与功能扩展建议当基础功能稳定后可以考虑以下优化和扩展让你的空气竖琴更强大力度感应目前我们发送的MIDI力度是固定值。你可以修改代码将传感器读数映射为力度值。距离越近读数越小力度越大。这需要更精确的校准但能实现更细腻的表达。多传感器融合与手势识别利用八个传感器的数据流可以尝试简单的手势识别。例如快速从左向右挥动所有传感器可以触发一个滑音效果或特殊的和弦手在传感器上方停留时间长短可以控制音符的延音Aftertouch。LED视觉反馈在每颗传感器旁边安装一个RGB LED。当音符被触发时LED亮起不同音高用不同颜色表示弯音时LED亮度或颜色可以随之变化。这能极大提升表演的视觉冲击力。Teensy 3.5有足够的引脚通过PWM或WS2812B灯带协议来控制LED。无线化使用带有蓝牙MIDI功能的开发板如Teensy 4.0搭配蓝牙模块或ESP32替代有线连接让演奏者彻底摆脱线缆束缚。但需注意无线传输可能引入轻微延迟对实时演奏有更高要求。外壳与美学设计用更精致的木材、亚克力或金属制作外壳将内部线路完全隐藏。设计优雅的支架使其可以像真正的竖琴一样立于地面演奏。良好的工业设计能让项目从“原型”升级为“产品”。6.3 从项目实践中获得的经验回顾整个项目最大的挑战并非硬件连接而是软件的稳定性和鲁棒性。传感器信号中的噪声是最大的敌人。我花了大量时间试验不同的滤波算法和阈值参数才最终得到一个在各种光照下都表现稳定的系统。这让我深刻体会到在嵌入式交互项目中“读取一个值”和“可靠地解读一个值”是天壤之别。引入迟滞比较是解决开关抖动的银弹而移动平均则是平滑随机噪声的基石。另一个重要经验是关于电源去耦。最初版本中当所有传感器同时工作时偶尔会出现Teensy重启的现象。这是因为传感器在测量时电流会有微小波动多个传感器叠加可能造成电源电压瞬间跌落。解决方案是在Teensy的3.3V输出引脚和GND之间以及每个传感器的VCC和GND之间都焊接一个10uF的电解电容和一个0.1uF的陶瓷电容用于滤除低频和高频噪声。这个改动后系统再也没有出现过意外复位。最后MIDI协议的精妙在于它的简洁和通用性。一旦你的设备能稳定发送标准的Note On/Off和Pitch Bend信息它就瞬间接入了整个数字音乐的世界。你可以用它控制硬件合成器、驱动复杂的软件管弦乐甚至作为灯光秀的触发控制器。这个项目的价值在于它为你打开了一扇门门后是物理世界与数字声音自由交互的广阔天地。