'How to solve the overflow phenomenon in BLE high speed transmission or strange bag loss phenomenon?

I tried to transmit at the rate of 30000~36000 bytes(Send the notify of the device continuously), but win10 bluetooth receiver has packet loss phenomenon, although there is no lack of comma or period, Win10 received Bluetooth packet string is relatively complete, but missing more than a dozen complete packets, as shown below:

BLE: ESP32 DEVKIT V1 PC: NOTEBOOK COMPUTER

Win10 PYTHON Bleak example Code(Bleak Ver0.15.0a1):

import sys
import time
import platform
import asyncio
import logging

from bleak import BleakClient

logger = logging.getLogger(__name__)

ADDRESS = (
    "24:71:89:cc:09:05"
)
CHARACTERISTIC_UUID = f"ca73b3ba-39f6-4ab3-91ae-186dc9577d99"


async def run_ble_client(address: str, char_uuid: str, queue: asyncio.Queue):
    async def callback_handler(sender, data):
        await queue.put((time.time(), data))

    async with BleakClient(address) as client:
        logger.info(f"Connected: {client.is_connected}")
        await client.start_notify(char_uuid, callback_handler)
        while True:
                await asyncio.sleep(10.0)
        # await client.stop_notify(char_uuid)
        # Send an "exit command to the consumer"
        await queue.put((time.time(), None))


async def run_queue_consumer(queue: asyncio.Queue):
    while True:
        # Use await asyncio.wait_for(queue.get(), timeout=1.0) if you want a timeout for getting data.
        epoch, data = await queue.get()
        if data is None:
            logger.info(
                "Got message from client about disconnection. Exiting consumer loop..."
            )
            break
        else:
            logger.info(f"Received callback data via async queue at {epoch}: {data}")


async def main(address: str, char_uuid: str):
    queue = asyncio.Queue()
    client_task = run_ble_client(address, char_uuid, queue)
    consumer_task = run_queue_consumer(queue)
    await asyncio.gather(client_task, consumer_task)
    logger.info("Main method done.")


if __name__ == "__main__":
    logging.basicConfig(level=logging.INFO)
    asyncio.run(
        main(
            sys.argv[1] if len(sys.argv) > 1 else ADDRESS,
            sys.argv[2] if len(sys.argv) > 2 else CHARACTERISTIC_UUID,
        )
    )

ESP32 Arduino Ino Code(Arduino BLE_UART example ):

#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
// #include <periph_ctr
#define SERIAL_RX_BUFFER_SIZE 2048
BLEServer *pServer = NULL;
BLECharacteristic *pTxCharacteristic;
bool deviceConnected = false;
bool oldDeviceConnected = false;
boolean newData = false;

const byte numChars = 36;
uint8_t txValue = 0;
char receivedChars[numChars];

// See the following for generating UUIDs:
// https://www.uuidgenerator.net/

#define SERVICE_UUID "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" // UART service UUID
#define CHARACTERISTIC_UUID_RX "f78ebbff-c8b7-4107-93de-889a6a06d408"
#define CHARACTERISTIC_UUID_TX "ca73b3ba-39f6-4ab3-91ae-186dc9577d99"

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)
    {
      Serial2.println("*********");
      Serial2.print("Received Value: ");
      for (int i = 0; i < rxValue.length(); i++)
        Serial2.print(rxValue[i]);

      Serial2.println();
      Serial2.println("*********");
    }
  }
};
void setup()
{
  Serial1.begin(500000, SERIAL_8N1, 3, 1);
  Serial2.begin(500000, SERIAL_8N1, 16, 17);

  // Create the BLE Device
  BLEDevice::init("UART Service");

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

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

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

  pTxCharacteristic->addDescriptor(new BLE2902());

  BLECharacteristic *pRxCharacteristic = pService->createCharacteristic(
      CHARACTERISTIC_UUID_RX,
      BLECharacteristic::PROPERTY_WRITE);

  pRxCharacteristic->setCallbacks(new MyCallbacks());

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

  // Start advertising
  pServer->getAdvertising()->start();

  Serial2.println("\nSet Serial1 ok!");
  Serial2.println("Waiting a client connection to notify...");
}

// void loop()
// {
//   recvWithEndMarker();
//   showNewData();
// }
void recvWithEndMarker()
{
  static byte ndx = 0;
  static boolean recvInProgress = false;
  char startMaker = '<';
  char endMarker = '>';
  char rc;

  // if (Serial1.available() > 0) {
  while (Serial1.available() > 0 && newData == false)
  {
    rc = Serial1.read();
    if (recvInProgress == true)
    {
      if (rc != endMarker)
      {
        receivedChars[ndx] = rc;
        ndx++;
        if (ndx >= numChars)
        {
          ndx = numChars - 1;
        }
      }
      else
      {
        receivedChars[ndx] = '\0'; // terminate the string
        recvInProgress = false;
        ndx = 0;
        newData = true;
      }
    }
    else if (rc == startMaker)
    {
      recvInProgress = true;
    }
  }
}

// Send data after read sensor data
void showNewData()
{
  if (newData == true)
  {
    Serial2.println(receivedChars);
    pTxCharacteristic->setValue(receivedChars);
    pTxCharacteristic->notify();
    newData = false;
  }
}
void loop()
{
  // disconnecting
  if (!deviceConnected && oldDeviceConnected)
  {
    delay(500);                 
    pServer->startAdvertising(); 
    Serial2.println("disconnecting start advertising");
    oldDeviceConnected = deviceConnected;
    ESP.restart();
  }
  // connecting
  if (deviceConnected && !oldDeviceConnected)
  {
    // do stuff here on connecting
    oldDeviceConnected = deviceConnected;
    Serial2.println("connecting start advertising");
  }
  if (deviceConnected)
  {

    recvWithEndMarker();
    showNewData();
  }
}

BLE typically has a connection interval of about 30 to 50 milliseconds, so it can only send 20 to 30 packets per second. HID devices can have the fastest interval of 15 milliseconds (depending on the configuration) which would be 66 packets per second. The maximum MTU is for most devices is 512 bytes, so this would give 66 * 512 = approx 34000 bytes per second. So perhaps the buffer on the ESP32 is overflowing from trying to send data faster than what is possible.

I tried to reduce the speed to 8000-10000 bytes, but it still lost packets.

I have no experience in bluetooth debugging. I need to ensure a high rate of data transmission and avoid packet loss.What is the solution for ESP32 sending buffer overflow?

Thank you for reading this question.😀

PS:

I tried to use classic Bluetooth(SPP), but got frustrated along the develop. I had the same problem from the url:ESP32 SPP Bluetooth not working with Windows 10



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source