Why the BLE Client example works on Arduino IDE but dont work on the Vscode PlatformIO

Im a student trying to read the temperature on a generic BLE Beacon using a ESP32-WROOM-32U. When i use the BLE client example on the Arduino IDE Version 1.8.19 using the native lib “ESP32 BLE Arduino” it works well, read the temp, all ok.

But when i upload the exactly same code using VsCode 1.69.1 and the same lib “ESP32 BLE Arduino” Version 2.0.0, compile and upload, but when it run, i get this error:

  Forming a connection to d4:b4:96:29:d5:b0
     - Created client
     - Connected to server
    
    Guru Meditation Error: Core  0 panic'ed (Unhandled debug exception). 
    Debug exception reason: Stack canary watchpoint triggered (BTU_TASK)
    Core  0 register dump:
    PC      : 0x40094f33  PS      : 0x00060b36  A0      : 0x80096c48  A1      : 0x3ffd0310
    A2      : 0x3ffb6c34  A3      : 0xb33fffff  A4      : 0x0000abab  A5      : 0x00060b23
    A6      : 0x00060b23  A7      : 0x0000cdcd  A8      : 0x0000cdcd  A9      : 0xffffffff  
    A10     : 0x00000000  A11     : 0x00000000  A12     : 0x00000008  A13     : 0x00000008  
    A14     : 0x007b6c34  A15     : 0x003fffff  SAR     : 0x0000001a  EXCCAUSE: 0x00000001
    EXCVADDR: 0x00000000  LBEG    : 0x4008fd48  LEND    : 0x4008fd5e  LCOUNT  : 0x00000000
    
    
    Backtrace:0x40094f30:0x3ffd03100x40096c45:0x3ffd0350 0x40096c6f:0x3ffd0370 0x40096ebc:0x3ffd0390 0x400834c6:0x3ffd03b0 0x400834d9:0x3ffd03e0 0x40083509:0x3ffd0400 0x40097305:0x3ffd0420 0x40097320:0x3ffd0440 0x401125c1:0x3ffd0460 0x40111d95:0x3ffd0480 0x40105149:0x3ffd04a0 0x401040b3:0x3ffd04c0 0x40128c41:0x3ffd04f0 0x40128d8f:0x3ffd0510 0x40128ed2:0x3ffd0530 0x400fbe25:0x3ffd0570 0x400fb295:0x3ffd0800 0x40115612:0x3ffd0820 0x40115750:0x3ffd0860 0x40115afa:0x3ffd0880 0x40115bb9:0x3ffd0b10 0x40115bd7:0x3ffd0b30 0x40115b9f:0x3ffd0b50 0x40115bd7:0x3ffd0b70 0x40115b9f:0x3ffd0b90 0x40115bd7:0x3ffd0bb0 0x40115b9f:0x3ffd0bd0 0x40115bd7:0x3ffd0bf0 0x40115b9f:0x3ffd0c10 0x40115bd7:0x3ffd0c30 0x40115b9f:0x3ffd0c50 0x40115bd7:0x3ffd0c70 0x40115b9f:0x3ffd0c90 0x40115cf6:0x3ffd0cb0 0x40100af1:0x3ffd0cd0 0x400fbe5e:0x3ffd0f70 0x400fc309:0x3ffd1200 0x400fccc1:0x3ffd1260 0x400fdffc:0x3ffd12a0 0x400fe032:0x3ffd12c0 0x40109299:0x3ffd12e0 0x400f9e18:0x3ffd1470 0x40112977:0x3ffd1490
    
    
    
    
    ELF file SHA256: 0000000000000000

    Rebooting...

I understand that in someway my code is making a stackoverflow, i already tried to modify the partition scheme using this https://geekelectronick.com/esp32-customizing-partition-in-platformio/ and reducing the massive use of serial.print but dont work.

I tried some of the tips here BLE client gets stuck while calling BLEClient::connect() · Issue #874 · nkolban/esp32-snippets · GitHub but dont work too.

The configuration on platformio.ini:

[env:esp32dev]
platform = espressif32
board = esp32dev
framework = arduino
monitor_speed = 115200

