繁体   English   中英

如何在 Arduino NANO 33 BLE (nRF52) 和 iPad 之间保持活动的 MIDI BLE 连接

[英]How to keep an active MIDI BLE connection between an Arduino NANO 33 BLE (nRF52) and an iPad

我正在使用 Arduino Nano 33 BLE 设备为 iPad 实现 BLE MIDI 控制器。 以下代码能够:

  • 使设备可被发现为 BLE MIDI 外设
  • 与 BLE MIDI 中央应用程序建立连接

连接稳定仅与 Android 应用程序。 每个 iOS 应用程序(例如 Garageband、AUM 等)立即关闭连接(arduino 板上的 LED 在几秒钟内打开和关闭),但如果设备不断发送 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 毫秒或更短的连接间隔。 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);
}

就是这样!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM