ESP-32 as BLE client: connection always closes after 40 seconds

Paul-K.
Posts: 5
Joined: Tue Jul 28, 2020 8:31 am

ESP-32 as BLE client: connection always closes after 40 seconds

Postby Paul-K. » Tue Jul 28, 2020 9:14 am

Hi Forum,

I have an issue with using an ESP32 with the Arduino implementation to connect to an EEG Headband from Muse (Modell 2016) via BLE.
I manage to get a connection, transfer a command to start streaming data, and receive data, all fine so far, BUT after always pretty much exactly 40 seconds, the connection is closed and I have no idea for what reason.
I created a simple script with only the bare minimum code to reproduce the issue and added some output for debugging.
I can see that the connection "breaks" off and with the ESP_GATTC_DISCONNECT_EVT event (code 41,"When the BLE physical connection disconnected" according to esp_gattc_api.h inline doc) and the given disconnect reason is "34", which according to esp_gatt_defs.h is referring to ESP_GATT_CONN_LMP_TIMEOUT stated as "Connection fail for LMP response tout" in the inline doc.

Unfortunately, I do not have any idea what that means and if the cause for this is in the ESP32 BLE Stack or if actually the BLE Server (Muse 2016 Headband in this case) closes the connection.
I also tried sending some keep-alive commands to the headset as well (not in example code anymore, since it did not make any difference) but it had no effect on the connection duration. It always closes after 40 seconds.

I basically checked implementations to connect to the headset on other platforms and found e.g. a JS implementation (https://github.com/urish/muse-js) that runs in the browser on my laptop (obviously using the Bluetooth Interface of my Laptop instead of an ESP32), following the same steps in the setup of the BLE connection and sending the same commands, this connection stays stable and does not disconnect, so I am wondering if the cause is to be found in the BLE stack of the ESP32.

My Environment / Versions:
PLATFORM: Espressif 32 1.12.4 > Espressif ESP32 Dev Module
HARDWARE: ESP32 240MHz, 320KB RAM, 4MB Flash
PACKAGES:
- framework-arduinoespressif32 3.10004.200129 (1.0.4)
- tool-esptoolpy 1.20600.0 (2.6.0)
- toolchain-xtensa32 2.50200.80 (5.2.0)
Dependency Graph
|-- <ESP32 BLE Arduino> 1.0.1

Here ist the code I use:
  1. #include <Arduino.h>
  2. #include "BLEDevice.h"
  3.  
  4. unsigned long packageCounter = 0;
  5. unsigned long connectionTime = 0;
  6.  
  7. void dataHandler(BLERemoteCharacteristic *pBLERemoteCharacteristic, uint8_t *pData, size_t length, bool isNotify)
  8. {
  9.     packageCounter++;
  10.     if (packageCounter % 20 == 0)
  11.     {
  12.         Serial.printf("recieved %ld packages so far\n", packageCounter);
  13.     }
  14. }
  15.  
  16. class MyClientCallback : public BLEClientCallbacks
  17. {
  18.     void onConnect(BLEClient *pclient)
  19.     {
  20.         Serial.println("connected to headset");
  21.         connectionTime = millis();
  22.     }
  23.  
  24.     void onDisconnect(BLEClient *pclient)
  25.     {
  26.         Serial.printf("Device disconnected after %ld ms and %ld recieved eeg packages\n", millis() - connectionTime, packageCounter);
  27.     }
  28. };
  29.  
  30. void gattcEventHandler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param)
  31. {
  32.     //ESP_LOGW(LOG_TAG, "custom gattc event handler, event: %d", (uint8_t)event);
  33.     if (event == ESP_GATTC_DISCONNECT_EVT)
  34.     {
  35.         Serial.printf("gattc event %i detected, disconnect reason: %i\n", (uint8_t)event, (int)param->disconnect.reason);
  36.     }
  37. }
  38.  
  39. void setup()
  40. {
  41.     Serial.begin(230400);
  42.  
  43.     BLEDevice::setCustomGattcHandler(gattcEventHandler);
  44.     BLEDevice::init("MuseClient");
  45.  
  46.     BLEClient *client = BLEDevice::createClient();
  47.     client->setClientCallbacks(new MyClientCallback());
  48.     BLEAddress address = BLEAddress("00:55:da:b0:e9:95"); //headset address
  49.     if (client->connect(address, BLE_ADDR_TYPE_PUBLIC))
  50.     {
  51.         BLERemoteService *pRemoteService = client->getService("0000fe8d-0000-1000-8000-00805f9b34fb");
  52.         if (pRemoteService != nullptr)
  53.         {
  54.             BLERemoteCharacteristic *pRemoteCharacteristic = pRemoteService->getCharacteristic("273e0003-4c4d-454d-96be-f03bac821358"); //TP9 EEG value
  55.             if (pRemoteCharacteristic != nullptr)
  56.             {
  57.                 pRemoteCharacteristic->registerForNotify(dataHandler);
  58.  
  59.                 String startDataFlowCmd = "\x02\x64\x0a";
  60.                 BLERemoteCharacteristic *pRemoteCharacteristicControlChannel = pRemoteService->getCharacteristic("273e0001-4c4d-454d-96be-f03bac821358");
  61.                 if (pRemoteCharacteristicControlChannel != nullptr)
  62.                 {
  63.                     Serial.println("Connected to control channel characteristic, sending command to start streaming data");
  64.                     pRemoteCharacteristicControlChannel->writeValue((unsigned char *)startDataFlowCmd.c_str(), startDataFlowCmd.length(), false);
  65.                 }
  66.             }
  67.             else
  68.             {
  69.                 Serial.println("Required remote characteristic not found");
  70.             }
  71.         }
  72.         else
  73.         {
  74.             Serial.println("Required service not found");
  75.         }
  76.     }
  77. }
  78.  
  79. void loop()
  80. {
  81. } // End of loop
And here the output of the above code in the serial console:

Code: Select all

connected to headset
Connected to control channel characteristic, sending command to start streaming data
recieved 20 packages so far
recieved 40 packages so far
recieved 60 packages so far
...
recieved 800 packages so far
recieved 820 packages so far
Device disconnected after 39971 ms and 829 recieved eeg packages
[I][BLEDevice.cpp:604] removePeerDevice(): remove: 0, GATT role client
gattc event 41 detected, disconnect reason: 34

pacsive
Posts: 1
Joined: Thu Aug 26, 2021 12:17 am

Re: ESP-32 as BLE client: connection always closes after 40 seconds

Postby pacsive » Thu Aug 26, 2021 12:21 am

Hi my friend, im trying to do the same as you, but why is the void loop empty in your code??? how does that work?
THanks

Paul-K.
Posts: 5
Joined: Tue Jul 28, 2020 8:31 am

Re: ESP-32 as BLE client: connection always closes after 40 seconds

Postby Paul-K. » Thu Aug 26, 2021 8:49 am

but why is the void loop empty in your code?
You don't need any code in the loop function if you are working with callbacks / event based API
The callback handler is assigned in the line:

Code: Select all

    client->setClientCallbacks(new MyClientCallback());
This takes care of handling incoming data in an event based approach.

Who is online

Users browsing this forum: Google [Bot] and 32 guests