Below the code im using:

 /**
     * A BLE client example that is rich in capabilities.
     * There is a lot new capabilities implemented.
     * author unknown
     * updated by chegewara
     */
    #include "arduino.h"
    #include "BLEDevice.h"
    
    
    // The remote service we wish to connect to.
    static BLEUUID serviceUUID("0000AA20");
    // The characteristic of the remote service we are interested in.
    static BLEUUID    charUUID("0000AA21");
       
    String addr = String("d4:b4:96:29:d5:b0");  
    
    static boolean doConnect = false;
    static boolean connected = false;
    static boolean doScan = false;
    static BLERemoteCharacteristic* pRemoteCharacteristic;
    static BLEAdvertisedDevice* myDevice;
    
    static void notifyCallback(
      BLERemoteCharacteristic* pBLERemoteCharacteristic,
      uint8_t* pData,
      size_t length,
      bool isNotify) {
        Serial.print("Notify callback for characteristic ");
        Serial.print(pBLERemoteCharacteristic->getUUID().toString().c_str());
        Serial.print(" of data length ");
        Serial.println(length);
        Serial.print("data: ");
        Serial.println((char*)pData);
    }
    
    class MyClientCallback : public BLEClientCallbacks {
      void onConnect(BLEClient* pclient) {
      }
    
      void onDisconnect(BLEClient* pclient) {
        connected = false;
        Serial.println("onDisconnect");
      }
    };
    
    bool connectToServer() {
        Serial.print("Forming a connection to ");
        Serial.println(myDevice->getAddress().toString().c_str());
        
        BLEClient*  pClient  = BLEDevice::createClient();
        Serial.println(" - Created client");
    
        pClient->setClientCallbacks(new MyClientCallback());
    
        // Connect to the remove BLE Server.
        pClient->connect(myDevice);  // if you pass BLEAdvertisedDevice instead of address, it will be recognized type of peer device address (public or private)
        Serial.println(" - Connected to server");
        
    
        // 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.
        if(pRemoteCharacteristic->canRead()) {
          std::string value = pRemoteCharacteristic->readValue();
          Serial.print("The characteristic value was: ");
          Serial.println(value.c_str());
        }
    
        if(pRemoteCharacteristic->canNotify())
          pRemoteCharacteristic->registerForNotify(notifyCallback);
    
        connected = true;
        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());
      String result = advertisedDevice.getAddress().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.isAdvertisingService(serviceUUID) && result.compareTo(addr)==0) {
          BLEDevice::getScan()->stop();
          myDevice = new BLEAdvertisedDevice(advertisedDevice);
          doConnect = true;
          doScan = 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 5 seconds.
      BLEScan* pBLEScan = BLEDevice::getScan();
      pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
      pBLEScan->setInterval(1349);
      pBLEScan->setWindow(449);
      pBLEScan->setActiveScan(true);
      pBLEScan->start(60, false);
    } // End of setup.
    
    
    // This is the Arduino main loop function.
    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()) {
          Serial.println("We are now connected to the BLE Server.");
        } else {
          Serial.println("We have failed to connect to the server; there is nothin more we will do.");
        }
        doConnect = false;
      }
    
      // If we are connected to a peer BLE Server, update the characteristic each time we are reached
      // with the current time since boot.
      if (connected) {
        String newValue = "Canopus: " + String(millis()/1000);
        pRemoteCharacteristic->writeValue(newValue.c_str(), newValue.length());
        Serial.print("\r\n - Result sensor");
        std::string value = pRemoteCharacteristic->readValue(); 
        Serial.printf("\r\nLength : %d\r\n", value.length()); 
        Serial.print(" 0x"); Serial.print((uint8_t)value[0], HEX); 
        Serial.print(" 0x"); Serial.print((uint8_t)value[1], HEX);
        Serial.print(" 0x"); Serial.print((uint8_t)value[2], HEX);
        Serial.print(" 0x"); Serial.print((uint8_t)value[3], HEX);
        Serial.print(" 0x"); Serial.print((uint8_t)value[4], HEX);
        Serial.print(" 0x"); Serial.print((uint8_t)value[5], HEX);
    
        float temp = value[1]*100+value[2];
        if(value[1]==1)
        {
          temp=temp*-1;
        }
        Serial.printf("\r\nTemp: %.02f*C", temp/100); 
        float humi = value[4]*100+value[5];
        Serial.printf("\r\nHumi: %.02f/%", humi/100); 
                      
      }else if(doScan){
        BLEDevice::getScan()->start(0);  // this is just example to start scan after disconnect, most likely there is better way to do it in arduino
      }
      
      delay(10); // Delay a second between loops.
    } // End of loop

Stack usage comes from RAM usage, not the flash space assigned to the application – this problem can’t be solved with a change of partition tables.

If it works in the Arduino IDE and the same versions with regards to all libraries and the Arduino-ESP32 core is used, the result should be the same.

What does Arduino IDE → Tools → Board → Board Manager → ESP32 say about the exact version? 2.0.4? 2.0.3? 1.0.6?

1 Like

Hi, thanks for your reply.

Its using the 1.0.6 version.

Then instead of writing this, write

platform = espressif32@3.5.0

and reupload.

Otherwise with the more recent versions you get a 2.x core. (Releases · platformio/platform-espressif32 · GitHub)

2 Likes

Of course, downgrading to a lower core version, if it works, is just a work around. It can’t be that the recent version like 2.0.3 or 2.0.4 are incapbable of running a simple BLE sketch without hard-crashing in a stack overflow, that would be unacceptable.

1 Like

Well, downgrading works. Its running for almost 1 hour without crashing.

Many thanks for your help!

And on the subject of crashing on version 2.0.3 its a issue on the core then?

In the Arduino IDE, can you upgrade to 2.0.4 with the board manager and retest the sketch? If it also fails there, open an issue in Issues · espressif/arduino-esp32 · GitHub.

Hi, Tested with Version 2.0.4 e 2.0.3 and worked with no problem on ArduinoIDE. Opened the issue on github.

If it works in the Arduino IDE at core version 2.0.3 and 2.0.4, then Arduino-ESP32 has no problem. But since it doesn’t work in PlatformIO, PlatformIO has the problem. Then you’d need to open an issue at Issues · platformio/platform-espressif32 · GitHub, not at Arduino-ESP32.

Corrected. Changed forum. Thanks.