esp32-snippets
esp32-snippets copied to clipboard
BLE client hang after reading server multiple times (#505 closed. Still errors with new library)
Hi All I am using the example of the client collecting data from a BLE server. Works fine a couple of times. After 5 till 25 times. It stops.
Here is the log:
- Found our device! address:
- Forming a connection to c4:7c:8d:66:13:9a
- Created client E (975) BT_OSI: osi_mem_dbg_clean invalid E (2749) BT_OSI: osi_mem_dbg_clean invalid
- Connected to server
- Found our service E (4422) BLERemoteCharacteristic: esp_ble_gattc_get_all_descr: ESP_GATT_NOT_FOUND E (4424) BLERemoteCharacteristic: E (4429) BLERemoteCharacteristic:
- Found our characteristic The characteristic value was: 318 E (4508) BT_OSI: osi_mem_dbg_clean invalid W (4511) BT_APPL: bta_gattc_conn_cback() - cif=1 connected=0 conn_id=1 reason=0x0016
- We are now connected to the BLE Server. Next connect 1
-Forming a connection to c4:7c:8d:66:13:9a
- Created client E (7744) BT_OSI: osi_mem_dbg_clean invalid
- Connected to server .... <this repeats itself between 5 and 25 times > .....
Next connect 24 Forming a connection to c4:7c:8d:66:13:9a
-
Created client E (127911) BT_OSI: osi_mem_dbg_clean invalid
-
Connected to server
-
Found our service E (129237) BLERemoteCharacteristic: esp_ble_gattc_get_all_descr: ESP_GATT_NOT_FOUND E (129239) BLERemoteCharacteristic: E (129242) BT_OSI: osi_mem_dbg_record invalid !! E (129247) BLERemoteCharacteristic: esp_ble_gattc_get_all_descr: ESP_GATT_NOT_FOUND E (129256) BT_OSI: osi_mem_dbg_record invalid !! E (129260) BLERemoteCharacteristic: esp_ble_gattc_get_all_descr: ESP_GATT_NOT_FOUND
-
Found our characteristic E (129304) BT_OSI: osi_mem_dbg_record invalid !! E (129305) BT_OSI: osi_mem_dbg_record invalid !! E (129305) BT_GATT: attr offset = 0 p_attr_buf = 0x0 E (129310) BT_OSI: osi_mem_dbg_record invalid !! E (130864) BT_OSI: osi_mem_dbg_record invalid !! E (133864) BT_OSI: osi_mem_dbg_record invalid !! E (136864) BT_OSI: osi_mem_dbg_record invalid !! W (137870) BT_APPL: bta_gattc_conn_cback() - cif=1 connected=0 conn_id=1 reason=0x0013 E (137874) BT_OSI: osi_mem_dbg_record invalid !! E (137875) BT_BTC: btc_gattc_cback transfer failed
So my guess is this is they key "BT_OSI: osi_mem_dbg_clean invalid" The result of that will come on the end with this "BT_OSI: osi_mem_dbg_record invalid !!"
I am using the arduino library but not the arduino environment. Here is my code: #include "Arduino.h" #include "BLEDevice.h"
static BLEUUID serviceUUID( "00001204-0000-1000-8000-00805f9b34ff"); static BLEUUID charUUID( "00001a02-0000-1000-8000-00805f9b34ff");
static BLEAddress pServerAddress; static boolean doConnect = false; static boolean connected = false; static BLERemoteCharacteristic pRemoteCharacteristic;
int countID = 0;
bool connectToServer(BLEAddress pAddress) { Serial.print("Forming a connection to "); Serial.println(pAddress.toString().c_str());
BLEClient* pClient = BLEDevice::createClient();
if (pClient == nullptr) {
Serial.print(" - Failed to create client");
return false;
}
delay(300);
Serial.println(" - Created client");
// Connect to the remove BLE Server.
pClient->connect(pAddress);
Serial.println(" - Connected to server");
if(!pClient->isConnected()){
Serial.println(" - Not connected");
return false;
}
// Obtain a reference to the service we are after in the remote BLE server.
BLERemoteService* pRemoteService = pClient->getService(serviceUUID);
if (pRemoteService == nullptr) {
Serial.print("Failed to find our service UUID: ");
Serial.println(serviceUUID.toString().c_str());
pClient->disconnect();
return false;
} Serial.println(" - Found our service");
// Obtain a reference to the characteristic in the service of the remote BLE server. pRemoteCharacteristic = pRemoteService->getCharacteristic(charUUID); if (pRemoteCharacteristic == nullptr) { Serial.print("Failed to find our characteristic UUID: "); Serial.println(charUUID.toString().c_str()); pClient->disconnect();
return false;
} Serial.println(" - Found our characteristic");
// Read the value of the characteristic. std::string value = pRemoteCharacteristic->readValue(); Serial.print("The characteristic value was: "); Serial.println(value.c_str());
Serial.println(""); pClient->disconnect(); delay(200); return true; } /** Scan for BLE servers and find the first one that advertises the service we are looking for. / class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks { /* Called for each advertising BLE server. */ void onResult(BLEAdvertisedDevice advertisedDevice) { Serial.print("BLE Advertised Device found: "); Serial.println(advertisedDevice.toString().c_str()); // We have found a device, let us now see if it contains the service we are looking for. //if (advertisedDevice.haveServiceUUID() && advertisedDevice.getServiceUUID().equals(serviceUUID)) { if (advertisedDevice.haveName() && (advertisedDevice.getName() == "Flower care")) {
//
Serial.print("Found our device! address: ");
advertisedDevice.getScan()->stop();
pServerAddress = new BLEAddress(advertisedDevice.getAddress());
doConnect = true;
} // Found our server
} // onResult
}; // MyAdvertisedDeviceCallbacks
void setup() { Serial.begin(115200); Serial.println("Starting Arduino BLE Client application..."); BLEDevice::init("");
// Retrieve a Scanner and set the callback we want to use to be informed when we // have detected a new device. Specify that we want active scanning and start the // scan to run for 30 seconds. Serial.print("Device is initialized -> ");Serial.println(BLEDevice::getInitialized());
BLEScan* pBLEScan = BLEDevice::getScan(); pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks()); pBLEScan->setActiveScan(true); pBLEScan->start(30); } // End of setup.
void loop() {
// If the flag "doConnect" is true then we have scanned for and found the desired // BLE Server with which we wish to connect. Now we connect to it. Once we are // connected we set the connected flag to be true. if (doConnect == true) { if (connectToServer(*pServerAddress)) { Serial.println("We are now connected to the BLE Server."); connected = true; } else { Serial.println("We have failed to connect to the server; there is nothing more we will do."); } //doConnect = false; }
delay(1000); // Delay a second between loops. countID++; Serial.print("Next connect "); Serial.println(countID); } // End of loop
I will solve this. But for now I am stuck. Need help to debug.
Its possible there might be some memory leak somewhere (just guessing now), but this requires some more heap trace debugging or at least free heap printing, somewhere in onConnect():
ESP_LOGW("TAG", "%d: - RAM left %d", __LINE__, esp_get_free_heap_size());
Im not sure this will work in arduino without changes but im sure you can find a way to print it.
Your line works. It starts 135772 memory with and ends with 4096 after looping 24 times. I will tomorrow check in detail where the leak is.
I found the memory leak. pClient = BLEDevice::createClient(); should be in setup instead of connecttoserver(). Thanks
I am heading a new issue. I do not understand:
After running some time. I got the following issue:Forming a connection to c4:7c:8d:66:13:9a
E (106920) BT_GATT: application already registered.
E (106920) BT_APPL: Register with GATT stack failed.
E (106923) BT_GATT: application already registered.
E (106929) BT_APPL: Register with GATT stack failed.
E (106935) BT_GATT: application already registered.
E (106940) BT_APPL: Register with GATT stack failed.
E (106946) BT_GATT: application already registered.
E (106951) BT_APPL: Register with GATT stack failed.
E (106957) BT_GATT: application already registered.
E (106963) BT_APPL: Register with GATT stack failed.
E (106969) BT_GATT: application already registered.
E (106974) BT_APPL: Register with GATT stack failed.
E (106981) BT_APPL: bta_gattc_process_api_open Failed, unknown client_if: 0
And then it stops running.
I can see that this causes the issue. pClient->connect(pAddress);
When connecting twise. (the message is quite clear :) )
I added a delay of 200ms. between pClient->isConnected()
That makes is much more stable.. But still not relyable.
The following construction does not help either.
if(!pClient->isConnected()){
pClient->connect(pAddress);
}
Any suggestion?
This lines:
E (106920) BT_GATT: application already registered.
E (106920) BT_APPL: Register with GATT stack failed.
mean you have BLEDevice::createServer()
somewhere in loop, but it can be invoked only one time in setup.
Just one question, how many characteristics and descriptors are you creating?
Many thanks chegeware. Helping me with this.
I am actually using only a client to get data from a server.
So zero descriptors or characteristics are created. Only reading. (see code above)
BLEScan* pBLEScan = BLEDevice::getScan();
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
pBLEScan->setActiveScan(true);
pBLEScan->start(30);
pClient = BLEDevice::createClient();
It works fine now.
The other issue is in the loop: start function
if(!pClient->isConnected()){ // should never appear pClient->connect(pAddress); } delay(400); Serial.println(" - Connected to server"); if(!pClient->isConnected()){ Serial.println(" - Not connected"); return false; } .... some code. pClient->disconnect(); end of function I can see that sometimes it is not connected. I stop the function When I run the function again. It is still not not connected But will give the message:
E (106920) BT_GATT: application already registered. E (106920) BT_APPL: Register with GATT stack failed.
For some reason, i dont know why because i dont know your code, you are calling pClient->connect(pAddress);
when your client is already connected but pClient->isConnected()
is still returning false:
https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/BLEClient.cpp#L99
Please try to use longer delay.
a longer delay did the trick. Again thanks a lot. 400ms was too short. I am using 1000ms now. But that sounds a lot. Anyway it runs stable now.
This is required only because your code is write this way. You have to remember there is always some latency between peer devices, even if 400ms sounds a lot to me, for some reason you need more delay. Maybe you need to think about re-writing code, or leave it as it is if that fits you.
#Now I am facing the last error. Most likely the hardest one. Guru Meditation Error: Core 0 panic'ed (LoadProhibited). Exception was unhandled. Core 0 register dump: PC : 0x4013c802 PS : 0x00060030 A0 : 0x80122498 A1 : 0x3ffd2400 0x4013c802: L2CA_CheckIsCongest at C:/esp32/esp-idf/components/bt/bluedroid/stack/l2cap/l2c_api.c:1849
A2 : 0x00000000 A3 : 0x00000000 A4 : 0x3ffdf0d6 A5 : 0x3ffdf0cc A6 : 0x00000000 A7 : 0x6c615665 A8 : 0x8013c7f7 A9 : 0x3ffd23d0 A10 : 0x3ffda840 A11 : 0x3ffd24ac A12 : 0x0000000a A13 : 0x3ffc3ae8 A14 : 0x00ff0000 A15 : 0xff000000 SAR : 0x00000010 EXCCAUSE: 0x0000001c EXCVADDR: 0x000000e8 LBEG : 0x4000c2e0 LEND : 0x4000c2f6 LCOUNT : 0xffffffff
Backtrace: 0x4013c802:0x3ffd2400 0x40122495:0x3ffd2430 0x4011f255:0x3ffd2490 0x400f7547:0x3ffd24e0 0x400f7949:0x3ffd2570 0x400f675a:0x3ffd25c0 0x400e3fc4:0x3ffd25f0
0x4013c802: L2CA_CheckIsCongest at C:/esp32/esp-idf/components/bt/bluedroid/stack/l2cap/l2c_api.c:1849
0x40122495: esp_ble_gattc_write_char at C:/esp32/esp-idf/components/bt/bluedroid/api/esp_gattc_api.c:536
0x4011f255: BLERemoteCharacteristic::writeValue(std::__cxx11::basic_string<char, std::char_traits
https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/ArduinoBLE.md#decoding-an-exception-stack-trace
Thanks. I will find the cause.
Hi everybody, during my test I found some problems when a client connect and disconnect several time to a server. As You suggested I tried to add a delay(1000) on if(!pClient->isConnected()){ // should never appear pClient->connect(pAddress); } delay(1000); Serial.println(" - Connected to server"); if(!pClient->isConnected()){......
but sometimes this not work for me, I supposed this situation: pClient->connect(pAddress); is called stay pending for some reasons pClient->isConnected() is not set correctly because connect is pending after a while pClient->connect(pAddress); is called again and this hang the board
As workaround before to call a pClient->connect(pAddress); I call pClient->disconnect(); This solved the problem for me. Best Regards Marco
@mpbejo Could you test code i just pushed to features branch? Now library should be able to work with multiple clients so no need to disconnect, also fixed few other issues, like scan memory leak etc.
Hi chegewara, thank You for the great work. A little problem... I don't know how to do. (sorry) I explain better, actually I installed arduino ide, add the esp32 board and I found the Esp32 BLE Arduino in the Samples. Now how can I install the new library from features branch that You suggest? I have to copy and paste the files or what. Thank You for your patience Best Regards Marco
I can prepare zip file if you wish, then you can use this tutorial: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/ArduinoBLE.md#replacing-the-version-that-comes-with-arduino-esp32
Yes please, so I am sure that the files are correct. And then I start to test! A big question, do You know how many clients can connect to a server? Best Regards Marco
bluetooth specs says about 8 devices, but arduino-esp32 is setup to 3 or 4. I performed yesterday test (im not sure it was correct test) and i was able to connect 9 clients to one esp32 server, which is very strange.
Hi chegewara, I have downloaded the zip file from github selecting Branch:features. Then following the instructions of the link that You sent me I tried to build the ESP32_BLE.zip but the "make" command is not recognized on windows. Could You attach the ESP32_BLE.zip file with your latest changes. Thank You Best Regards Marco
Well, I think that I was able to install the library, I deleted the BLE folder from /hardware/esp32. Then in the Arduino IDE / Sketch / #include library / Add library from .ZIP file / and I selected the ZIP file downloaded from github, I compiled with no errors I hope it is correct!
Sorry is not working, I don't understand if I wrong to install the new library or if there is some new bugs. The server version of my sketch is compiled with no problem. The client have errors during compile it say that there is more than one "SPI.h" library I tried to change the order of the #include #include "xbm.h" // Sketch tab header for xbm images #include <TFT_eSPI.h> // Hardware-specific library #include <SPI.h> #include "Wire.h" #include <BLEDevice.h> #include <BLEUtils.h> #include <BLEScan.h> #include <BLEAdvertisedDevice.h>
and I was able to compile: Now the client connect to server but when pRemoteCharacAddr = pRemoteService->getCharacteristic(charUUID_Addr); is called I have this error: E (14478) boot: Assert failed in heap_caps_free, /Users/ficeto/Desktop/ESP32/ESP32/esp-idf-public/components/heap/heap_caps.c:261 (heap != NULL && "free() target pointer is outside heap areas") Task watchdog got triggered. The following tasks did not reset the watchdog in time:
- IDLE (CPU 0) Tasks currently running: CPU 0: Btc_task CPU 1: IDLE
As You wrote on https://github.com/espressif/arduino-esp32/issues/2012
@mpbejo Can you check charUUID_Addr
is the same on ble peripheral and pRemoteService != nullptr
?
Yes is the same, and now I have reinstalled the default BLE library and the sketch run correctly. Any suggestion? Can You confirm that my steps (wrote upper) to install the new library are correct? Because I think if You don't have my same problem I suppose I wrong something
@mpbejo Could you try with this zip file: https://github.com/nkolban/esp32-snippets/issues/717#issuecomment-440858956
No difference. with #717 zip. When the BLE is too far away it hangs. Does this help?
I am having the same issue. do yo solve this problem?
I think It was in my code. I believe I pointed to a nullpointer. I am not sure anymore (too long ago). Anyway. I restarted the ESP if there was a time out. (after 2 minutes). Here is my code:
/* >>>>>>>> bandaid begin try do continue even when no data is there / / */ hw_timer_t * timer = NULL; portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
void IRAM_ATTR onTimer() { portENTER_CRITICAL_ISR(&timerMux); ESP.restart(); // restart the ESP when it takes too long //Serial.print("Something happend. Please take action! "); portEXIT_CRITICAL_ISR(&timerMux);
}
void bandAidStartTimer() { timer = timerBegin(0, 80, true); timerAttachInterrupt(timer, &onTimer, true); timerAlarmWrite(timer, 1000000*120, false); // 2 minutes once a reset true); timerAlarmEnable(timer); }
void bandAidStopTimer() { timerEnd(timer); timer = NULL; }
/* <<<<<<<<<< band iad end */
bandAidStartTimer(); // start BandAid , restart ESP32 after 2 minutes. So that hangs in write() is not causing a full stop. ..............Your BLE reading, that might hang......................... bandAidStopTimer(); // stop BandAid
Hello, I have spent 3 days & nights trying to exchange data between my 2 ESP32 (DOIT ESP32 DEVKIT 1) without success. I tryed also your solution but I am always stuck there: the client replies in serial: "We have failed to connect to the server; there is nothing more we will do." I can test BLE_Server with my smartphone and everything is OK: read and write operation. I give you below the serial output. It is possible to share your codes: for the server and for the client ? Thanks for any help.
"Starting Arduino BLE Client application... BLE Advertised Device found: Name: , Address: 30:61:e6:c9:4f:80, manufacturer data: 0600010f20021a1e6cbdf0bc92667989c792c80877f8abfdc8d7444dda BLE Advertised Device found: Name: Long name works now, Address: 94:b9:7e:e4:a3:da, serviceUUID: 4fafc201-1fb5-459e-8fcc-c5c9c331914b, txPower: 3 Forming a connection to 94:b9:7e:e4:a3:da
- Created client
- Connected to server TAG120980: - RAM left 1073610484
- Found our service
- Found our characteristic The characteristic value was: Hello World says Neil We have failed to connect to the server; there is nothin more we will do. Setting new characteristic value to "Time since boot: 2" Setting new characteristic value to "Time since boot: 4" Setting new characteristic value to "Time since boot: 5" " Used sources are : https://github.com/nkolban/ESP32_BLE_Arduino