• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Пример: bluedroid gatts_table_creat_demo отправляет пакеты с задержками.

SAD_sim

New member
Здраствуйте.
Я использую пример gatts_table_creat_demo esp-idf-v5.3.1.
Минимальное количество изменений. В основном цикле он должен отправлять пакеты каждые 19 мс.

while (1) {
esp_ble_gatts_send_indicate(ESP_GATTS_temp, param_write_conn_id_temp, heart_rate_handle_table[IDX_CHAR_VAL_A], size of(esp_ble_buffer), esp_ble_buffer, false);
vTaskDelay(19/ portTICK_PERIOD_MS);
}

Но данные поступают с разными задержками. Получается после команды esp_ble_gatts_send_indicate проходит разное время до отправки самого пакета.


Со стороны принимающей стороны посчитали задержку (время) между пакетами (мс).: 23, 31, 6, 22, 30, 5, 25, 33, 8, 22, 31, 7, 29, 21, 32, 10, 19, 5, 24, 30, 13, 50, 15, 14, 13, 20, 6, 18

Насколько я понимаю, esp_ble_gatts_send_indicated загружает данные в буфер, из которого они отправляются. Но я не могу понять, как сделать так, чтобы эти данные отправлялись немедленно? Или с минимальной задержкой.
 

pvvx

Активный участник сообщества
БLE соединение имеет свой интервал передачи-приема. Приемная сторона включает приемник и передатчик только на малое окно через каждый согласованный при соединении "период соединения". Это требуется для работы с несколькими BLE соединениями одновременно.
Обновление (передача) данных происходит только в эти интервалы.
Если они не кратны вашим вызовам esp_ble_gatts_send_indicated(), то соответственно будет разный период между приемом на другой стороне.
И передача у вас с флагом без подтверждения приема...
 

SAD_sim

New member
БLE соединение имеет свой интервал передачи-приема. Приемная сторона включает приемник и передатчик только на малое окно через каждый согласованный при соединении "период соединения". Это требуется для работы с несколькими BLE соединениями одновременно.
Обновление (передача) данных происходит только в эти интервалы.
Если они не кратны вашим вызовам esp_ble_gatts_send_indicated(), то соответственно будет разный период между приемом на другой стороне.
И передача у вас с флагом без подтверждения приема...
С МК nRF52810 таких проблем нет. Получение пакетов приближено к времени их отправки в коде. Передача с флагом без подтверждения приема, дает возможность отправляющей стороне отправлять следующие пакты сразу без задержки ожидания ответа от принимающей стороны, а принимающая сторона работает только в режиме приемника...
Если есть согласованный при соединении "период соединения", как его изменить? И к этому периоду привязать отправку (вызов esp_ble_gatts_send_indicated() )?
 

pvvx

Активный участник сообщества
> С МК nRF52810 таких проблем нет.

Значит там устанавливается другой интервал соединения...


У устройства параметры соединения прописываются и читаются в специальном UUID.
Но клиент, при соединении обычно лезет со своими параметрами соединения - как ему вздумается. Далее, обычно, устройство передает запрос на изменение параметров соединения на необходимые. Клиент соглашается, если нет - можно долго подбирать на что он будет соглаcен, но проще послать (разорвать соединение - нафиг такие клиенты не нужны, т.к. если не согласен - значит выжрет батарейку....).
При соединении для некоторых функций можно менять параметры соединения....

Обратите внимание на параметр cоединения, называемый "latency".
 

pvvx

Активный участник сообщества
Клиент - это Master в Bluetooth/BLE.
Устройство - это Slave в Bluetooth/BLE.
А у ESP всё по своему. Но фиг с ними.

При работе с BLE на ESP не забывайте отключить все отладочные сообщения в UART. Вообще лучше не пользоваться UART. Скорость вывода сообщений во много раз больше тайминга в BLE.
Так же не рекомендуется использовать всяческие "string". Ну и прочие команды C++ связанные с запросом памяти из "Heap".
Если это не учли - тогда получите дикие задержки в передаче и кучи дублирований приемо-передач.
ESP и так тормоз ещё тот, т.к. доступ программе из к SPI-Flash ограничен примерно 25 мегабайтами в сек и если код программы большой (а он всегда в ESP раздут), то КЭШ не хватает и CPU работает с постоянной выборкой программы и данных из Flash. А это уровень производительности аналогичный ARM Cortex M0 на 16 МГц.
 

pvvx

Активный участник сообщества
Возможно вы столкнулись с этим:
ESP32 не может успешно обрабатывать BLE в Arduino (и через SDK) на 160 МГц CLK. Даже на 240 МГц подтверждения пакетов задерживаются, что сильно влияет на батареи датчиков.

Пример считывания 50 измерений из истории термометра.
50 измерений передаются в ESP32 за 12 секунд
изображение
(график тока от батареи в мА и msна стороне BLE термометра)

