这个过程中有什么不明白的自己问ai, 网络问题自己解决.
arduino ide v1.8
esp32支持包
github.com/espressif/arduino-esp32
https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json,在arduino ide里添加这个源 我安装的是2.0.17版.
买的是"esp32-c3 经典版",它自带串口要安装CH343这个驱动,arduino里的开发板型号选AirM2M_CORE_ESP32C3.然后esp32c3用usb线连接电脑,在arduino的"端口"里选非COM1的那个,在没有其它COM端口设备的情况下我这里显示的是COM11
arduino 里额外安装的依赖库,zip包要手动安装.
MIDI Library版本号:5.0.2,这个可以在arduino里搜索并安装.
github.com/lathoub/Arduino-BLE-MIDI
网页链接(下载这个最新的版本,不要去releases页面下载旧版本).
github.com/h2zero/NimBLE-Arduino
编译下面的代码并烧录到esp32c3后,可以在arduino ide里打开串口窗口查看信息.
我用的是安卓系统手机,打开蓝牙,搜索并点击"ESP32-MIDI",首次连接有可能只显示为一个MAC地址,点击它进行配对,此时如果esp32c3蓝牙连接成功led灯会亮,然后关闭手机的蓝牙并再次开启(第一次是用手机自身的蓝牙程序连接进配对,以后只能用其它应用进行蓝牙连接),下载SynprezFM这个免费软件,我用的版本是2.3.6,点击右上角的三个点的图标,选扫描蓝牙键盘它会自动连接esp32.或者下载"MIDI+BTLE",运行后点击start bluetooth scan扫描并连接ESP32-MIDI,然后运行SynprezFM就行.
示例代码,连接成功会后LED灯会亮并且循环发送C键的midi信号:
#include <BLEMIDI_Transport.h>
#include <hardware/BLEMIDI_ESP32_NimBLE.h>
#include <WiFi.h> // 引入Wi-Fi库以执行彻底关闭操作
#include <esp_wifi.h> // 引入底层Wi-Fi配置库以彻底释放系统资源
// 蓝牙MIDI设备名字.
BLEMIDI_CREATE_INSTANCE("ESP32-MIDI", MIDI)
unsigned long lastNoteTime = 0; // 记录上一次发送音符动作的时间戳
unsigned long lastCheckTime = 0; // 记录上一次检测蓝牙连接状态的时间戳
bool isConnected = false; // 蓝牙连接状态标志,true为已连接,false为断开
bool noteOn = false; // 音符开关状态,true表示当前处于NoteOn状态,false表示NoteOff状态
void setup() {
Serial.begin(115200);
delay(1000); // 启动延迟,等待串口稳定
Serial.println("--- BLE MIDI System Started ---");
WiFi.mode(WIFI_OFF); // 设置Wi-Fi模式为关闭
esp_wifi_stop(); // 彻底停止Wi-Fi驱动并释放其占用的硬件及系统流资源
// 配置内置LED引脚为输出模式
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW);
MIDI.begin();
}
void loop() {
MIDI.read();
unsigned long now = millis();
// 限制底层蓝牙状态查询的频率(每50ms查询一次,降低CPU开销,防卡顿)
if (now - lastCheckTime >= 50) {
lastCheckTime = now;
bool realConnectionState = false; // 实时连接状态缓存
NimBLEServer* pServer = NimBLEDevice::getServer(); // 获取当前运行的NimBLE服务器实例
if (pServer != nullptr) {
realConnectionState = (pServer->getConnectedCount() > 0); // 如果连接数大于0,说明仍处于连接状态
}
// 状态同步逻辑,防止断开连接后仍判定为已连接
if (realConnectionState != isConnected) {
isConnected = realConnectionState;
if (isConnected) {
digitalWrite(LED_BUILTIN, HIGH);
Serial.println("[BLE] Connected");
} else {
noteOn = false;
digitalWrite(LED_BUILTIN, LOW);
Serial.println("[BLE] Disconnected");
}
}
}
if (isConnected) {
// 每隔 1000 毫秒交替发送 NoteOn 和 NoteOff
if (now - lastNoteTime >= 1000) {
lastNoteTime = now;
if (!noteOn) {
MIDI.sendNoteOn(60, 100, 1); // 发送 C4 音符,力度 100,通道 1
noteOn = true;
Serial.println("NoteOn");
} else {
MIDI.sendNoteOff(60, 0, 1); // 发送 C4 音符关闭信号,通道 1
noteOn = false;
Serial.println("NoteOff");
}
}
}
delay(1); // 主动让出CPU使用权让FreeRTOS内核和蓝牙协议栈更平稳地运行
}