h2zero / NimBLE-Arduino

A fork of the NimBLE library structured for compilation with Arduino, for use with ESP32, nRF5x.
https://h2zero.github.io/NimBLE-Arduino/
Apache License 2.0
672 stars 138 forks source link

ESP32 slow bluetooth speed #553

Closed pwilkowski closed 1 year ago

pwilkowski commented 1 year ago

Hello, is there any way to increase performance of BLE ?

I am trying to send 1Mb of firmware file split into 469bytes chunks, unfortunately this takes like 20 minutes (500ms per chunk) I tried using write value without respose but that did not solve anything.

My code is super simple at this point and i cant think of anything that could speed it up:

// Create the BLE Device
    NimBLEDevice::init("UART Service");
    NimBLEDevice::setPower(ESP_PWR_LVL_P9);

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

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

    // Create a BLE Characteristic
    pTxCharacteristic = pService->createCharacteristic(CHARACTERISTIC_UUID_TX, NIMBLE_PROPERTY::NOTIFY);

    auto pRxCharacteristic =
        pService->createCharacteristic(
            CHARACTERISTIC_UUID_RX,
            NIMBLE_PROPERTY::WRITE_NR | NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::READ
        );

    pRxCharacteristic->setCallbacks(new MyCallbacks());

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

    // Start the server
    pServer->start();

    NimBLEAdvertising* pAdvertising = NimBLEDevice::getAdvertising();
    pAdvertising->addServiceUUID(pService->getUUID());
    /** If your device is battery powered you may consider setting scan response
     *  to false as it will extend battery life at the expense of less data sent.
     */
    pAdvertising->setScanResponse(true);
    // Start advertising
    pAdvertising->start();

    Serial.println("Waiting a client connection to notify...");
chegewara commented 1 year ago

Is this your whole ble code? Do you have maybe onConnect callback with something like that?

updateConnParams(desc->conn_handle, 50, 50, 0, 200); // the lower the better (here are fairly medium)

or this with too high values

setConnectionParams(100, 100, 0, 200); // the lower the better
pwilkowski commented 1 year ago

@chegewara yes i tried that as well, even with just 1, 1 (1, 10 or 10, 20, basically tried to gradually reduce it till 1, 1):

void MyServerCallbacks::onConnect(NimBLEServer* pServer, ble_gap_conn_desc* desc) {
    deviceConnected = true;
    Serial.print("Client address: ");
    Serial.println(NimBLEAddress(desc->peer_ota_addr).toString().c_str());
    /** We can use the connection handle here to ask for different connection parameters.
     *  Args: connection handle, min connection interval, max connection interval
     *  latency, supervision timeout.
     *  Units; Min/Max Intervals: 1.25 millisecond increments.
     *  Latency: number of intervals allowed to skip.
     *  Timeout: 10 millisecond increments, try for 5x interval time for best results.
     */
    pServer->updateConnParams(desc->conn_handle, 1, 1, 0, 60);
};

Did not change a thing.

I have also changed MTU to 512, that slightly increased the speed.

I tried to remove ALL the code from onWrite callback to see if that is the problem and still no difference.

UPDATE:

Chip ESP32-S3 Board: WT SC01 Plus (16mb flash, 2mb psram) Code repo: https://github.com/kaminaris/UniVesc-Display2

chegewara commented 1 year ago

Then you should check what min values are allowed. 1, 1 are way too low. IIRC 6,6 are minimal values. And yes, I had similar problem with the same board recently, then I figured out how small I know about ble after 5 years of working with it. When I changed to minimal I had to add delay, because ota over ble was too fast.

pwilkowski commented 1 year ago

@chegewara wow this is amazing, i put 6,6 and it suddenly speed up 20x, entire firmware sent in about 1 minute, thanks!

doudar commented 1 year ago

I’m not 100% but I believe this may be because your MTU data needs to fit within your max connection interval.

chegewara commented 1 year ago

I’m not 100% but I believe this may be because your MTU data needs to fit within your max connection interval.

you dont have to believe he did test, he confirmed its working, its all that matters case closed, topic can be closed