Reputation: 61
I am trying to build an Android app that interfaces with the ESP32 using BLE. I am using the RxBluetoothKotlin library from Vincent Masselis for the Android side. For the ESP32 side, I am using the default Kolban libraries that are included in the Arduino IDE. My phone is a OnePlus 5T and my ESP32 is a MH ET Live ESP32DevKIT. My Android app can be found here, and my ESP32 program here.
The whole system works pretty much perfectly for me in terms of pure functionality. That is to say, every button does what it's supposed to do, and I get the exact behaviour I had expected to get. However, the communication itself is very slow. Around 200 bytes/second. My test button in the Android app requests a bunch of text data from the ESP32, and displays this in a dialog. It also lists a number which represents the time between request and reception in milliseconds. Using this, I get around 2 seconds for 440 bytes of data. When I send less data, the time decreases approximately linearly with data size. 40 bytes of data will take around 200ms, and 20 bytes or under typically takes less than 100ms.
This seems rather slow to me. From what I understand, I should be able to at least get a few kilobytes per second. I have tried to check the speed using nRF Connect, but I get the same 2 seconds timespan for my data transfer. This suggests that the problem is not in my app, since I also have it with a completely different app. I also put the code in my main loop inside of callbacks instead (which I probably should have done in the first place), but this didn't change things at all. I have tried taking the microcontroller and my phone to a few different locations, hoping to eliminate interference. I have tried to mess with BLEDevice::setPower and BLEDevice::setMTU, as well as setting RxBluetoothGatt.requestMtu(500) on the Android side. Everything so far seems to have had little to no effect. The only thing that did anything, was adding the line "pServer->updatePeerMTU(0,500);" in my loop during the connection phase. This caused the first 23 bytes of data to be repeated whenever I pressed the test button in my app, and made the data transfer take about 3 seconds. If I'm lucky, I can get maybe a bit under 1.8 seconds for 440 bytes, but this is a very small change when I'm expecting an order of magnitude of difference, and might even be down to pure chance rather than anything I did.
Does anyone have an idea of how to increase my transfer speed?
Upvotes: 2
Views: 7271
Reputation: 71
I experienced the same problem as you and was happy to find your comment:
I have messed around with partition schemes in my IDE, uploaded the code to my ESP32, then messed around some more with a larger MTU and higher priority, and now it seems I'm getting about 10kByte/s.
So after messing around with all this settings I found working solution for me (16 kB/s).
Here is my summary, sorted by priority:
gatt.requestMtu()
after discovering services) and not from the server side (ESP: BLEDevice::setMTU();
)gatt.requestConnectionPriority(BluetoothGatt.CONNECTION_PRIORITY_HIGH)
BLECharacteristic::PROPERTY_READ
is enough for me.esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_DEFAULT,ESP_PWR_LVL_P9);
had no effect for meResults - changing priority:
| Speed [B/s] | Priority | MTU | Payload |
|-------------|------------|-----|---------|
| 190 | DCK | 500 | 495 |
| 1035 | LOW_POWER | 500 | 495 |
| 5522 | BALANCED | 500 | 495 |
| 16566 | HIGH | 500 | 495 |
Results - changing MTU:
| Speed [B/s] | Priority | MTU | Payload |
|-------------|------------|-----|---------|
| 571 | HIGH | 23 | 495 |
| 1183 | HIGH | 46 | 495 |
| 4141 | HIGH | 230 | 495 |
| 5522 | HIGH | 460 | 495 |
| 16566 | HIGH | 500 | 495 |
Results - changing payload size:
| Speed [B/s] | Priority | MTU | Payload |
|-------------|------------|-----|---------|
| 100 | HIGH | 500 | 1 |
| 400 | HIGH | 500 | 10 |
| 3400 | HIGH | 500 | 100 |
| 16566 | HIGH | 500 | 495 |
| 5533 | HIGH | 500 | 496 | (!)
When I had all flags BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY | BLECharacteristic::PROPERTY_INDICATE
I was able to send "only" 455 bytes at 15233 B/s.
I know this response is a bit late, but somebody may still find it helpful:)
Upvotes: 3
Reputation: 1648
The data transmission speed is mainly influenced by the Bluetooth LE connection interval (between 7.5 ms and 4 seconds) and is negotiated between the master (central unit) and the peripheral device. The master establishes a connection with a parameter set and the peripheral can propose to change this parameter set. In the end, however, the central unit decides which parameter set is to be used.
But the Bluetooth connection interval cannot be changed by an Android applications directly, which normally act as the central role. Instead it can request a connection priority which is known to have an influence on the connection interval.
Upvotes: 2