I’ve been using the Adafruit LE friend to do some data transfer tests. With the basic setup, I was sending 1 kB of data in about 9.5 to 10 seconds. That is horribly slow! About 100 bytes per second.
I did some research and found a couple of good links. This link about BLE discusses using the Nordic nRF chip and mbed to send data to a peripheral (i.e.: from the computer to the device). This link about sending data from the peripheral has some good tips when going in the other direction.
I gave up trying to get the Adafruit LE friend to be fast and started working with the RedBearLab BLE nano (v1.5). It has been tough getting Xcode setup to compile code right, and I ended up using “embedXcode” as a starting point, and the Arduino plugin for RedBearLab. I’d rather just use mbed, but the web experience is terrible, and I must use Xcode. However, I couldn’t get their scripts to compile..mainly do to case sensitivity issues (BLE.h and ble.h both exist, and my drive partition is insensitive).
For the Nano, the bottom line was I had to edit the projectconfig.h file and use these settings:
#define CFG_GAP_CONNECTION_MIN_INTERVAL_MS 20// corbin!! fYI, 40 worked. 50 /**< Minimum acceptable connection interval */
#define CFG_GAP_CONNECTION_MAX_INTERVAL_MS 40// corbin!! 500 /**< Maximum acceptable connection interval */
#define CFG_GAP_CONNECTION_SUPERVISION_TIMEOUT_MS 500// corbin!! 4000 /**< Connection supervisory timeout */
The key part was not just the min interval, but the max; 500 was too large, and there is no API to control it (I can add some in for myself). 40 is required. I didn’t test lower…but lower might be better too. Too low, and the Mac (or iOS device) might not be able to keep up.
When sending from an OS X app, I discovered I could get the most data by doing a “write without response”:
peripheral.writeValue(subData, forCharacteristic: _uartTransmitCharacteristic!, type: CBCharacteristicWriteType.WithoutResponse)
And batching the 20 byte data chunks every 2 nano seconds:
let delay: Int64 = Int64(NSEC_PER_MSEC)*2// At about 4ns, it starts to get slower on the recieving end.
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, delay), dispatch_get_main_queue(), { () -> Voidin
self.sendMoreData();
})
Anything longer and it would be slower. This doesn’t make sense…as the BLE stack can’t really be faster than 7.5ms, but I’m sure the computer is doing a bit of processing and handling the BLE stack separately from my process. I have yet to test the code on iOS…it might need a larger delay, and might be slower. That is fine… my goal is to send files from the desktop to the device, and potentially vice-versa.
With my above changes, a raw read of 1024 bytes (1kB) took 185ms; and it was fairly consistent. That’s about 5.4kB per second! I could probably improve it 6x more by using multiple characteristics to write at simultaneously, but I’ll test that later. 5.4kB/second is fast enough to start with.
I was curious if the Adafruit Bluefruit LE friend could be made faster. I know the GAP interval can be changed, so I made it match with:
m_ble.sendCommandCheckOK(“AT+GAPINTERVALS=20,40,25,30”);
I know this post is nearly 7 years old, but you might have just solved my weekslong headache. Thanks for the informative summary!