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

Ios 如何在Arduino NANO 33 BLE(nRF52)和iPad之间保持活动MIDI BLE连接,ios,arduino,bluetooth-lowenergy,midi,nrf52,Ios,Arduino,Bluetooth Lowenergy,Midi,Nrf52,我正在使用Arduino Nano 33 BLE设备为iPad实现一个BLE MIDI控制器。以下代码能够: 使设备作为可调式MIDI外围设备可被发现 建立与可编解码MIDI中央应用程序的连接 只有Android应用程序的连接才是稳定的每个iOS应用程序(如Garageband、AUM等)立即关闭连接(arduino板上的led在几秒钟内打开和关闭),但如果设备不断发送MIDI消息(查看loop()函数中注释的代码行),连接将永远保持活动状态;不幸的是,重复发送消息并不是我想要实现的控制器的

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

  • 使设备作为可调式MIDI外围设备可被发现
  • 建立与可编解码MIDI中央应用程序的连接
只有Android应用程序的连接才是稳定的每个iOS应用程序(如Garageband、AUM等)立即关闭连接(arduino板上的led在几秒钟内打开和关闭),但如果设备不断发送MIDI消息(查看loop()函数中注释的代码行),连接将永远保持活动状态;不幸的是,重复发送消息并不是我想要实现的控制器的目的

可能需要执行BLE服务的特定配置或轮询操作,以符合严格的iOS标准,但我找不到任何适用于Nano 33 BLE设备的工作解决方案或示例,该设备不包括在loop()函数中发送注释

#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));
}
#包括
字节midiData[]={0x80,0x80,0x00,0x00};
//设置MIDI服务和MIDI消息特征:
BLEService midiService(“03B80E5A-EDE8-4B33-A751-6CE34EC4C700”);
Bleer特性(“7772E5DB-3868-4112-A1A9-F2669D106BF3”,
BLEWrite | blewritewithotresponse|
BlNotify | BLERead,sizeof(midiData));
bool midi_connected=false;
无效设置(){
//初始化串行通信
Serial.begin(9600);
//初始化内置LED:
引脚模式(LED内置,输出);
//初始化可恢复服务:
如果(!BLE.begin()){
Serial.println(“启动BLE失败!”);
虽然(正确);
}
BLE.setLocalName(“MBLE”);
BLE.setAdvertisedService(midiService);
setEventHandler(BLEConnected、onConnected);
setEventHandler(BLEDisconnected、onDisconnected);
setEventHandler(BLESWRITED、ONWRITED);
midiService.addCharacteristic(midischaracteristic);
table.addService(midiService);
可设置可连接(true);
table.setAdvertisingInterval(32);
table.setConnectionInterval(32,64);
BLE.adversed();
}
void循环(){
BLEDevice central=BLE.central();
国际单项体育联合会(中央){
//MIDI命令(0x90、60、127);
//延迟(250);
//MIDI命令(0x80,60,0);
//延迟(250);
}
}
未连接的空隙(设备中心){
数码写入(LED内置,高);
midi_connected=true;
}
无效连接断开(设备中心){
数码写入(LED内置,低电平);
midi_connected=假;
}
写入时无效(BLEDevice central、BLECharacteristic){
自动缓冲区=特征值();
自动长度=特征值。valueLength();
如果(长度>0)
{
//在下一个midi通道上回音
MIDI命令(缓冲区[2]、缓冲区[3]、缓冲区[4]);
}
}
void命令(字节cmd、字节data1、字节data2){
middata[2]=cmd;
middata[3]=data1;
middata[4]=data2;
setValue(middata,sizeof(middata));
}
我(最终)通过查看苹果提供的MIDI-BLE规范,找到了一个解决方案

附件应要求15 ms或更短的连接间隔。苹果建议从一个请求开始 连接间隔为11.25毫秒,如果苹果拒绝连接请求,则连接间隔将变为15毫秒 产品。 大于15毫秒的间隔不适合实时播放

后来

支持蓝牙低能量MIDI的Apple设备将在与附件建立连接后尝试读取MIDI I/O特性。 […]附件应使用无有效载荷的数据包响应读取的初始MIDI I/O特性

因此,我在setup()函数中更改了连接间隔

并在连接事件处理程序函数中包含了几行

void onConnected(BLEDevice central) {
  digitalWrite(LED_BUILTIN, HIGH);
  midi_connected = true;
  midiCharacteristic.setValue(0);
}
就这样

void onConnected(BLEDevice central) {
  digitalWrite(LED_BUILTIN, HIGH);
  midi_connected = true;
  midiCharacteristic.setValue(0);
}