Corbin's Treehouse - Corbin Dunn, Santa Cruz, CA
Plug Bug
Treehouse
Photography
Videos
Projects
Unicycling
About

Tricks for fast Bluetooth LE data transfers


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”);

 
Indeed, this did help! the UART service can read 1024 bytes in 3.5 seconds, instead of 10 seconds, or about 0.3kB/second versus 0.1kB/second.  This is reading the data from a teensy, which means the Adafruit BLE friend first reads the data, and then transfers it to the teensy over SPI. That protocol is somewhat slow, and it has a 16 byte payload (it really needs to be 20 bytes to transfer complete packets from the BLE). 
 
Of course…my test is ignoring the SPI transfer from the nRF chip to the teensy chip. This is also going to take some time, and might slow my numbers down a bit. I also need to learn how to write SPI code and make my own mechanism for transferring data. Lots more coding to do…



(c) 2008-2017 Corbin Dunn

Corbin's Treehouse is powered by WordPress. Made on a Mac.

Subscribe to RSS feeds for entries and comments.

35 queries. 0.402 seconds.