ESP32 не успевает обрабатывать входящие пакеты, и термометру приходится постоянно дублировать передачи, прежде чем получать подтверждения от ESP32.
В данном примере Wi-Fi на ESP32 отключен, чтобы не замедлять BLE еще больше.

TelinkMiFlasher.html через обычный USB-BT адаптер считывает 50 измерений (0,2 сек):
изображение
(график тока от батареи в мА и msна стороне BLE термометра)
 

pvvx

Активный участник сообщества
Из последних попыток сделать что-то более менее работающее в BLE на ESP32-xxx удался только прием BLE рекламы, включая варианты PHY Coded (c доп.либой в ESP-IDF). Всё остальное тормозит и работает неудовлетворительно.

Жду уже более 4-х лет, когда у Espressif выйдет что-то более менее для работы BLE и Zigbee…
 

SAD_sim

New member
Спасибо за ответы, только не удается открыть изображения . Настройки как только не крутил. и 240 МГц тоже. и wi-fi отключал. и уже все подряд, но ноль реакции только хуже)
Единственное что немного улучшает, это:
conn_params.max_int = 0x06; // *1.25ms
conn_params.min_int = 0x06; // *1.25ms
Но меньше нельзя поставить(
Пока докапал что используется семафор buff_semaphore, и возможно очередность его обработки какая-то кривая, но не могу разобраться какая, т.к. похоже он просто как счетчик используется.
И отправка идет из задачи btc_task с небольшим приоритетом #define BTC_TASK_PRIO (BT_TASK_MAX_PRIORITIES - 6) но как только меняю приоритет то БТ перестает работать....
 

pvvx

Активный участник сообщества
> Спасибо за ответы, только не удается открыть изображения .

Дублирую... (видимо копирование своих картинок с github как-то не так проходит):

Пример считывания 50 измерений из истории термометра.
50 измерений передаются в ESP32 за 12 секунд
1739380525271.png
(график тока от батареи в мА и msна стороне BLE термометра)

ESP32 не успевает обрабатывать входящие пакеты, и термометру приходится постоянно дублировать передачи, прежде чем получать подтверждения от ESP32.
В данном примере Wi-Fi на ESP32 отключен, чтобы не замедлять BLE еще больше.

TelinkMiFlasher.html через обычный USB-BT адаптер считывает 50 измерений (0,2 сек):
1739380536331.png

(график тока от батареи в мА и msна стороне BLE термометра)

Единственное что немного улучшает, это:
conn_params.max_int = 0x06; // *1.25ms
conn_params.min_int = 0x06; // *1.25ms
Но меньше нельзя поставить(
7.5 ms - это минимум. НО!
Apple и старые смарты и адаптеры BT могут не потянуть такие интервалы.
Apple на всё имеет свои стандарты с более жесткими ограничениями пользователей во всём и там вроде минимум 12 ms (точно не помню - уточняйте в Apple нормативах), а рекомендуемые ещё больше.
 

pvvx

Активный участник сообщества
Передача данных при BLE соединении аналогична USB.

Примерно так (упрощенно): В USB мастер опрашивает устройство с фиксированным интервалом (USB2.0 - 1 ms). Если у устройства есть данные, то передается первый блок данных. Но, по концу приема блока мастер опять опрашивает устройство на доп. данные и если они есть то передается следующий блок. Если устройство не успело подготовить новый блок по концу передачи предыдущего, то на этом мастер прерывает опрос до следующего интервала. Таким образом, за один интервал происходит несколько транзакций, пока устройство успевает подготавливать новые блоки.
 

pvvx

Активный участник сообщества
Время после передачи на опрос, что есть ещё данные в BLE - пара сотня мкс. Т.е. они должны быть уже в очереди передачи до конца передачи предыдущего блока.
А ESP тормоз и не успевает производить анализ ответа-подтверждений мастера после передачи блока и подсунуть новый блок в эту сотню мкс...
 

pvvx

Активный участник сообщества
В этом бардаке участвует и значение MTU и параметр соединения “latency”.
"latency" указывает, сколько интервалов соединения может пропустить устройство (не выходить на связь), но мастер всё равно должен включать приемник на каждое окно интервала соединения для приема от устройства... Это делается для экономии энергии у устройства.
Смотрите схемы, как происходят передачи в BLE при разных MTU и как влияет параметр соединения “latency”. Благо таких статей в инет куча…
 

pvvx

Активный участник сообщества
1739383929040.png

На данной картинке и показано, что интервал соединения = 20 ms, а "latency" = 124. Т.е., если нет нужды в передачах, то устройство пропускает 125 интервалов (2.5 сек).
Но когда происходи запрос устройству на чтение данных (на графике это 5000 ms), то устройство меняет latency на 0 и согласует - уточняет заголовки на передачу данных каждые 20 ms, а затем передает сами данные (50 блоков) уже непрерывно на пределе скорости PHY и обмена подтверждений каждого мелкого блока (там BT4.2 - это по 20 байт данных, ATT_MTU_SIZE = 23).
В случае с ESP это нереально - ESP не успевает подтверждать блоки и вообще теряет-нарушает тайминги BLE...
 

pvvx

Активный участник сообщества
И вы видели кучу процедур разбора принятых блоков в ESP-IDF. Пока они отработают в ESP, устройство уже десятки раз передаст повторно этот блок, т.к. RF подтверждения приемо-передачи не было. И так на каждый блок, в итоге каждый блок устройство дублируется более 50 раз. Это как разговор с глухим и тупым - надо орать несколько раз, пока не получите подтверждения.

На передающей части (если передает ESP) ситуация аналогична.
А при работе ещё и WiFi - там вообще полная лажа.
Да и куда девать сотни килобайт принятых в секунду данных в ESP? В MQTT с ожиданием ответа сервера на каждый принятый десяток байт по BLE? :) :)
 

