Android BLE Write Timeout on ESP32

ss3dev
Posts: 4
Joined: Fri Apr 03, 2020 12:38 pm

Android BLE Write Timeout on ESP32

Postby ss3dev » Fri Apr 03, 2020 1:00 pm

Hello,

I am experiencing an issue with writing to a BLE characteristic from Android. I have an ESP-WROOM-32 dev board and am using esp-idf version 3.1. After negotiating an MTU higher than the default value a write operation with more than 20 bytes fails. From the Android client side the write succeeds, however from the esp32 side there is no event received. Instead a disconnect event occurs with reason code 0x13: Timeout. This only effects specific Android models. Pixel 3, and Pixel 4 both work as expected. Samsung s9 and Samsung s10 running Android 10 fail as described. Its worth noting that writes of 18 bytes or fewer will succeed (this is the default MTU minus some overhead). Also, IOS is able to negotiate an MTU and write larger packets without issue.

The gatt server demo included with esp-idf can be used to reproduce the issue. I have so far made two modifications.

When starting bluetooth I call a method to change the local mtu which allows the client (Android Phone) to negotiate a higher mtu.

Code: Select all

esp_ble_gatt_set_local_mtu(500);
When a client connects I also update the connection parameters. This was an attempt to increase the timeout value. This is run inside the ESP_GATTS_CONNECT_EVT event.

Code: Select all


esp_ble_conn_update_params_t conn_params = {0};
memcpy(conn_params.bda, param->connect.remote_bda, sizeof(esp_bd_addr_t));
conn_params.latency = 0;
conn_params.max_int = 0x20;    // max_int = 0x20*1.25ms = 40ms
conn_params.min_int = 0x10;    // min_int = 0x10*1.25ms = 20ms
conn_params.timeout = 400;    // timeout = 400*10ms = 4000ms
esp_ble_gap_update_conn_params(&conn_params);

Here is a related, unresolved forum thread from someone else experiencing a similar issue. https://forum.developer.samsung.com/t/s ... ession/509

I will try updating to esp-idf v4 to see if that resolves the issue. I'm wondering if anyone else has experienced a similar issue and been able to resolve it.

Edit:

Since originally positing I have updated to esp-idf v4.0. I still experience the same behavior with Samsung devices.

chegewara
Posts: 2207
Joined: Wed Jun 14, 2017 9:00 pm

Re: Android BLE Write Timeout on ESP32

Postby chegewara » Sat Apr 04, 2020 9:12 pm

Disconnect error:

Code: Select all

0x13 Remote User Terminated Connection
I am working with esp v3.3/arduino/AmazonFreeRTOS, esp-idf v4.x and i dont see any problems with it (samsung S9+ with android 10). Maybe there is problem with MTU negotiating. Setting local MTU does not mean its negotiated successfully. Do you have MTU event in app? Can you try nRF connect on android and check logs in it? Remember you have to set MTU in nRF connect manually after connection established.

ss3dev
Posts: 4
Joined: Fri Apr 03, 2020 12:38 pm

Re: Android BLE Write Timeout on ESP32

Postby ss3dev » Mon Apr 06, 2020 3:24 pm

I apologize, I mixed up the error code in the original post, we are seeing code 8: Timeout on writes from Samsung devices.

Below are the full logs from a connection until disconnect using the nordic app on. The client connects, sets the MTU, and then attempts a write containing 50 bytes. Instead the esp32 receives a disconnect event. Our code only allows for one connection at a time, and automatically begins advertising again after a disconnect.

Code: Select all

(395746) bt_provisioning.c: ESP_GATTS_CONNECT_EVT (gatts_if: 3 conn_id: 0).
(404766) bt_provisioning.c: ESP_GATTS_MTU_EVT, MTU set to 500.
(428546) bt_provisioning.c: ESP_GATTS_DISCONNECT_EVT4 (gatts_if: 3 conn_id: 0 reason: 0x08).
(428556) bt_provisioning.c: ESP_GAP_BLE_ADV_START_COMPLETE_EVT.
(428556) bt_provisioning.c: advertising start success.
Is there anything to be configured on the esp32 to better support writes?

chegewara
Posts: 2207
Joined: Wed Jun 14, 2017 9:00 pm

Re: Android BLE Write Timeout on ESP32

Postby chegewara » Tue Apr 07, 2020 2:04 am

Can you confirm in nRF connect logs that MTU has been negotiated and confirmed?
Remember you have to call this before connect (or at least before central asks MTU):

Code: Select all

esp_ble_gatt_set_local_mtu(500);

ss3dev
Posts: 4
Joined: Fri Apr 03, 2020 12:38 pm

Re: Android BLE Write Timeout on ESP32

Postby ss3dev » Tue Apr 07, 2020 2:36 pm

Here are the logs from the nordic app:
Image
https://imgur.com/a/mLppfu5

The logs show the device connecting, connection parameters are updated. Once to an interval of 7.5ms, latency 0 and timeout 5000. I think these are the android defaults. Then parameters re updated again to an Interval of 30ms, latency 0 and timeout 4000. These are parameters coming from the esp32. The MTU is then set to 500. I then attempted to write more than 20 bytes. the logs do not reflect this, instead showing a GATT ERROR (0x85) followed by a GATT CONN TIMEOUT (0x8).

