ios - 如何在 Arduino NANO 33 BLE (nRF52) 和 iPad 之间保持活动的 MIDI BLE 连接
问题描述
我正在使用 Arduino Nano 33 BLE 设备实现适用于 iPad 的 BLE MIDI 控制器。以下代码能够:
- 使设备可作为 BLE MIDI 外围设备被发现
- 与 BLE MIDI 中央应用程序建立连接
仅与 Android 应用程序的连接是稳定的。每个 iOS 应用程序(例如 Garageband、AUM 等)都会立即关闭连接(arduino 板上的指示灯会在几秒钟内打开和关闭),但如果设备不断发送 MIDI 消息(请查看注释中的代码行)loop()函数)连接永远保持活动状态;不幸的是,重复发送消息不是我想要实现的控制器的目的。
BLE 服务的特定配置或要实施的轮询操作可能符合严格的 iOS 标准,但我找不到任何适用于Nano 33 BLE设备的有效解决方案或示例,其中不包括在循环中发送注释()功能。
#include <ArduinoBLE.h>
byte midiData[] = {0x80, 0x80, 0x00, 0x00, 0x00};
// set up the MIDI service and MIDI message characteristic:
BLEService midiService("03B80E5A-EDE8-4B33-A751-6CE34EC4C700");
BLECharacteristic midiCharacteristic("7772E5DB-3868-4112-A1A9-F2669D106BF3",
BLEWrite | BLEWriteWithoutResponse |
BLENotify | BLERead, sizeof(midiData));
bool midi_connected = false;
void setup() {
// initialize serial communication
Serial.begin(9600);
// initialize built in LED:
pinMode(LED_BUILTIN, OUTPUT);
// Initialize BLE service:
if (!BLE.begin()) {
Serial.println("starting BLE failed!");
while (true);
}
BLE.setLocalName("MBLE");
BLE.setAdvertisedService(midiService);
BLE.setEventHandler(BLEConnected, onConnected);
BLE.setEventHandler(BLEDisconnected, onDisconnected);
midiCharacteristic.setEventHandler(BLEWritten, onWritten);
midiService.addCharacteristic(midiCharacteristic);
BLE.addService(midiService);
BLE.setConnectable(true);
BLE.setAdvertisingInterval(32);
BLE.setConnectionInterval(32, 64);
BLE.advertise();
}
void loop() {
BLEDevice central = BLE.central();
if (central) {
// midiCommand(0x90, 60, 127);
// delay(250);
// midiCommand(0x80, 60, 0);
// delay(250);
}
}
void onConnected(BLEDevice central) {
digitalWrite(LED_BUILTIN, HIGH);
midi_connected = true;
}
void onDisconnected(BLEDevice central) {
digitalWrite(LED_BUILTIN, LOW);
midi_connected = false;
}
void onWritten(BLEDevice central, BLECharacteristic characteristic) {
auto buffer = characteristic.value();
auto length = characteristic.valueLength();
if (length > 0)
{
// echo on the next midi channel
midiCommand(buffer[2], buffer[3], buffer[4]);
}
}
void midiCommand(byte cmd, byte data1, byte data2) {
midiData[2] = cmd;
midiData[3] = data1;
midiData[4] = data2;
midiCharacteristic.setValue(midiData, sizeof(midiData));
}
解决方案
我(最终)通过查看Apple 提供的MIDI BLE 规范找到了一个解决方案,上面写着
附件应请求 15 ms 或更短的连接间隔。Apple 建议从 11.25 毫秒的连接间隔请求开始,如果连接请求被 Apple 产品拒绝,则转到 15 毫秒。高于 15 毫秒的间隔不适合现场回放情况。
然后
支持蓝牙低功耗 MIDI 的 Apple 设备将在与配件建立连接后尝试读取 MIDI I/O 特征。[...] 附件应使用没有有效负载的数据包响应读取的初始 MIDI I/O 特征。
所以我在setup()函数中更改了连接间隔
BLE.setConnectionInterval(9, 12);
并在连接事件处理函数中包含几行
void onConnected(BLEDevice central) {
digitalWrite(LED_BUILTIN, HIGH);
midi_connected = true;
midiCharacteristic.setValue(0);
}
就是这样!
推荐阅读
- c# - 在函数应用程序中分配作业时如何启用/禁用时间触发器
- barbajs - Barba JS页面过渡未显示
- angular - 目标入口点“@angular/material/slider”缺少依赖项:
- android - android 解析图片的URI
- firebase - 当我在颤振中使用firebase动态链接时,它会打开应用程序,但在应用程序被杀死时无法获取链接
- javascript - Jquery在按Enter键时获取textarea值
- python - 如何按比例调整图像大小 Tensorflow 图像
- android-studio - 将 Android Studio JDK 更新到 Java 9
- flutter - 按钮由于彼此靠近而重叠现在我无法点击 Flutter 下方的按钮
- javascript - Why this expression is var a = 3, b = a = typeof b; giving undefined?