nkolban / esp32-snippets

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

BLE Server+ WiFi, BLE::Init Exception #818

Open jsmith1717 opened 5 years ago

jsmith1717 commented 5 years ago

I'm having a basic problem getting BLE to work with WiFi. The example BLE server (ble_server.ino) works great by itself. I have a large app that runs wifi, http server, client, etc which also works great and never crashes. When I put the ble_server code into my app, it crashes on BLEDevice::init("..."), just like it did for ifrew in this thread [https://github.com/nkolban/esp32-snippets/issues/227].

Weirdly, it doesn't get a guru meditation error with a stackdump that I can trace. Instead, it only prints the reset code plus fatal exception:

rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:952
load:0x40078000,len:6084
load:0x40080000,len:7936
entry 0x40080310
Fatal exception (0): IllegalInstruction
epc1=0x40080342, epc2=0x00000000, epc3=0x00000000, excvaddr=0x00000000, depc=0x00000000 

I added -Map=arduino.map to our custom config.mk to generate a map file, so I could find out where it was crashing. It turns out that epc1=0x40080342 is in the exception handler. So the error is no help in finding the problem. I only found out what line it crashes on by commenting out code til it stopped crashing.

I then ran @ifrew's ble example.ino.

#include <WiFi.h>
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>

char LK8EX1_Sentence[80];

BLECharacteristic *pCharacteristic;

bool deviceConnected = false;

uint8_t txValue = 0;

const char *CHARACTERISTIC_UUID_DEVICENAME = "00002A00-0000-1000-8000-00805F9B34FB";
const char *CHARACTERISTIC_UUID_RXTX = "0000FFE1-0000-1000-8000-00805F9B34FB";
const char *CHARACTERISTIC_UUID_RXTX_DESCRIPTOR = "00002902-0000-1000-8000-00805F9B34FB";
const char *SERVICE_UUID = "0000FFE0-0000-1000-8000-00805F9B34FB";

class MyServerCallbacks : public BLEServerCallbacks {

    void onConnect(BLEServer* pServer) {
        deviceConnected = true;
    };

    void onDisconnect(BLEServer* pServer) {
        deviceConnected = false;
    }

};

class MyCallbacks : public BLECharacteristicCallbacks {

    void onWrite(BLECharacteristic *pCharacteristic) {
        std::string rxValue = pCharacteristic->getValue();
        if (rxValue.length() > 0) {
            Serial.println("*********");
            Serial.print("Received Value: ");
            for (int i = 0; i < rxValue.length(); i++)
                Serial.print(rxValue[i]);
            Serial.println();
            Serial.println("*********");
        }

    }

};

void NEMEA_Checksum(char *sentence)
{
    char chksum[3];
    const char *n = sentence + 1; // Plus one, skip '$'
    uint8_t chk = 0;
    /* While current char isn't '*' or sentence ending (newline) */
    while ('*' != *n && '\n' != *n) {
        chk ^= (uint8_t)*n;
        n++;
    }
    //convert chk to hexadecimal characters and add to sentence
    sprintf(chksum, "%02X\n", chk);
    strcat(sentence, chksum);
}

void BLESendChunks(std::string str)
{
    std::string substr;
    if (deviceConnected) {
        for (int k = 0; k < str.length(); k += _min(str.length(), 20)) {
            substr = str.substr(k, _min(str.length() - k, 20));
            pCharacteristic->setValue(substr);
            pCharacteristic->notify();
        }
    }
}

void setup() {
    Serial.begin(115200);
    WiFi.status();
    WiFi.mode(WIFI_AP);
    WiFi.begin();
    int timeout = 0;
    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        timeout++;
        Serial.printf("[%ld] - Wifi connect status : %d\r\n", millis(), WiFi.status());
        if (timeout == 20)
        {
            WiFi.mode(WIFI_AP);
            break;
        }
    }
    IPAddress ip;
    WiFi.softAPConfig(ip.fromString("192.168.4.1"), ip.fromString("192.168.4.1"), IPAddress(255, 255, 255, 0));
    WiFi.softAP("testble", "12345678");
    delay(100);
    // Create the BLE Device
    BLEDevice::init("UART Service");

    // Create the BLE Server
    BLEServer *pServer = BLEDevice::createServer();
    pServer->setCallbacks(new MyServerCallbacks());

    // Create the BLE Service
    BLEService *pService = pServer->createService(SERVICE_UUID);

    // Create a BLE Characteristic
    pCharacteristic = pService->createCharacteristic(CHARACTERISTIC_UUID_RXTX,
        BLECharacteristic::PROPERTY_NOTIFY| BLECharacteristic::PROPERTY_WRITE

    );

    pCharacteristic->addDescriptor(new BLEDescriptor(CHARACTERISTIC_UUID_RXTX_DESCRIPTOR));

    BLECharacteristic *pCharacteristic = pService->createCharacteristic(
        CHARACTERISTIC_UUID_DEVICENAME,
        BLECharacteristic::PROPERTY_READ
    );
    pCharacteristic->setValue("esp32ble-hm10");

    pCharacteristic->setCallbacks(new MyCallbacks());

    // Start the service
    pService->start();

    // Start advertising
    pServer->getAdvertising()->start();
    Serial.println("Waiting a client connection to notify...");
}