The logs from the esp32 are the same as shown previously.

I will adjust the interval values to see if I can find more stable settings

chegewara
Posts: 2207
Joined: Wed Jun 14, 2017 9:00 pm

Re: Android BLE Write Timeout on ESP32

Postby chegewara » Wed Apr 08, 2020 7:59 am

Ok, it looks like MTU has been negotiated to 500. All is fine.
GATT ERROR (0x85)
This error is nasty, because its unspecific error. Ive got it sporadically few times and never knew why. Also i couldnt find any satisfying info on internet about that error. This explains why its followed by TIMEOUT. After error 0x85 device is disconnected.

My advice is to use debug log level in nRF connect.

ss3dev
Posts: 4
Joined: Fri Apr 03, 2020 12:38 pm

Re: Android BLE Write Timeout on ESP32

Postby ss3dev » Thu Apr 09, 2020 1:07 pm

bumping up the loglevel on the nordic app confirmed that the app is indeed performing the write, immediately afterwards is the error 0x85.

I bought an s9 for testing. We now have an S9, S10, PIxel 3 and an IOS device. for the S9 to work I did have to tweak some parameters. Unfortunately the S10 is still not working, giving the same 0x85 error followed by 0x8 Timeout. I'll share my configuration below. The advertising interval, and min/max interval I found in some reference material. For some reason the S9 could not find the esp32 until i increased the advertising interval to 800 (500ms). Do you mind sharing your configuration?

Code: Select all


static esp_ble_adv_data_t bt_adv_config = {
    .set_scan_rsp = false,
    .include_name = true,
    .include_txpower = true,
    .min_interval = 50, // * 1.25 ms = 62.5 ms
    .max_interval = 200, // * 1.25 ms = 250.0 ms
    .appearance = 0x00,
    .manufacturer_len = 0,
    .p_manufacturer_data = NULL,
    .service_data_len = 0,
    .p_service_data = NULL,
    .service_uuid_len = 0,
    .p_service_uuid = NULL,
    .flag = (ESP_BLE_ADV_FLAG_GEN_DISC | ESP_BLE_ADV_FLAG_BREDR_NOT_SPT),
};
// config scan response data
static esp_ble_adv_data_t bt_scan_rsp_config = {
    .set_scan_rsp = true,
    .include_name = true,
    .include_txpower = true,
    .manufacturer_len = 0,
    .p_manufacturer_data = NULL,
    .service_data_len = 0,
    .p_service_data = NULL,
    .service_uuid_len = 0,
    .p_service_uuid = NULL,
    .flag = (ESP_BLE_ADV_FLAG_GEN_DISC | ESP_BLE_ADV_FLAG_BREDR_NOT_SPT),
};

static esp_ble_adv_params_t bt_adv_params = {
    .adv_int_min        = 800, // * 0.625 = 500.0ms
    .adv_int_max        = 800, // * 0.625 = 500.0ms
    .adv_type           = ADV_TYPE_IND,
    .own_addr_type      = BLE_ADDR_TYPE_PUBLIC,
    //.peer_addr            =
    //.peer_addr_type       =
    .channel_map        = ADV_CHNL_ALL,
    .adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY,
};
Then on the ESP_GATTS_CONNECT_EVT event I update parameters. This may no longer be necessary.

Code: Select all

            {
                esp_ble_conn_update_params_t conn_params = {0};
                memcpy(conn_params.bda, param->connect.remote_bda, sizeof(esp_bd_addr_t));
                conn_params.latency = 0;
                conn_params.min_int = 50;    // min_int = 50*1.25ms = 62.5ms
                conn_params.max_int = 200;    // max_int = 200*1.25ms = 250.0ms
                conn_params.timeout = 400;    // timeout = 400*10ms = 4000ms
                esp_ble_gap_update_conn_params(&conn_params);
            }
Finally this is the initialization of the ble stack, showing the local mtu being set. I stripped out all of the error handling for brevity. I suppose where i set the local mtu could be in the wrong place.

Code: Select all

    esp_bt_controller_init(&bt_cfg);
    esp_bt_controller_enable(ESP_BT_MODE_BLE);
    esp_bluedroid_init();
    esp_bluedroid_enable();
    esp_ble_gatt_set_local_mtu(500);
    esp_ble_gatts_register_callback(gatts_event_handler);
    esp_ble_gap_register_callback(gap_event_handler);
    esp_ble_gatts_app_register(SECURE_PROFILE_APP_IDX);
Just to re-iterate, these settings work for 3 of the 4 devices I have.

Thanks for the help.

chegewara
Posts: 2207
Joined: Wed Jun 14, 2017 9:00 pm

Re: Android BLE Write Timeout on ESP32

Postby chegewara » Sat Apr 11, 2020 8:24 pm

I heard the rumors that some users got issues with samsung S10 and esp32 (maybe other chips too).

I am using advertising interval/window between 20ms and 200-250ms, maybe even longer. In most my projects i am using arduino/arduino like library or amazon freertos and samsung s9+. Like i said, i had few times problems with error 0x85, but it was some time ago and i dont remember how i did fix it.

Who is online

Users browsing this forum: Majestic-12 [Bot] and 97 guests