pvvx

Активный участник сообщества
Передача с флагом без подтверждения приема, дает возможность отправляющей стороне отправлять следующие пакты сразу без задержки ожидания ответа от принимающей стороны, а принимающая сторона работает только в режиме приемника...
Это относится только к софт подтверждению - получите специальный фрейм о приеме в какой callback() или стек BLE. Но никак не относится к RF подтверждению приема.
 

pvvx

Активный участник сообщества
С МК nRF52810 таких проблем нет.
Но у него производительность RF и ПО в сотни раз больше при в десять раз меньшей тактовой частоте CPU, чем у ПО от "программеров" в ESP-IDF и двух ядер ESP32 на 240 MHz. :)
Для полноценного обслуживания BLE в BT5.2 (PHY 2M) сверх достаточно Cortex M0 на 16 МГц с выборкой кода из SPI-Flash на 40 MHz CLK и кэшем в 500 байт.
 

pvvx

Активный участник сообщества
C ESP32-xxx в BLE/Zigbee вообще многое не ясно.

К примеру, какие задержки у RF для обслуживания ALC/ ALC2.

Для nRF52840 они указаны в PDF:
Время между задачей RXEN и событием READY после настройки частоты канала (1 Мбит/с BLE с быстрым нарастанием) - 40 мкс.
Время между задачей TXEN и событием READY после настройки частоты канала (1 Мбит/с BLE с быстрым нарастанием и 150 мкс TIFS) – 40 мкс.


Что говорит о том, что после передачи приемник будет готов для приема даже на другом канале уже через 40 мкс.
 

pvvx

Активный участник сообщества
Если считать, что ESP принимает данные от BLE устройства и передает их по MQTT, тогда:

Пусть на передачу пакета в 20 байт в среднем по BLE уходит 1 мс.

ESP переводит данные пакета в string для MQTT (расширяет в сотню байт в Json) и отправляет.
Ответ от сервера по WiFi-TCP при местной связи приходит через пару мс, если уже передачи согласованы поcле beacon от AP WiFi. Beacon в WiFi следуеn каждые 102.4 мс. Если не согласованы или AP WiFi занята более приоритетными клиентами, то ответ от MQTT получим через сотни мс, иногда и более 1 секунды...

За это время по BLE приходит новый пакет, но антенна занята WiFi. Это требует устройству BLE дублировать передачу пока ESP не соизволит ответить...

Если будем буферизировать данные json – тогда за секунду накопится 1000 фреймов в Json по не менее сотне байт – это более 100 килобайт с учетом индексации. И ESP потребуется совершить 1000 транзакций по WiFi-TCP с MQTT сервером…

Т.е. это просто нереально, даже если вы всё напишите на ASM для ESP32.
Но такое пишут все Ардуинщики на ESP и при этом в C++ :)
 

pvvx

Активный участник сообщества
При приеме BLE рекламы (маков), скорость их поступления достигает 3 мс (с учетом приема каждого по 3-м каналам). В итоге необходимо успевать сливать каждый во вне за 3 мс. Сливаемые данные маяка около 40 байт (raw) на маяк, если не переводить в ASCII и не создавать большого заголовка для фреймовой синхронизации. В итоге нужен канал слива не менее 333*40=13320 байт в сек. Для этого успешно подходит USB. Это максимум что можно выжать из ESP32-xxx. На большее ESP32-xx на сегодня в BLE не годится. Дешифрировать принятые маяки ESP уже некогда.
 

pvvx

Активный участник сообщества
Учитывая, что BLE разрабатывался и разрабатывается для простых и маломощных CPU ядер, то в нем очень редко используются числа с плавающей точкой. Только целочисленные мат. операции. Иначе CPU не имеющие FPU будут не успевать работать с BLE таймингами.

А в Arduino, помимо плавающей точки используются С++ strings и другие команды запрашивающие Heap. Это очень медленные операции (аж с запретом всех прерываний) и не годятся для обслуживания BLE таймингов.

Мигать светодиодом раз в час – это участь Arduino и ESP-IDF на простых MCU/SoC.
 
Сверху Снизу