sandeepmistry / arduino-BLEPeripheral

An Arduino library for creating custom BLE peripherals with Nordic Semiconductor's nRF8001 or nR51822.
MIT License
463 stars 180 forks source link

How to send more than 2 packets per cycle? #261

Open neroroxxx opened 5 years ago

neroroxxx commented 5 years ago

Hi all, I'm working on a MIDI BLE device using the Adafruit Bluefruit LE - nRF8001 Breakout (https://www.adafruit.com/product/1697) and a Teensy 3.2

I have code written to connect and send/receive MIDI data and works like a charm, however I only have 1 issue, I can only send 2 packets per cycle then i have to wait between 20 to 30 milliseconds to send more packets, the time i have to wait is always different but i've noticed that if i wait at least 30ms to send the other 2 packets it works fine.

I read that iOS allows more than 2 packets, but i'm wondering if this is a limitation of the chip or i have to do something different to send more than 2 packets at a time...

The sketch below is tested with the nRF8001 and has a maximum of 20 bytes per packet, it will try to send 4 packets every 2 seconds once it's connected to a central.

For a central i'm using midimttr from the App Store to connect, then you can see on the Serial monitor which packets were sent and which were not.

I followed the examples here https://learn.sparkfun.com/tutorials/midi-ble-tutorial/all

Any advice would be much appreciated.

#include <SPI.h>
#include <BLEPeripheral.h>

// used to check if enough time has passed
unsigned long txTime = 0;

BLEPeripheral ble;
BLEService service("03B80E5A-EDE8-4B33-A751-6CE34EC4C700");
BLECharacteristic characteristic("7772E5DB-3868-4112-A1A9-F2669D106BF3", BLERead | BLEWrite | BLEWriteWithoutResponse | BLENotify, 20);
BLEDescriptor descriptor("2902", 0);

void setup() {
  Serial.begin(115200);
  delay(1000);
  Serial.println("Start");
  // setup ble
  ble.setLocalName("BLE MIDI");
  ble.setDeviceName("BLE MIDI");
  ble.setAdvertisedServiceUuid(service.uuid());
  ble.addAttribute(service);
  ble.addAttribute(characteristic);
  ble.addAttribute(descriptor);
  characteristic.setValue(0);
  ble.begin();
}

void loop(){
  BLECentral central = ble.central();
  if(central) {
    if(central.connected()){
      sendPackets();
    }
  }
}

void sendPackets(){
  // send 4 packets every 2 seconds
  // 4 system exclusive arrays with 15 bytes between 0xF0 and 0xF7
  if(millis() >= (txTime+2000)){
    uint8_t packet[20];
    for(uint8_t i=0;i<4;i++){
      memset(packet,i,20);
      uint16_t currentTimeStamp = millis() & 0x01FFF;
      packet[0] = ((currentTimeStamp >> 7) & 0x3F) | 0x80; // midi header
      packet[1] = (currentTimeStamp & 0x7F) | 0x80; // midi low time stamp always sent before a status byte (in this case 0xF0)
      packet[2] = 0xF0;
      // all the bytes in the array are "i" except for the timestamps and status bytes
      packet[18] = (currentTimeStamp & 0x7F) | 0x80; // midi low time stamp always sent before a status byte (in this case 0xF7)
      packet[19] = 0xF7;

      if(!characteristic.setValue(packet,20)){
        Serial.println("");
        Serial.println("!!!!!!!!!!!!!!");
        Serial.print("Packet ");
        Serial.print(i);
        Serial.println(" was NOT sent :-(");
        Serial.println("!!!!!!!!!!!!!!");
        Serial.println("");
        break;
      } else {
        Serial.print("Packet ");
        Serial.print(i);
        Serial.println(" sent :-)");
      }
    }
    txTime = millis();
  }
}
zeroby0 commented 5 years ago

Try setting the connection interval to a lower value. Android has a minimum value of 7.5 ms and iOS 20 ms.

https://github.com/sandeepmistry/arduino-BLEPeripheral/blob/master/API.md#set-connection-interval