burst notifications with Bluetooth Low Energy on Android - android

I'm developing a Bluetooth low energy application to connect with a device which will be sending 20 byte long transmissions in notification mode in intervals of 6 milliseconds or more.
So far the application is working fine. It can scan, discover and then subscribe to the characteristic to receive data notifications. The issue is that for the first 2-4 seconds the data will be read nicely in a sequential order but after that the notification data starts to appear in bursts or as in chunks of data but not in consistent intervals between each transmission.
This doesn't happen when i check the data transmission with the Texas Instruments BLE evaluation kit, there my reader shows a perfect transfer with not bursts appearing. Only on android it's become visible.
Could this be an issue that can be configured to fix in android side?
Could this be a problem with the high transmission rate (~milliseconds intervals)?
Thank you..
So it sums up to that optimal throughput can be achieved with the proper configuration of connection parameters for the BLE connection. It is usually done at the peripherals end and may have to differ for the platform connecting to (i.e. IOS , Android may have different connection requirements..)
P.S. : Since i was looking at android found this method documented here https://developer.android.com/reference/android/bluetooth/BluetoothGatt.html#requestConnectionPriority(int) which is calling for a connection priority( CONNECTION_PRIORITY_BALANCED, CONNECTION_PRIORITY_HIGH or CONNECTION_PRIORITY_LOW_POWER) But I didn't test it.

You could try to enable Bluetooth HCI Snoop Log in Developer Options and then view the log file in WireShark. Look for connection update commands, these can be issued by either side of communication. This command change the transmission settings and slow down the transfer. Also look for GAPROLE_PARAM_UPDATE_ENABLE in your TI BLE app.

Yes Michael we use CC2650 and for our requirement BLE is sufficient bur I'm not sure if it really supports bluetooth classic (http://www.ti.com/product/CC2650/description) .
You can try playing around the BLE connection parameters to get the setup tuned, that's what we did other than trying to build the app giving priority to BLE operations.Take a look at this for more information on connection parameters.
https://devzone.nordicsemi.com/question/60/what-is-connection-parameters/
You can't configure the connection parameters on the phone but the peripheral(i.e. SensorTag) even so there's not guarantee that the given parameters will actually be accepted by the central device in case will settle with a set of parameters accepted by the central device. (Android and IOS have different policies in terms of these..)
In our case we are transmitting in intervals of 15ms and seems quite stable. But all these high frequent transfers at the cost of the low power consumption capabilities of BLE which is really what it is intended for. We could go even below that close to 7.5ms which is the minimum connection interval supported by Android. Our initial tests were stable but reliability of such a low latency is questionable.

Related

Setting BLE connection parameters in movesense application

I am wondering if there is a way to set the BLE connection parameters in my custom firmware and also for the logbook service. As I would like to transfer data as fast as possible from the device to a mobile application.
From what I can see in the BLE spec, and from reading documentation the Connection interval, the number of packets per interval and the "data length extension" can be set to increase the transfer rate. But these cannot be set from the either the Android Device nor the iOS device. And the recommendation is to set it from the peripheral device
And from what I have read in the Movesense documentation I could not find any way of setting the preferred settings from trough the Movsense API.
Update: The BLE parameter customization is coming out in version 2.2
Original answer:
For now there is no way of setting the BLE connection parameters from the Movesense device. The default settings (connection interval 7.5ms-1000ms, MTU 158, DLE enabled) allow the phone to choose the best performing settings. I've typically seen connection interval of 45ms when connecting with Android phone that supports large MTU & DLE (BLE 4.2) which provides the maximum transfer rate possible (around 10-12kB/s).
We have planned to add a way to give more control to the BLE parameters as well as to optimize the power consumption in typical use cases (when this would be available for developers is not yet clear).
Full disclosure: I work for Movesense team

Android ble, requestConnectionPriority not working

