1. 项目概述与核心思路如果你玩过合成器或者接触过电子音乐制作大概率会对“琶音器”这个功能又爱又恨。爱的是它能让简单的几个音符自动循环出复杂的旋律线是营造氛围和节奏的利器恨的是很多硬件琶音器操作逻辑复杂或者功能固定缺乏DIY的乐趣。几年前当我第一次看到类似“Pianocade”这种将街机摇杆按钮和音乐控制器结合的项目时我就萌生了一个想法能不能自己做一个更酷、更开放、既能当MIDI控制器又能独立发声的“玩具”于是就有了这个基于Arduino平台的街机风格琶音合成器。这个项目的核心是一个融合了硬件交互、嵌入式编程和音频合成的DIY电子乐器。它看起来像一个复古的街机摇杆但本质上是一个功能完整的音乐设备。正面两排共12个发光的红色街机按钮构成了一个跨越一个八度的“键盘”用于选择琶音的根音。一个8向街机摇杆负责实时调整速度和音高偏移。正面还有三个功能按钮分别控制琶音的启动/停止、琶音范围1到3个八度以及8种内置琶音模式的切换。它的“大脑”是Adafruit Feather M4 Express这是一块基于ATSAMD51 Cortex-M4内核的开发板性能足以运行复杂的音频合成代码。通过一块MIDI FeatherWing扩展板它同时具备了USB MIDI和传统5针DIN MIDI输出能力。而最吸引人的是它内置了一个基于Teensy Audio Library的四声道方波合成器可以直接从3.5mm耳机孔输出温暖的芯片音乐Chiptune风格音色——这意味着即使不连接电脑或其他合成器它本身就是一个能出声的乐器。为什么选择这样的方案首先模块化设计极大降低了制作门槛。Adafruit的LED街机按钮板1x4 STEMMA QT将4个按钮的开关和LED驱动集成在一块小板上并通过I2C总线通信这意味着你不需要为16个按钮焊接32根线只需用4根线的STEMMA QT电缆串联即可布线整洁度提升了不止一个量级。其次Feather生态系统的兼容性让扩展变得异常简单。Feather M4作为主控MIDI FeatherWing提供专业音频接口FeatherWing Proto板用于搭建额外的音频输出电路FeatherWing Tripler则将这三块板子牢固地堆叠在一起这种“乐高式”的组装方式非常适合原型制作和爱好者项目。最后软件层面的灵活性是开源硬件的精髓。项目提供的固件基于Arduino框架使用了专门为音乐应用优化的Arpy琶音引擎库和强大的Audio Library。你可以轻松修改琶音模式、调整合成器音色比如把方波换成锯齿波或三角波甚至改变整个设备的控制逻辑这远非市面上大多数封闭系统的商业产品所能比拟。简单来说这个项目适合三类人一是电子音乐爱好者和制作人想要一个独特、可定制的硬件控制/音源二是嵌入式开发者和硬件极客对结合了物理交互、实时音频和通信协议的项目感兴趣三是DIY和创客社区的朋友享受从激光切割亚克力外壳到编写每一行代码的完整创造过程。它不是一个“黑箱”产品而是一个完全开放、可供你拆解、学习和重塑的音乐伙伴。2. 核心硬件选型与电路设计解析制作这样一个设备硬件选型是基石。每一个部件的选择都直接影响了最终的功能、可靠性和制作体验。我们不能只是照单采购更需要理解其背后的“为什么”。2.1 主控与扩展板Feather生态的优势项目的核心是Adafruit Feather M4 Express。为什么是它而不是更常见的Arduino Uno或Teensy关键在于性能与生态的平衡。ATSAMD51芯片Cortex-M4 120MHz提供了远超传统AVR芯片如Arduino Uno的ATmega328P的处理能力这对于实时音频合成和多任务处理同时处理16个按钮、摇杆输入、MIDI输出和音频渲染至关重要。其内置的硬件浮点运算单元FPU能高效处理音频算法。同时Feather M4原生支持USB MIDI无需额外芯片即可被电脑识别为标准的MIDI设备极大地简化了开发。MIDI FeatherWing是专业性的体现。虽然Feather M4可以通过USB发送MIDI但很多老式或专业的硬件合成器、音源模块只接受传统的5针DIN MIDI接口。这块扩展板基于经典的6N138光耦隔离电路设计确保了MIDI信号电气隔离的稳定性和抗干扰能力符合MIDI 1.0标准。它直接插在Feather Tripler上将主控的串口Serial1信号转换为标准的MIDI电流环信号输出。FeatherWing Proto板和FeatherWing Tripler是项目的“连接骨架”。Proto板为我们提供了一个自定义的焊接区域。在这里我们搭建了一个简单的RC低通滤波电路一个1kΩ电阻串联一个10uF电容到地连接在Feather M4的模拟音频输出A0和3.5mm耳机插孔之间。这个电路的作用是滤除音频信号中来自数字电路的高频噪声通常在人耳可听范围之上让输出的声音更干净。Tripler则是一个三层的堆叠板用尼龙支柱固定它同时为Feather主控、MIDI Wing和Proto板提供稳固的机械连接和电气连接避免了飞线让内部结构井然有序。2.2 输入设备街机按钮与摇杆的工程化处理输入部分是这个控制器的灵魂其设计充分考虑了用户体验和工程实现的简化。LED Arcade Button 1x4 STEMMA QT 分线板是这个项目的点睛之笔。每个板子管理4个街机按钮包括机械开关检测每个按钮的开关信号通过板载的seesaw协处理器实际上是一个ATTiny8系列MCU读取并通过I2C总线汇总上报给主控。这解决了传统矩阵扫描或直接GPIO读取需要大量引脚和软件去抖的问题。LED PWM驱动板子直接驱动按钮的LED并通过I2C接受主控的亮度控制指令0-255。我们可以轻松实现按下亮起、当前根音高亮等视觉效果。I2C地址配置为了将4块板子串联在同一条I2C总线上必须为它们设置不同的地址。板子上的A0和A1跳线焊盘就是用于此目的。通过切割特定的焊盘轨迹可以将默认地址0x3A改为0x3B、0x3C或0x3D。这是硬件配置的关键一步如果地址冲突所有按钮将无法正常工作。街机摇杆的选择也很有讲究。项目选用的是8向带微动开关的摇杆而非模拟电位器摇杆。这意味着上、下、左、右四个方向分别对应四个独立的数字开关。它的好处是编程简单直接读取数字引脚的高低电平手感清晰有明确的“咔哒”触感功能定义明确左/右控制速度增减上/下控制八度偏移。使用模拟摇杆虽然能提供连续值但对于BPM速度和八度这种通常按步进调整的参数来说数字开关反而更直观、不易误操作。布线技巧与实战心得颜色编码如原文作者所述用不同颜色的热缩管或电线标记按钮的LED正负极和开关线在组装16个按钮时能救命。我建议采用更系统的方法用红/黑代表LED的/ -用黄/白代表开关的两极开关无极性但统一颜色便于区分。为每一排4个按钮的线缆束使用同一种颜色的扎带这样在最后插接到分线板时能快速定位。电源考量16个高亮LED同时点亮时电流不小。Feather M4的3.3V输出引脚可能无法提供足够电流导致电压下降或板子重启。项目通过I2C分线板供电是可行的因为seesaw芯片内部对LED电流有限制。但如果你计划使用更耗电的组件需要考虑外接5V电源并通过Proto板合理分配。防反接保护虽然开关线无极性但LED线接反了灯就不会亮。在焊接或插接前用万用表的二极管档或通断档快速测试一下每个按钮的LED极性并做好标记能避免后续开箱检查的麻烦。2.3 外壳与结构设计从图纸到实物的细节激光切割的亚克力外壳不仅是为了美观更是整个项目的物理基础。设计文件SVG格式包含了底板、侧板、前面板、后面板、多层顶板以及所有按钮、摇杆的安装孔。材料选择3mm约1/8英寸厚度的亚克力是强度和重量的良好平衡。磨砂灰色和黑色能营造复古的工业感而 translucent white半透明白用于顶板可以让按钮的LED光柔和地透出增加氛围感。切割时务必注意将亚克力的保护膜面朝上进行切割这样切割产生的熔边会在背面正面保持光滑。组装顺序是关键从原文的步骤图可以看出组装遵循着“由内到外自下而上”的逻辑先固定核心电路将4块街机按钮分线板用M2.5尼龙支柱固定在底板上。这里有一个极易出错的细节分线板的方向。必须确保每块板子的STEMMA QT插座朝向一致通常是朝向控制器中心否则后续的串联电缆会无法顺畅连接或者长度不够。再安装堆叠主板将组装好的Tripler包含Feather M4、MIDI Wing、Proto板用支柱固定在底板上并立即用200mm长的STEMMA QT电缆将第一块按钮分线板与Proto板上的QT插座连接。此时可以做一个上电初步测试仅连接USB检查Feather M4的电源灯和按钮板上的电源指示灯是否亮起。安装面板与按钮按照后面板Reset/Enable开关、侧板、前面板三个功能按钮、顶板12个主按钮的顺序逐一安装。每安装完一层建议就连接该层的所有线缆。例如装好后面板就接好两个开关的线装好前面板就接好那三个按钮到第四块分线板。最后总装与测试在合上最顶层的亚克力板并拧紧所有M4螺丝之前务必进行一次全面的功能测试原文也特别强调了这一点。接上USB和耳机测试每个按钮的触发和LED反馈测试摇杆四个方向的功能测试MIDI输出如果有硬件的话。一旦封箱再发现问题拆解将非常耗时耗力。结构稳固性使用M4 x 80mm的长螺丝从顶部贯穿到底部并用螺母在底板下方锁紧形成了非常坚固的框架结构。底部的橡胶脚垫或金属键盘脚垫既保护了桌面也抬高了机身让底部的螺丝头和螺母不会直接接触桌面同时也有利于散热。3. 软件架构与代码深度剖析硬件是躯体软件才是灵魂。这个项目的固件虽然代码量不大但巧妙地整合了多个库实现了实时性要求很高的多任务处理。我们来逐层拆解。3.1 核心库与初始化项目依赖于几个关键的Arduino库Adafruit_TinyUSBMIDI.h提供USB MIDI功能。Audio.hTeensy Audio Library一个功能极其强大的音频合成、处理库被移植到了SAMD51平台。它提供了高质量的音频对象如波形发生器、滤波器、包络、混音器和低延迟的音频渲染引擎。Bounce2.h用于按钮和摇杆开关的消抖处理。机械开关在闭合或断开的瞬间会产生一系列快速的通断抖动这个库能有效过滤这些抖动确保一次物理按压只触发一次逻辑动作。Adafruit_seesaw.h用于与LED街机按钮分线板上的seesaw协处理器通信通过I2C读取开关状态和控制LED亮度。Arpy.h一个自定义的琶音引擎库负责根据根音和选定的模式生成琶音音符序列。ADT.hmidi_to_freq.hADT.h包含了由Audio System Design Tool一个图形化音频流设计工具生成的音频连接补丁。midi_to_freq.h则是一个将MIDI音符编号转换为对应频率的查找表。在setup()函数中代码完成了以下关键初始化I2C高速模式Wire.setClock(400000);将I2C总线速度设置为400kHz确保16个按钮状态和LED控制指令的通信流畅。MIDI初始化同时初始化了USB MIDI (MIDIusb)和通过Serial1的经典MIDI (MIDIclassic)。MIDI_CHANNEL_OMNI模式表示监听所有MIDI通道。摇杆引脚配置将摇杆的四个方向引脚设置为输入上拉模式并专门使用一个引脚D6设置为输出低电平作为摇杆开关的公共地。这是一种常见的节省引脚和简化布线的方法。LED Arcade板初始化循环检测4块分线板地址0x3A到0x3D是否在线并配置所有按钮引脚为输入上拉模式初始化所有LED为低亮度。琶音器与音频合成初始化设置琶音器的音符开关回调函数、初始BPM、门时间等。初始化Audio库分配内存设置滤波器截止频率、包络参数起音、衰减、延音、释音等。3.2 主循环与实时控制逻辑loop()函数是实时响应的核心它必须快速执行不能有长时间阻塞。其逻辑流如下void loop(){ arcadeButtonCheck(); // 1. 检查所有按钮状态 // 2. 更新摇杆消抖状态 joyDown.update(); joyUp.update(); joyLeft.update(); joyRight.update(); // 3. 处理摇杆“按下”事件单次触发 if ( joyUp.fell() ) { octave_offset octave_offset 1; if( octave_offset7) { octave_offset7; } arp.setOctaveOffset(octave_offset); // ... 视觉反馈 ... } // ... 处理 joyDown.fell() ... // 4. 处理摇杆“按住”事件自动重复 int joyLeftVal joyLeft.read(); if( joyLeftVal LOW ) { bpm bpm - 1; if(bpm 100) { bpm 100; } arp.setBPM( bpm ); // ... 视觉反馈 ... } // ... 处理 joyRight.read() ... // 5. 更新琶音器状态 arp.update(root_note); // 6. 简单的定时任务此处用于控制LED反馈的持续时间但原代码中未实现 if( millis() - lastControlMillis 20 ) { lastControlMillis millis(); } }关键设计解析分时处理将按钮检查、摇杆状态更新、事件处理、琶音器更新等任务拆分每次循环只做少量工作保证整体响应速度。两种摇杆交互对于“八度偏移”上/下使用了.fell()事件即只在摇杆从松开到按下的瞬间触发一次。这适合离散的、步进式的调整。对于“速度调整”左/右则使用了.read()直接读取当前状态并在按住时持续增减BPM实现了“自动重复”的效果方便快速调节。视觉反馈任何用户操作都伴随LED的即时反馈。例如按下前面板的功能按钮该按钮的LED会闪烁或改变亮度用摇杆调整参数时对应的功能按钮LED也会短暂高亮。这种即时反馈对于没有屏幕的设备至关重要让用户明确知道设备接收到了指令。3.3 音频合成与MIDI输出通路音频生成和MIDI发送是在noteOn(uint8_t note)和noteOff(uint8_t note)这两个回调函数中完成的它们由Arpy库在需要播放或停止一个音符时调用。音频合成路径波形生成当琶音器触发一个音符例如MIDI编号48即C3时noteOn函数会调用四个AudioSynthWaveform对象wave0到wave3让它们以该音符对应的频率从midi_to_freq查找表获取开始播放方波WAVEFORM_SQUARE。失谐效果仔细观察四个波形发生器的频率略有不同* 1.01,* 1.005,* 1.025。这是一种经典的失谐手法让多个相同波形但略有音高差异的声音叠加会产生更丰满、更具“合唱”感的音色避免了纯方波的单薄和刺耳。混合与处理四个波形信号送入一个四通道混音器mixer0然后经过一个包络发生器env0来塑造音量的动态按下有声松开渐弱。接着通过一个状态变量滤波器filter0虽然代码中滤波器频率被设为固定最大值6000Hz但这里预留了滤波控制的可能性。最后信号被送到最终的立体声输出混音器mixerL,mixerR和AudioOutputAnalogStereo对象从Feather M4的A0左和A1右引脚输出模拟音频。物理输出A0和A1输出的模拟信号经过Proto板上的RC低通滤波电路进入3.5mm耳机插孔驱动耳机或有源音箱。MIDI输出路径 在同一个noteOn和noteOff函数中除了生成音频还会同步发送标准的MIDI Note On和Note Off消息。MIDIusb.sendNoteOn(note, 127, 1);通过USB发送音符开消息音符力度为127最大通道为1。MIDIclassic.sendNoteOn(note, 127, 1);通过Serial1和MIDI FeatherWing硬件发送给5针DIN MIDI输出口。一个重要的细节在noteOff中发送的也是Note On消息但力度velocity为0。这在MIDI协议中是标准且等效于Note Off消息的做法被所有MIDI设备兼容。同时代码中还有一个midiPanic()函数它会遍历所有128个MIDI音符并发送力度为0的Note On消息用于在琶音器停止或出现异常时强制关闭所有可能“卡住”的音符这是一个非常实用的安全措施。3.4 琶音模式与自定义琶音的核心逻辑封装在Arpy.h库中。在源代码里我们可以找到琶音模式的定义int8_t arps[arp_count][arp_len] { {0, 4, 7, 12}, // 大三和弦 {0, 3, 7, 10}, // 小七和弦 {0, 3, 6, 3}, // 减和弦 {0, 5, 7, 12}, // 挂四和弦 {0, 12, 0, -12}, // 八度跳跃1 {0, 12, 24, -12}, // 八度跳跃2 {0, -12, -12, 0}, // 低音八度 {0, 0, 0, 0}, // 单音重复 };每一行代表一种琶音模式数组中的数字表示相对于根音的音程偏移以半音为单位。例如{0, 4, 7, 12}表示依次播放根音、上方大三度、上方纯五度、上方八度这正好构成一个大三和弦的分解琶音。自定义你的琶音这是项目最大的乐趣点之一。你可以修改这些数字来创建任何你想要的音程组合。例如{0, 7, 12, 19}一个更开阔的五度八度进行。{0, 2, 4, 7, 11}一个五音模式可以创造出更复杂的旋律线。{0, 12, 7, 19}一个上下跳跃的八度模式。修改后重新编译上传固件你的控制器就拥有了独一无二的琶音风格。你甚至可以修改arp_len来改变每个模式的步进数或者增加新的模式数组。4. 组装、调试与问题排查全记录即使按照教程一步步来在制作这样一个涉及硬件、软件、结构的多维度项目时也难免会遇到问题。下面是我在复现过程中遇到的一些典型情况及解决方案希望能帮你避开这些坑。4.1 硬件组装阶段常见问题问题1按钮LED不亮或只有部分亮。排查步骤检查电源首先用万用表测量Feather M4的3.3V输出是否稳定。如果电压低于3V可能是USB供电不足尝试更换USB线或使用带电源的USB集线器。检查I2C地址这是最常见的问题。确认四块LED Arcade板上的A0/A1跳线切割正确。使用一个简单的I2C扫描程序Arduino IDE的示例里有上传到Feather扫描地址。你应该看到0x3A,0x3B,0x3C,0x3D四个地址。如果缺少某个地址检查对应的板子焊接和跳线。检查STEMMA QT连接确认4根线的电缆连接顺序正确并且插接牢固。电缆是否从地址0x3A的板子依次连接到0x3D最后一根是否接到了Proto板的QT端口检查LED极性用万用表通断档测试每个按钮的LED引脚。当红表笔接LED正极通常有“”标记或更长引脚黑表笔接负极时LED应微亮。如果确认接反需要调整线序。问题2按钮按下无反应但LED能控制。排查步骤检查开关接线开关线是否插到了分线板上标有SW1-SW4的端口而不是PWM端口开关线本身是否导通检查软件配置确认代码中#define NUM_BOARDS 4与你实际使用的板子数量一致。检查SWITCH1-SWITCH4的引脚定义是否与seesaw板一致通常不需要改。检查内部上拉代码中已配置INPUT_PULLUP这意味着开关另一端应接地。确认你的开关接线一端接信号另一端接的是GND而不是3.3V。问题3摇杆控制失灵或方向相反。排查步骤检查接线对照原理图确认摇杆的“上”、“下”、“左”、“右”四个引脚分别接到了Proto板正确的引脚上D12, D11, D9, D10。公共地线是否接到了D6并在代码中设置为LOW输出检查逻辑电平摇杆未按下时由于内部上拉读取的应该是HIGH1。按下时引脚通过开关连接到D6地读取到LOW0。可以用Serial.println()分别打印四个引脚的状态来验证。方向映射如果上下左右逻辑正确但功能相反例如按左速度增加只需在代码中交换joyLeft和joyRight的处理逻辑即可。问题4没有音频输出或输出噪音很大。排查步骤检查耳机插孔焊接确认3.5mm耳机插孔的左、右、地三个焊点没有短路或虚焊。特别是RC滤波电路1kΩ电阻串联10uF电容到地是否正确连接在A0和地之间。检查Audio库初始化AudioMemory(120);分配了音频内存。如果这个值太小可能导致音频破裂或无输出。如果添加了更复杂的音频处理可以适当增大此值。排查数字噪声如果输出有高频“嘶嘶”声RC滤波电路是关键。确保电容10uF是电解电容注意其极性负极通常对应地。可以尝试将电容值增加到22uF或在电源入口处增加一个更大的滤波电容如100uF。4.2 软件调试与功能验证在完全封箱前进行分段测试至关重要。第一阶段测试基础IO与I2C上传一个最简单的I2C扫描程序确认所有4块按钮板被正确识别。上传一个测试程序循环点亮每一块板子上的每一个LED。确保所有16个LED都能受控亮灭且亮度可调。第二阶段测试按钮与摇杆输入修改示例代码将loop()中处理声音和MIDI的部分注释掉只保留arcadeButtonCheck()和摇杆状态读取。使用Serial.println()将按下的按钮编号和摇杆方向打印到串口监视器。确保每个物理按键都对应唯一的编号0-15且摇杆四个方向能正确触发。第三阶段测试音频与MIDI输出恢复音频和MIDI代码。对于音频接上耳机按下按钮你应该能听到清晰的方波声音。用摇杆调整速度和八度听变化是否流畅。对于USB MIDI用一根USB线连接控制器和电脑。打开一个DAW如Ableton Live, FL Studio或MIDI监视软件如MIDI-OX。在软件中设置输入设备为该控制器。按下按钮你应该能在软件中看到接收到的MIDI音符信息。对于经典MIDI用5针MIDI线连接控制器的MIDI OUT到一台硬件合成器或MIDI接口的MIDI IN。将合成器设置为接收通道1确保能触发声音。4.3 进阶优化与自定义建议当设备基本功能正常后你可以考虑以下优化增加视觉反馈模式目前的LED反馈比较基础。你可以修改lightLED()函数实现更炫的效果比如呼吸灯、按下时涟漪扩散、根据BPM闪烁等。扩展合成器音色Audio Library支持多种波形正弦波、三角波、锯齿波、脉冲波。你可以修改waveform变量或甚至加入第二个振荡器进行调频FM合成创造更丰富的芯片音乐音色。还可以将滤波器频率设置为可调例如用另一个摇杆轴或电位器增加音色变化。保存用户设置Feather M4有内置的Flash存储可以使用EEPROM库或FlashStorage库来保存用户最后一次设置的BPM、琶音模式、八度偏移等实现关机记忆功能。实现MIDI CC控制除了音符你还可以让摇杆或某些按钮发送MIDI控制改变CC信息用于在DAW中控制滤波器、混响等参数。外壳个性化亚克力外壳可以喷涂、贴膜或内部加入可编程的RGB灯带打造独一无二的外观。这个街机风格琶音器项目的魅力在于它完美地结合了直观有趣的物理交互、专业的音乐协议支持和深度可定制化的开源软件。从第一颗螺丝拧紧到第一段属于自己的琶音旋律响起整个过程充满了硬件DIY和音乐创作的双重成就感。它不仅仅是一个工具更是一个激发创意的平台。希望这份详细的解析和记录能帮助你顺利打造出属于自己的那台音乐街机。