void loop() {
    if (deviceConnected) {
        sprintf(LK8EX1_Sentence, "$LK8EX1,%d,%d,%d,%d,%d.%d*", 101300, 8500, 2, 20, 3, 7);
        NEMEA_Checksum(LK8EX1_Sentence);
        Serial.printf("*** Sent Value: %s", LK8EX1_Sentence);
        //BLESendChunks(LK8EX1_Sentence);
    }
    delay(1000);
}

I had to make a new partition .csv and new board in board.txt with more app space to compile it. Weirdly, I did not have to do that to compile my large app with knolban's ble_server code in it. I don't understand how ifrew's small example can be larger than my app + Neil's BLE.

Anyway, I tried uncommenting the esp_bt_controller_mem_release in BleDevice.cpp. Still crashed. Then I commented it, and added the line to setup() per @chegewara 's instructions. Still crashed. Then I edited sdkconfig.h, even though the top of the file says autogenerated and "do not edit". Still crashes. I can't get it to run long enough to print the free heap space. On my big app with no BLE I have 162K.

I downloaded the esp32 core for Arduino in August 2018. I'm reluctant to download the latest, because I have three big projects close to release that use the 2018 core.

I'd really appreciate some help in dealing with this. I'm about to release three products that all require Bluetooth. Everything else works great, and yet I'm stonewalled at the finish line.

chegewara commented 5 years ago

If you are using old arduino-esp32 version then using esp_bt_controller_mem_release should works, just remember to call it as very first line in setup (just in case). In new arduino-esp32 it will crash app.

My suggestion would be to try change order wifi and ble initialization.

jsmith1717 commented 5 years ago

Thank you. Unfortunately, changing the Wifi/Ble order didn't fix the problem. It still crashes on the first line of Bluetooth (BleInit). I tried the latest arduino-esp32 on a different machine and it also crashes on the BleInit.

I'm really perplexed because it seems like a lot of other people are running Bluetooth + Wifi. And I can't even get ifrew's simple example to work. Yet I am able to write large programs with Wifi, Https, Dns, Ssdp, and lots of other stuff that all plays great together...

h2zero commented 5 years ago

I had trouble with this a bit in the past using the core from the same time frame. The problem was solved when I initialized WiFi first then put it in max power save mode with esp_wifi_set_ps(WIFI_PS_MAX_MODEM) then initialized BLE.

tommy-mor commented 5 years ago

any update on this? did you figure it out?.. having the same issue.

mrdc commented 4 years ago

BLE and WiFi init in my case, but I get unstable WiFi connection and BLE also drops. Several times I was able to control BLE devices while using WiFi, but it was unstable with HUGE delays. After some time ESP32 reboots because of an error: esp32 freertos/queue.c:706 (xQueueCreateCountingSemaphore)- assert failed!

@jsmith1717 Have you fixed the issue?

@h2zero

The problem was solved when I initialized WiFi first then put it in max power save mode with esp_wifi_set_ps(WIFI_PS_MAX_MODEM) then initialized BLE.

It doesn't help in my case. I init WiFi first, then adjust the Wifi Power Saving features and then init BLE. Part of code below:

  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  Serial.print("Connecting to ");
  Serial.print(WIFI_SSID);
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }
  esp_wifi_set_ps(WIFI_PS_MAX_MODEM);
  Serial.println();
  Serial.print("Connected to ");
  Serial.println(WIFI_SSID);
  Serial.print("IP Address is : ");
  Serial.println(WiFi.localIP());                          

And then BLE:

BLEDevice::init("TestDevice"); 
  BLEServer *pServer = BLEDevice::createServer();
  pServer->setCallbacks(new MyServerCallbacks());