I am trying to send 10 bytes of data, every 30milisecond,s between 2 android devices using bluetooth low enegry notifications. The goal is to achieve low latency communication and there is no interest in low energy.
You can check the results in the Delay graph(Y field = delta time between packets). The first 10seconds the communication is being perfomed good enough. (The interval between the packets is max 30-40ms). However after the 10th second, the intervals are either extremly high or extremely low.
This is probably happenning due to non strict connection interval parameters. You can check a sample of hci_events that shows clearly the slow down is caused by the hci_events.
I have tried to configure the parameters of the connection, calling from the master the function
requestConnectionPriority
However, it didn't change anything on the result graph. I also check the packets using wireshark and findout that the master didn't even send a request for configuring the connection interval. I also tried another configuration request with
requestMtu
with exactly the same results, no update packets was send from the master.
So, there are 2 questions that show up from this observations.
Has ble a timeout in the 10th second in order to ensure low energy consumption? If so, how can I disable it?
Is some thing wrong calling requestConnectionPriority, from the android 6.0.1 with the role of the central(master)? Can you give me a simple example on how is being called properly?
Note that requestConnectionPriority is called right after the connection being establish in the onConnectionStateChange of the BluetoothGattCallback.
The device that has role of a slave(server) is running (Android 5.1.1) and the master(client) is running (Android 6.0.1).
Thanks a lot!
IMPORTANT UPDATE: It's crucial to mention the way the connection is being initiated between the devices.
The central device calls device.connectGatt, where device is BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address). Address is a hardcoded string, the peripheral's public mac address. You can check logcat logs and also hci logs.
I have also tried connecting with the legit method (peripheral advertising and connect to scanned random address), but I get an error 'initiate direct connection fail, topology limitation'. You can check logcat logs and also hci logs.
Has ble a timeout in the 10th second in order to ensure low energy consumption? If so, how can I disable it?
No
Is some thing wrong calling requestConnectionPriority, from the android 6.0.1 with the role of the central(master)? Can you give me a simple example on how is being called properly?
I'm not aware of any bugs regarding requestConnectionPriority. But you could try to execute that method after the onServicesDiscovered callback. Android temporarily changes connection interval to 7.5 ms during the GATT service discovery so it might be confused if you don't wait until the service discovery is completed.
Regarding requestMtu, make sure you execute that method while there are no other GATT operations pending (otherwise it won't work).
One additional tip is to use an air sniffer and not only look at the hci logs.

Is there a way to communicate reliably via Bluetooth?

I have to exchange data between two bluetooth devices, one of them will be an Android device. For simplicity's sake you can assume the other device will be a generic linux device running bluez producing data similar to the data a fitness tracker would produce.
The scenario seems a straightforward use case for Bluetooth Low Energy. The problem i am currently running into comes from the fact that communication has to be reliable (reliable in the way TCP is reliable). This means:
no losses
no corruption of data
order needs to be preserved
no duplicates
no phantom packets
While losses are prevented at link layer level, the order for instance seems not to be explicitly preserved when working with Low Energy (using indications would probably achieve this).
Not having done a lot of work with Bluetooth I am currently overwhelmed quite a bit with the amount of options while at the same time no option seems to fit the bill nicely.
Is there a "best-practice" for setting up reliable communication between two bluetooth devices? A Bluetooth Low Energy solution would be preferable, but is not mandatory.
Once your Bluetooth connection is setup its reliable. So you don't have to be worried about data loss or corruption.
So the things you're worried about can be easily handled in your side. You'll get proper connection and disconnection callback while setting up a BroadcastReceiver for your BluetoothAdapter.
In case of any disconnection you may have to restart the procedure for connection again and once its established properly you may resend the data.
I don't know about your purpose yet, but one thing I need to mention here is, I would not recommend Bluetooth communication if you're holding the connection for long time. Some devices disconnects the connection automatically after some time if there's no continuos transmission.
Android has Bluetooth support, but it only allow to send ot receive data from stream. There is a very good sample project from Google: https://github.com/googlesamples/android-BluetoothChat . The only drawback of this sample is that it use Handler to nitify about Bluetooth events. I changed it a bit so it use another Thread and from it calls methods of interface you set, take a look at project: https://github.com/AlexShutov/LEDLights . This is ordinary Bluetooth, not BLE, hope it will help
Android's BLE stack is as good as the link layer specification. So you can use "write without response" in one direction and notifications for the other direction. Just make sure your peripheral side does not drop incoming writes.
BLE uses 24-bit CRC. for the amount of data transmitted using BLE the CRC is quite robust and the possibility of corruption is very low ( note that TCP CRC is 16bit and the Ethernet CRC is 32bit, please see http://www.evanjones.ca/tcp-and-ethernet-checksums-fail.html).
The ordering issues in wired network is a result of routing packets through different routes to the same destination ( plese see If TCP is connection oriented why do packets follow different paths?) . This is partially due to the use of sliding window acknowledgement protocol, which allows a number of packets to be transmitted before being acknowledged.In BLE there is no routing and the acknowledgement scheme is a variation of stop and wait ARQ scheme(2-bit lazy acknowledgement), this means that it is not possible to send a new packet without being acknowledged. These two factors makes the possibility of having an out of order transmission highly unlikely.

BLE: Why are Write Commands slower than Notifications?

In the context of BLE (Bluetooth Low Energy), Write Commands can be used to write from a Client to the Server, and Notifications to write from the Server to the Client. In my setup, the Client is a Central device (Android phone), and the Server is a Peripheral (dev board).
After performing several data throughput tests with multiple phones, I noticed that the throughput varies greatly with the phone, which is expected because a great deal of the BLE lower layers implementation is up to the manufacturer to figure out. But what caught my attention was that Write Command always achieve a much lower throughput that Notifications, independently from the phone. Why is that?
They should have the same throughput. Multiple write commands and notifications can be sent during one connection event. They are treated the same.
You could use an air sniffer to see if you find any problems.
How long the connection event should be open can be suggested when the connection is created and with connection parameter updates. Sadly, Android's BLE stack hard codes this to the default value, which means no recommendation. That will in practice mean you are limited to 3 or 4 packets per connection event.

Android Bluetooth Low Energy sequential Write perfomance

I do have a Bluetooth LE remote controlled car. Therefore i need to write periodically to a drive characteristic on the car. My microcontroller (AtmelXMega128A1 # 32Mhz + nRF8001) should be able to handle up to 122 connections per second # 7,5ms connection interval.
My Android App is based on cordova and a bluetooth low energy plugin: https://github.com/randdusing/BluetoothLE
I am running this on a Nexus 5 with Android v4.4.4.
I have a timer which sends values for steering and acceleration to the car each 175ms. I would like to send each 50ms but that does not work. I cannot tell where the problem is but i guess it is the android implementation of GATT (I get the pending command error at some level).
If i write more than it can handle the car executes all commands in a row but time shifted. Some queue hickup obviously and this is not the Microcontroller as it operates much faster.
I am doing a timing change which seems to be successful. I tried turning WiFi off as i hoped it would help but nothing changed.
Is there any experience on periodical writings to a GATT characteristics on Android? Examples would be great.
First of all you should make a robust design. Data should be driven by callback from the Android BT Stack telling when it's ready to accept more data (when the previous transmission is done). Do not use a timer. There will always happen need for retransmissions on the lower stack level so you cannot rely on an exact transfer interval and throughput.
The 7.5ms is the shortest possible connection interval however the default is usually much slower (48.75ms on my Nexus 5 with Android L) So from your peripheral you should try to request a faster connection interval once connected. This will speed up your throughput and responsiveness.
Some Android BT stacks refuse if you try to force a very fast connection interval. You should be handling that intelligently. Like trying with 7.5ms (parameter = 6) and increase it if it failed. iOS design guideline say you must not use a lower value than 20 (*1.25ms) and the upper request value should be at least 20 higher than the lower. You will get a faster connection parameter though if you request values min=10, max=20 and end around 18ms or something.
For android it seems most will accept the 7.5ms (value 6) but again you should not force it because the stack might cancel the connection then.
I made experiments on Android L, requesting connection intervals from the peripheral side when connected. Android rounded off requests so only every 3rd step gave a difference.
6=7.5ms, 9=11.25ms, 12=15.0ms, ..., 39=48.75ms which seems to be the default value on Nexus 5 running Android L.
Bluetooth is a shared resource in the broadcom chipset most are using on the smartphone side. Wifi, BT Classic, BT Low Enegy and sometimes GPS shares bandwidth. You will see hiccups and must be tolerant about them. Make a robust design.
Something else you can try is to renegotiate MTU-SIZE if you need larger data packages than the default. This is by specification an optional BLE feature however Apple broke it completely in iOS7 where they use it as a mandatory thing to boost up throughput. This broke all BLE devices which didn't implement the response handler and so it crashed and could never be used with iOS devices until a SW update was made. Baaaaaad. For android this is not a problem though.

Categories

Resources