nkolban / esp32-snippets

Sample ESP32 snippets and code fragments
https://leanpub.com/kolban-ESP32
Apache License 2.0
2.37k stars 710 forks source link

Unknown crashes and error messages on ESP32 using BLEDevice #1141

Open hugovantriet opened 2 years ago

hugovantriet commented 2 years ago

I'm facing several stability issues with this library on multiple ESP32 boards. I made a custom version of the BLE_client example for reading a BLE heart rate monitor and printing the values over serial. My ESP-WROVER-KIT board is the most stable of the 2, but my regular ESP32 WROOM development board mostly keeps bootlooping. This is the code I wrote:


#define red 0
#define green 2
#define blue 4

// Heart rate monitor service UUID:
static BLEUUID serviceUUID("0000180d-0000-1000-8000-00805f9b34fb");
// Heart rate characteristic:
static BLEUUID charUUID(BLEUUID((uint16_t)0x2A37));

static boolean doConnect = false;
static boolean connected = false;
static boolean doScan = false;
static boolean notification = false;
static BLERemoteCharacteristic* pRemoteCharacteristic;
static BLEAdvertisedDevice* myDevice;

static void LEDInit() {
  pinMode(red, OUTPUT);
  pinMode(green, OUTPUT);
  pinMode(blue, OUTPUT);
  digitalWrite(red, LOW);
  digitalWrite(green, LOW);
  digitalWrite(blue, LOW);
}

static void notifyCallback(BLERemoteCharacteristic* pBLERemoteCharacteristic, uint8_t* pData, size_t length, bool isNotify) {
  //printing the heart rate value with length of 2 bytes to the serial monitor (only 2nd byte)
  if (length == 2) {
    Serial.println(pData[1], DEC);
  }
}

class MyClientCallback : public BLEClientCallbacks {
  void onConnect(BLEClient* pclient) {
  }

  void onDisconnect(BLEClient* pclient) {
    connected = false;
    Serial.println("disconnected");
    digitalWrite(red, HIGH);
    delay(2000);
    digitalWrite(red, LOW);
  }
};

bool connectToServer() {
    Serial.println("connecting");
    Serial.println(myDevice->getAddress().toString().c_str());

    BLEClient*  pClient  = BLEDevice::createClient();

    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)
    pClient->setMTU(517); //set client to request maximum MTU from server (default is 23 otherwise)

    // Obtain a reference to the service we are after in the remote BLE server.
    BLERemoteService* pRemoteService = pClient->getService(serviceUUID);
    if (pRemoteService == nullptr) {
      Serial.println("no service");
      pClient->disconnect();
      return false;
    }

    // Obtain a reference to the characteristic in the service of the remote BLE server.
    pRemoteCharacteristic = pRemoteService->getCharacteristic(charUUID);
    if (pRemoteCharacteristic == nullptr) {
      pClient->disconnect();
      return false;
    }
    // Read the value of the characteristic.
    if(pRemoteCharacteristic->canRead()) {
      std::string value = pRemoteCharacteristic->readValue();
    }

    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) {
    // We have found a device, let us now see if it contains the service we are looking for.
    if (advertisedDevice.haveServiceUUID() && advertisedDevice.isAdvertisingService(serviceUUID)) {

      BLEDevice::getScan()->stop();
      myDevice = new BLEAdvertisedDevice(advertisedDevice);
      doConnect = true;
      doScan = true;

    } // Found our server
  } // onResult
}; // MyAdvertisedDeviceCallbacks

void setup() {
  LEDInit();
  Serial.begin(115200);
  while (!(Serial.available() > 0));
  Serial.println("starting");
  BLEDevice::init("BLE receiver");

  // 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 20 seconds.
  BLEScan* pBLEScan = BLEDevice::getScan();
  pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
  pBLEScan->setInterval(1349);
  pBLEScan->setWindow(449);
  pBLEScan->setActiveScan(true);
  for (int i=0; i<3; i++) {
    digitalWrite(blue, HIGH);
    delay(50);
    digitalWrite(blue, LOW);
    delay(50);
  }
  pBLEScan->start(20, 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("connected");
      digitalWrite(green, HIGH);
      delay(2000);
      digitalWrite(green, LOW);
    } else {
      Serial.println("disconnected");
      digitalWrite(red, HIGH);
      delay(2000);
      digitalWrite(red, LOW);
    }
    doConnect = false;
  }

  if (connected) {
    if (!notification) {
      const uint8_t onPacket[] = {0x01, 0x00};
      pRemoteCharacteristic->getDescriptor(BLEUUID((uint16_t)0x2902))->writeValue((uint8_t*)onPacket, 2, true);
      notification = true;
    }
  }else if(doScan){
    delay(2000);
    for (int i=0; i<3; i++) {
      digitalWrite(blue, HIGH);
      delay(50);
      digitalWrite(blue, LOW);
      delay(50);
    }
    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(1000); // Delay a second between loops.
} // End of loop

This code mostly works fine on the WROVER devboard, but sometimes when I get my heart rate monitor out of reach it will give me the following errors:

Guru Meditation Error: Core  0 panic'ed (Unhandled debug exception). 
Debug exception reason: Stack canary watchpoint triggered (BTU_TASK) 
Core  0 register dump:
PC      : 0x40084505  PS      : 0x00060536  A0      : 0x00060520  A1      : 0x3ffd0390  
A2      : 0x00000000  A3      : 0x00060523  A4      : 0x00060520  A5      : 0x00060523  
A6      : 0x00060523  A7      : 0x00000000  A8      : 0x00000001  A9      : 0x00000000  
A10     : 0x00060523  A11     : 0x00000000  A12     : 0x00000008  A13     : 0x00000008  
A14     : 0x007b6c34  A15     : 0x003fffff  SAR     : 0x0000001f  EXCCAUSE: 0x00000001  
EXCVADDR: 0x00000000  LBEG    : 0x4008feb0  LEND    : 0x4008febb  LCOUNT  : 0xffffffff  

Backtrace:0x40084502:0x3ffd03900x0006051d:0x3ffd0460  |<-CORRUPTED

ELF file SHA256: 0000000000000000

Rebooting...

The WROVER only shows this message when I get the sensor out of reach, but the WROOM will just keep bootlooping with this during startup, and sometimes with a lot of luck it will finish the boot cycle and start doing this after the first values are printed. Does someone know if this is a known problem and how I can fix it?

chegewara commented 2 years ago

Stack canary watchpoint triggered (BTU_TASK)

but i dont see anything which could lead to this issue