低功耗蓝牙(ESP32 和 Android 智能手机之间):数据传输很慢
Posted
技术标签:
【中文标题】低功耗蓝牙(ESP32 和 Android 智能手机之间):数据传输很慢【英文标题】:Bluetooth Low Energy (between ESP32 and Android smartphone): Data transmission quite slow 【发布时间】:2021-10-11 22:23:01 【问题描述】:这是我在这个板上提出的第一个问题
项目简介:
5 个传感器,与 esp32 板相连,每秒传输 1000 个样本,每个样本有 16 位。这些值应通过 BLE 传输(使用 BLE Arduino 库和 ESP32)。连接的设备(智能手机)应该读取这些值并对其进行处理(也通过 BLE,使用以下库:https://github.com/RobotPajamas/Blueteeth)。 ESP32 是服务器! Java 用于 Android Studio!
问题:
在测试 BLE 连接时,会传输一个简单的“hello world”作为特征值。每次我在 android-device 端收到“hello world”时,都会增加一个变量:问题是,该变量在一秒钟内只增加了 4 次。这意味着(假设 1 个字符在等于 1 字节的字符串中)正在传输 11byte*4(1/s)=44byte/s。 -> 这显然是不够的(BLE 不应该传输 ~2MBit/s(减去协议数据))
代码片段
ESP32:传输价值的BLE-Server
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
class MyCallbacks: public BLECharacteristicCallbacks
void onWrite(BLECharacteristic *pCharacteristic)
std::string value = pCharacteristic->getValue();
if (value.length() > 0)
Serial.println("*********");
Serial.print("New value: ");
for (int i = 0; i < value.length(); i++)
Serial.print(value[i]);
Serial.println();
Serial.println("*********");
;
void setup()
Serial.begin(115200);
BLEDevice::init("MyESP32");
BLEServer *pServer = BLEDevice::createServer();
BLEService *pService = pServer->createService(SERVICE_UUID);
BLECharacteristic *pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE
);
pCharacteristic->setCallbacks(new MyCallbacks());
pCharacteristic->setValue("Hello World");
pService->start();
BLEAdvertising *pAdvertising = pServer->getAdvertising();
pAdvertising->start();
void loop()
// put your main code here, to run repeatedly:
delay(2000);
Android Studio 代码(接收源代码片段):
try
while(sampleBluetoothData)
this.selectedDevice.readCharacteristic(MainActivity.characteristicUUID, MainActivity.serviceUUID, (response, data) ->
if (response != BlueteethResponse.NO_ERROR)
return;
Log.d("AUSGANG", new String(data) + "times: "+ i);
i++;
);
catch (Exception e)
e.printStackTrace();
ESP32 端的写入是 Arduino IDE 的空白示例代码,Android 端的读取由 BLE-Library 发布者进行。是的,Log.d 会影响性能,但不会降低太多。
Android代码的变量“data”是接收到的char-array。蓝牙读取在后台线程上运行。
我现在问自己的问题:
问题是 Android-Studio 库还是 Arduino 库 这是一种正常行为吗,如果特征值没有改变,它的传输速度会很慢。 更新特征值的速度有多快提前致谢!
【问题讨论】:
您应该使用特征通知而不是特征读取。 【参考方案1】:BLE 绝对可以每秒传输超过 4 个 11 字节的部分。
阅读方法:
-
一般来说,一直持续读取并不是 BLE 的预期方式 - 最好订阅数据更改,因此 ESP32 只会在需要时通知(例如,执行一次
selectedDevice.subscribeToCharacteristic
,而不是循环读取,然后是 ESP32代码应相应更改)
我猜selectedDevice.readCharacteristic
请求异步BLE 读取,当您在while(sampleBluetoothData)
中调用它时,您的蓝牙库正在添加越来越多的读取请求。也许明智的做法是在前一次读取完成后才请求新的读取 - 在读取回调中添加 if(sampleBluetoothData) this.readAgain();
考虑从这个 kickstart 示例制作一个测试原型:BLEProof on github - Android 和 ESP32,读取、写入、通知(但它只使用系统 API 没有蓝牙库,你的方法更好,它是使用该库更容易、更安全)。
还有什么要检查的:
-
Android 端:您确定您的代码没有进入
if (response != BlueteethResponse.NO_ERROR)
内部吗?
Android 端:为确保蓝牙库不会因读取请求而过载,请尝试在读取循环中添加 50 毫秒的延迟(只是为了检查,这不是解决方案)
Android 端:您确定在读取这些数据时没有其他 BLE 读/写操作吗?
ESP32 端:使用更短的 BLE 连接间隔 (BLE throughput article) - 在 pAdvertising->start();
之前添加 pAdvertising->setMinPreferred(0x06);
和 pAdvertising->setMaxPreferred(0x20);
(但这仅设置“首选”间隔,Android 可能会忽略它)
【讨论】:
感谢您的详细解答!好像我使用的是旧的库版本,在这个版本(2.0)上订阅是不可能的。我更新到4.0版本,现在可以了。【参考方案2】:使用读取请求,您主要受限于传输速度的连接间隔 - 即请求 + 响应的 2 个间隔。
例如,如果您的客户端的连接间隔为 50 毫秒,那么您应该期望每秒 10 次读取最多 20 个字节的特征。
如果另一个客户端的连接间隔为 30 毫秒,则此速率提高到每秒 16.6 次读取。
最快的可协商连接间隔为 7.5 毫秒,每秒最多读取 66.6 次(读取 20 字节时为 10.7kbps)。
【讨论】:
【参考方案3】:我正在阅读 BLE ***页面,最低数据速率为 125Kbit/s ,所以我认为在你的情况下是可行的,因为你只会传输 16Kbit/s。看看BLE wikipedia。
【讨论】:
以上是关于低功耗蓝牙(ESP32 和 Android 智能手机之间):数据传输很慢的主要内容,如果未能解决你的问题,请参考以下文章
arduino ESP32 AndroidStudio BLE低功耗蓝牙 物联网
arduino ESP32 AndroidStudio BLE低功耗蓝牙 物联网