AI写歌,这个ESP32教你弹奏
让AI写一段曲子,听它演奏,然后让板子教你弹奏它
选择一种情绪,点击WRITE,AI就会创作一段简短的旋律。板子会演奏它,并随着演奏点亮每个琴键。然后点击LEARN,它就变成了一位老师:它会一次点亮一个琴键,等你按下它,一个音符接一个音符,直到你自己完整地弹奏出整首曲子。
922-这是AI音乐文章(当前文章)
923-钢琴项目在这里。
它随时仍然是一架完整的21键钢琴——直接弹奏即可。
Robojax_Makerfab即可。使用它不会花费您任何费用,同时也有助于支持本站的免费代码和教程。屏幕

顶部有六个按钮,下面是一个21键键盘——三行七列,从C3到B5。与钢琴项目不同,这里没有黑白键布局,因为AI被限制为只能使用七个自然音符,而这个网格就是这些音符的呈现方式。
| 按钮 | 功能 |
|---|---|
| STYLE | 循环切换情绪:HAPPY、SAD、SPOOKY、FOLK、LULLABY。这就是发送给AI的内容。 |
| WRITE | 请求AI以该情绪创作一段旋律。思考时显示WAIT,然后播放返回的旋律。 |
| PLAY | 重新播放当前加载的旋律。再次点击可停止。 |
| LEARN | 教学模式——点亮一个琴键并等待您按下。 |
| WAVE | 音色:SOFT、ORGAN或BRIGHT。 |
| VOL | 点击以步进音量1到5。标签显示当前级别。 |
板子启动时的音量由程序顶部附近的#define VOLUME设置,因此您可以编译您偏好的音量级别,同时仍然可以在运行时更改它。
AI实际生成的内容
这部分值得精确说明,因为很容易被夸大。AI并不生成音频。生成实际的波形需要大型模型和显卡;没有微控制器能做到这一点,任何声称能做到的人都是在播放其他地方渲染的文件。
它生成的是一个音符列表,以普通文本形式呈现:
[{"n":"C4","ms":300},{"n":"E4","ms":300},{"n":"G4","ms":600}]
板子使用ArduinoJson解析该内容,并使用与钢琴项目相同的合成器来播放它。一次简短的文本请求只需花费不到一分钱,而且一旦旋律到达,即使断开互联网也可以无限次重播。
为什么提示词要限制AI
请求告诉模型它只能使用这个键盘上实际存在的21个音符——从C3到B5的自然音,没有升号或降号。这不是合成器的限制,合成器可以播放任何频率。这样做有两个充分的理由:
- 它写的每个音符都是LEARN模式实际上可以教您的,因为每个音符都有对应的琴键
- 保持在同一个调内意味着结果听起来总是有音乐性的,即使模型状态不佳时也是如此
解析语言模型的回答
模型喜欢表现得乐于助人,在这里意味着用markdown代码围栏包裹答案,并添加一句友好的说明来描述它们写了什么。程序会坚定地要求纯JSON格式,然后防御性地提取第一个[和最后一个]之间的所有内容。任何无法放置在键盘上的音符都会被跳过,只有至少四个可用音符保留下来时结果才会被接受。对不完美输出的容忍是任何解析AI文本的项目中大部分工作的核心。
空回复以及如何避免它
如果你更换模型或提示词,有一件事会让你措手不及。DeepSeek 在回答之前会思考,而这种思考会与回答共用同一个 max_tokens 预算。如果你问它一个难题,它可能会把整个预算都花在思考上,然后返回一个空回复——一个成功但内容为空的请求。
在这个项目中,这表现为较难的情绪模式失败,而简单的模式却能正常工作。SPOOKY 和 LULLABY 需要小调,而当所有升号和降号都被禁止时,这确实很难,所以模型会反复斟酌——然后预算耗尽。C 大调的 HAPPY 则立即回答了。
有两种修复方法,这个草图两种都用到了。请求会发送 "thinking": {"type": "disabled"},这会完全关闭推理功能,这样整个预算都用于回答,回复速度也会快得多。而且提示词现在会告诉模型如何在不使用升号的情况下表现出小调的感觉——将旋律中心放在 A 或 E 上,这样使用的音符是相同的。
finish_reason。length 表示预算耗尽——请提高 MELODY_TOKENS。stop 表示模型选择不输出任何内容,这属于提示词问题。教学模式
点击 LEARN,一个键会变成绿色。按下它,开发板会前进到下一个音符。按错键时仍然会发声——毕竟这是一架钢琴——但不会继续前进。状态栏会统计你的进度,当你到达终点时,它会告诉你。
没有时间压力,也没有分数。它会等你多久都行,这正是它能真正用于学习一段乐句而不是仅仅作为新奇玩意的原因。
没有 WiFi 也能工作
草图中内置了一段旋律,所以 PLAY 和 LEARN 在完全没有网络的情况下也能工作。只有 WRITE 需要互联网——而且只需要一个 DeepSeek 密钥。这个项目不需要 Azure 或 OpenAI 账户。
测试时,先点击 PLAY:这会在涉及任何网络之前确认音频路径和键盘是否正常,所以如果之后 WRITE 失败,你已经知道该从哪里排查了。
进一步拓展的想法
- 通过编辑风格列表,要求生成一首“水手号子风格”的旋律。
- 让它写出与第一句相呼应的第二句。
- 将旋律保存到 SD 卡,让开发板随着时间积累出一本歌曲集。
- 添加语音助手项目中的麦克风,这样你就可以说出请求,而不是点击预设按钮。
关于 MaTouch AI ESP32-S3 2.8" 开发板
此页面上的每个项目都运行在 Makerfabs 的 MaTouch AI ESP32-S3 2.8" TFT ST7789V 上。这是一块一体化开发板:彩色触摸屏、300 万像素摄像头、两个麦克风和一个真正的扬声器放大器,全部由带有 8 MB PSRAM 的 ESP32-S3 驱动。正是这种组合使得这些 AI 项目可以在单块开发板上实现,无需外接任何其他设备。
8 MB 的 PSRAM 比这里任何其他数字都重要。它让开发板能够同时在内存中保存一帧摄像头画面、几秒钟的录音或一段 base64 编码的照片——这些都无法容纳在 ESP32 的常规 RAM 中。
制造商文档:Makerfabs wiki 页面。
这块开发板的其他每个项目——摄像头、离线人脸识别、AI 语音助手、AI 视觉和绘图项目——都有各自的教程。所有链接都在本文下方。
主要规格
- 处理器:ESP32-S3,双核 240 MHz,WiFi 2.4 GHz + 蓝牙 5.0
- 内存:16 MB 闪存,8 MB PSRAM(这里几乎所有项目都需要)
- 显示屏:2.8" IPS,320×240,ST7789V 驱动,SPI 接口
- 触摸:GT911 电容式,可同时追踪 5 个手指
- 摄像头:OV3660,300 万像素,最高 2048×1536
- 麦克风:两个 INMP441 I2S 数字麦克风(真正的立体声对)
- 扬声器:MAX98357A D 类放大器,4 Ω 下 3.2 W
- 存储:microSD 卡槽(SPI 模式)
- 电源:USB-C、JST 电池连接器、TP4056 充电器、电源开关
- 板上其他组件:WS2812B RGB LED、PCF8563T 电池供电实时时钟,以及一个未在官方规格中列出的 MAX17048 电池电量计
USB CDC On Boot设置为Disabled。使用错误的端口会导致音频异常或上传失败。使用电池供电? 两个USB-C插座、TP4056充电器和电源开关的完整说明(含原理图)请参阅开发板测试文章——包括哪个插座用于充电以及开关应处于开还是关状态。
Arduino IDE设置
这些设置很重要。人们报告的大多数与此开发板相关的问题都是其中一项设置错误所致,而且这些设置在更改核心版本时会重置,因此任何更改后请重新检查。
| 设置 | 值 |
|---|---|
| 开发板 | ESP32S3 Dev Module |
| ESP32核心版本 | 2.0.17 |
| PSRAM | OPI PSRAM |
| Flash大小 | 16MB(128Mb) |
| 分区方案 | 16M Flash(3MB APP/9.9MB FATFS) |
| USB CDC On Boot | Disabled |
| 上传速度 | 921600 |
| 上传前擦除全部Flash | Disabled |
| 端口 | CH340K USB-C端口 |
如果上传失败:手动将开发板置于下载模式
大多数情况下,只需点击Upload即可成功。但有时不会——IDE会停留在Connecting......状态,然后以Failed to connect to ESP32-S3: No serial data received错误退出。
这是因为IO0在此开发板上同时承担三项任务:它是BOOT按钮、来自CH340K的自动复位线,以及RGB LED的数据线。当开发板上已运行的草图正在驱动该LED时,它可能与自动复位冲突,导致芯片重启到旧草图而非引导加载程序。
解决方法只需五秒钟。手动将其置于下载模式:
- 按住BOOT按钮。
- 在按住BOOT的同时,按下RESET并松开RESET。
- 然后松开BOOT。屏幕变空白——这是引导加载程序在等待。
- 点击Upload。
- 完成后,按一次RESET以运行新草图。
如果仍然无法连接,请将Upload Speed降至115200并重试。同时检查开发板的电源开关是否已打开——即使开发板本身已关闭,CH340K仍会枚举并提供COM端口,这常常会误导人。
所需库
此项目需要下表中的所有库——不多不少。大多数可直接从Arduino IDE的Tools → Manage Libraries安装,但GFX Library for Arduino必须从ZIP文件安装。版本号很重要,请务必使用所列出的确切版本。
| 库 | 版本 | 作者 | 安装来源 |
|---|---|---|---|
| GFX Library for Arduino | 1.5.6 | moononournation | ZIP文件——见下文 |
| bb_captouch | 1.3.1 | Larry Bank | 库管理器 |
| ArduinoJson | 7.x | Benoit Blanchon | 库管理器 |
| Adafruit NeoPixel | 任意近期版本 | Adafruit | 库管理器 |
从ZIP文件安装GFX库
- 下载ZIP文件。它包含在本项目的下载中,或者你也可以从Arduino_GFX 仓库获取——点击绿色的Code按钮,然后选择Download ZIP。
- 将其保存到你能再次找到的位置。不要解压。
- 在Arduino IDE中,点击Sketch → Include Library → Add .ZIP Library。
- 浏览到你下载的ZIP文件并点击Open。
- IDE会安装它并在窗口底部确认。如果你已经安装了1.6版本,请先从
Documents/Arduino/libraries中删除该文件夹,否则两者会发生冲突。
设置 secrets.h
你的WiFi信息和任何API密钥都放在secrets.h中,该文件包含在下载中并带有占位符值。在Arduino IDE中打开该标签页,将其替换为你自己的信息。
secrets.h中使用该名称。获取你的API密钥
本项目与云端AI服务通信,因此你需要自己的密钥。如果你从未做过这件事,不用担心——它就像密码一样,用于向服务标识你的账户。只需几分钟,一次即可。
DeepSeek——思考部分
DeepSeek是实际回答你问题的语言模型。它价格低廉——几美元的额度可以覆盖数千次回复。
- 前往platform.deepseek.com并创建账户。
- 在菜单中打开API keys,点击Create new API key。
- 立即复制它。它只显示一次,之后不再显示——如果你丢失了,请删除该密钥并重新创建一个。
- 在Top up下添加少量额度。没有免费层级,但最小的充值在这种使用量下可以维持很长时间。
将密钥放入secrets.h中,作为DEEPSEEK_KEY。它以sk-开头。
deepseek-chat和deepseek-reasoner已退役,因此你在网上找到的大多数教程都会以400错误失败。请使用deepseek-v4-flash,这些项目已经设置好了。运行成本
非常少,但并非免费,在让项目持续运行之前,你应该大致了解自己在花费多少。
| 服务 | 大致费用 |
|---|---|
| DeepSeek | 每次回答不到一分钱——几美元可获得数千次回复 |
价格会变化,因此请将这些视为参考而非报价。这些服务都有使用页面,你可以查看已花费的金额,并且它们都允许你设置消费限额——第一天就设置是值得的。
故障排除
| 症状 | 原因和解决方法 |
|---|---|
| 屏幕保持黑屏 | GFX库版本错误(请使用1.5.6)或开发板设置错误。 |
PSRAM alloc failed |
Tools → PSRAM未设置为OPI PSRAM。 |
| 无法上传 / 没有COM端口 | USB-C端口错误,或CH340驱动未安装。 |
|||您可能需要的东西
资源与参考
-
文档Makerfabs MaTouch ESP32-S3 2.8" Camera and Touchscreen: User's Manualwiki.makerfabs.com
-
文档
-
外部Makerfabs websitemakerfabs.com