HI! I tried to transmit at the rate of 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 Code:
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 ino Code:
#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();
// // 确定传感器的连接状态
// // 缓冲区没有字符时,每半秒发送1次
// while (true)
// {
// if (Serial1.available() <= 0)
// {
// Serial1.print('A');
// delay(500);
// }
// else
// {
// while (Serial1.available()>=0)
// {
// Serial1.read();
// }
// break;
// }
// }
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;
}
}
}
// 输出数据
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();
// long time = millis();
// for (int i = 0; i < 7000; i++)
// {
// recvWithEndMarker();
// showNewData();
// }
// float a = 1000 / ((millis() - time) / 1000);
// Serial2.println();
// Serial2.println();
// Serial2.println();
// Serial2.println();
// Serial2.println();
// Serial2.println();
// Serial2.println(xiao.data());
// delay(100000);
}
}
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.![]()
