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:
- #include <Arduino.h>
- #include "BLEDevice.h"
- unsigned long packageCounter = 0;
- unsigned long connectionTime = 0;
- void dataHandler(BLERemoteCharacteristic *pBLERemoteCharacteristic, uint8_t *pData, size_t length, bool isNotify)
- {
- packageCounter++;
- if (packageCounter % 20 == 0)
- {
- Serial.printf("recieved %ld packages so far\n", packageCounter);
- }
- }
- class MyClientCallback : public BLEClientCallbacks
- {
- void onConnect(BLEClient *pclient)
- {
- Serial.println("connected to headset");
- connectionTime = millis();
- }
- void onDisconnect(BLEClient *pclient)
- {
- Serial.printf("Device disconnected after %ld ms and %ld recieved eeg packages\n", millis() - connectionTime, packageCounter);
- }
- };
- void gattcEventHandler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param)
- {
- //ESP_LOGW(LOG_TAG, "custom gattc event handler, event: %d", (uint8_t)event);
- if (event == ESP_GATTC_DISCONNECT_EVT)
- {
- Serial.printf("gattc event %i detected, disconnect reason: %i\n", (uint8_t)event, (int)param->disconnect.reason);
- }
- }
- void setup()
- {
- Serial.begin(230400);
- BLEDevice::setCustomGattcHandler(gattcEventHandler);
- BLEDevice::init("MuseClient");
- BLEClient *client = BLEDevice::createClient();
- client->setClientCallbacks(new MyClientCallback());
- BLEAddress address = BLEAddress("00:55:da:b0:e9:95"); //headset address
- if (client->connect(address, BLE_ADDR_TYPE_PUBLIC))
- {
- BLERemoteService *pRemoteService = client->getService("0000fe8d-0000-1000-8000-00805f9b34fb");
- if (pRemoteService != nullptr)
- {
- BLERemoteCharacteristic *pRemoteCharacteristic = pRemoteService->getCharacteristic("273e0003-4c4d-454d-96be-f03bac821358"); //TP9 EEG value
- if (pRemoteCharacteristic != nullptr)
- {
- pRemoteCharacteristic->registerForNotify(dataHandler);
- String startDataFlowCmd = "\x02\x64\x0a";
- BLERemoteCharacteristic *pRemoteCharacteristicControlChannel = pRemoteService->getCharacteristic("273e0001-4c4d-454d-96be-f03bac821358");
- if (pRemoteCharacteristicControlChannel != nullptr)
- {
- Serial.println("Connected to control channel characteristic, sending command to start streaming data");
- pRemoteCharacteristicControlChannel->writeValue((unsigned char *)startDataFlowCmd.c_str(), startDataFlowCmd.length(), false);
- }
- }
- else
- {
- Serial.println("Required remote characteristic not found");
- }
- }
- else
- {
- Serial.println("Required service not found");
- }
- }
- }
- void loop()
- {
- } // End of loop
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