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

Обмен между двумя модулями по BLE

nikolz

Well-known member
Добрый день,
Вопрос к знатокам.
Задача:
Есть два модуля, расстояние между которыми не более 5 метров.
Необходимо передавать непрерывно с одного на другой модуль короткое сообщение , не более 32 байт (сейчас это 4 байта)
Задержка передачи данных желательно не более 1 ms ( терпимо до 10 ms)
---------------
Хотел бы реализовать это на SOC с BLE, например TLSR8266.
Предположительно, один модуль работает в режиме рекламы.
Не знаю как сделать , если возможно,
чтобы другой принимал эти пакеты без сканирования,
так как мас адрес первого заранее известен.
Желательно пример или ссылку на решение.
-----------
Интересны любые другие варианты.
 

pvvx

Активный участник сообщества
Для этого существует BLE соединение.
Нет смысла забивать эфир основных каналов пакетами с периодами в несколько мс.
При соединении устройства будут работать на каналах, на которых меньше помех (с автоматическим выбором).
Минимальный шаг-период связи у BLE соединения 7.5 мс, если используются малые пакеты (малый MTU). Иначе фрейм передается подряд несколькими пакетами, но старт пачки всегда с периодом (конкретнее - стробом) 7.5 мс.

Задержка передачи не может быть 1 мс, т.к. BLE реклама передается на 3-х каналах последовательно с паузами от 500 мкс на прием запроса соединения или расширенной рекламы. И даже короткий RF-фрейм у PHY 1M стремится к 1 мс.
В итоге - 3 мс минимум. Плюс тупость приемной стороны. В итоге, по практике, от события до отработки внешнего устройства выльется в 5..7 мс при условии, что вы полноценно освоили BLE и программирование.
На WiFi или проводном интернет итог задержки всегда больше.
 

pvvx

Активный участник сообщества
Есть такой протокол Enhanced ShockBurst (ESB). В народе - RF24.
У TLSR есть примеры типа ESB_demo. Но там придется покопаться...
На ESP c nRF24L01 предел 150 транзакций в сек, как не оптимизируй имеющиеся в инете исходники. На TLSR - тысяча. Исходники не дам - лень чистить.
 

pvvx

Активный участник сообщества
Что-то подобное c либой libesb_ll.a от Telink...
Часть инициализации:
C:
    //rf configuration
    ESB_SetDatarate(ESB_DR_2M);
    ESB_SetOutputPower(ESB_RF_POWER_0DBM);
    ESB_SetAddressWidth(ADDRESS_WIDTH_5BYTES);
    ESB_ClosePipe(ESB_PIPE_ALL);

    unsigned char rx_address[5] = { 0xe7, 0xe7, 0xe7, 0xe7, 0xe7 };
#if (RF_RX_TX == RF_TX)
    ESB_SetAddress(ESB_PIPE0, rx_address);
    ESB_OpenPipe(ESB_PIPE0, 1);
    ESB_SetTXPipe(ESB_PIPE0);
    ESB_ModeSet(ESB_MODE_PTX);
#else
    ESB_SetAddress(ESB_PIPE0, rx_address);
    ESB_OpenPipe(ESB_PIPE0, 1);
    ESB_ModeSet(ESB_MODE_PRX);
#endif

    ESB_SetRFChannel(chn);
    ESB_SetAutoRetry(2, 150); //5,150
    ESB_RxTimeoutSet(500); // 500 us
    ESB_RxSettleSet(80); // 80 us
    ESB_TxSettleSet(149); // 149 us

    ESB_EnableDynamicPayload(1);

    irq_clr_src();
    rf_irq_clr_src(FLD_RF_IRQ_ALL);
    //enable irq
    irq_enable_type(FLD_IRQ_ZB_RT_EN); //enable RF irq
    rf_irq_disable(FLD_RF_IRQ_ALL);
    rf_irq_enable(FLD_RF_IRQ_TX | FLD_RF_IRQ_TX_DS | FLD_RF_IRQ_RX_DR | FLD_RF_IRQ_RETRY_HIT | FLD_RF_IRQ_INVALID_PID);
    irq_enable(); //enable general irq
У Telink cуществует несколько реализаций...
Смотреть всякие RF_Demo...
C:
void main_loop (void) {
        if(rf_is_rx_finish())
        {
#if (RF_MODE==RF_ANT)
            if(rf_is_rx_finish() && if(rf_is_rx_right()))
#elif ((RF_MODE==RF_BLE_2M)||(RF_MODE==RF_BLE_1M)||(RF_MODE==RF_BLE_1M_NO_PN)||(RF_MODE==RF_LR_S8_125K)||(RF_MODE==RF_LR_S2_500K))
            if(RF_BLE_PACKET_CRC_OK(rx_packet)&&RF_BLE_PACKET_LENGTH_OK(rx_packet))
#elif (RF_MODE==RF_ZIGBEE_250K)
            if(RF_ZIGBEE_PACKET_CRC_OK(rx_packet)&&RF_ZIGBEE_PACKET_LENGTH_OK(rx_packet))
#elif ((RF_MODE==RF_PRIVATE_2M)||(RF_MODE==RF_PRIVATE_1M)||(RF_MODE==RF_PRIVATE_500K)||(RF_MODE==RF_PRIVATE_250K))
 #if(PRI_MODE == ESB_MODE)
            if(RF_NRF_ESB_PACKET_CRC_OK(rx_packet)&&RF_NRF_ESB_PACKET_LENGTH_OK(rx_packet))
 #elif(PRI_MODE == SB_MODE)
            if(RF_NRF_SB_PACKET_CRC_OK(rx_packet))
 #endif
#endif // RF_PRIVATE
// debug UART 2Mbit/s
            {
                uart_send_rxpkt();
                rx_cnt++;
            }
            rf_rx_finish_clear_flag();
            rf_set_tx_rx_off_auto_mode();
        }
 

pvvx

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

Это текущей прошивке для всех термометров и т.д.

Если прием ведется на устройстве типа AdScanerTrg https://github.com/pvvx/AdScanerTrg , тогда время между нажатием кнопки или срабатыванием геркона и сигналом на выходе GPIO у приемника равно 4..7 мс.

Если в цепи участвует какой “Вумный дом” без Cloud, то период срабатывания еле-еле укладывается в “санитарные” нормы.
1728752924429.png
В итоге необходимо дублировать нажатие кнопки дополнительным индикатором, т.к. за время, когда произойдет отработка наглядным действием нормальный человек уже успеет продумать несколько вариантов типа – что-то не работает, плохо нажал кнопку, программу писал Ардуинщик – необходимо контролировать срабатывание, может взять молоток и стукнуть того Ардуинщика, ...
 

nikolz

Well-known member
Благодарю за подробный ответ.
Буду изучать примеры.
-----------------
Вариант с NRF24 рассматривал как запасной. Но хотел его повесить на TLSR.
-------------------------
Важно обеспечить минимальное потребление, вес и размеры передающей части,
Источник питания CR2032 или даже LIR2032.
Время непрерывной работы не менее 16 часов.
Частота дискретизации желательно не менее 100 Гц.
Передающее устройство самое простое - читает данные с датчика и отсылает их.
Сейчас 1 датчик и данных всего 4..8 байт, потом это 3 датчика и данных уже 32 байта.
----------------
Еще вариант взять какой-нибудь SoC без радио и добавить NRF24.
 

pvvx

Активный участник сообщества
Описал же - nRF24 в связке с ESP значительно медленнее - макс 150 транзакций в сек. Такова скорость интерфейса к nRF24L01x у всех ESP. Выше не разгоняется.
ESB(народное RF24) на TLSR дает уже около тысячи транзакций в сек.
Так же есть ещё FSK.
Оба они ESB и FSK используются для мышей и т.д. Все виды работают на TLSR чипах и у Telink есть примеры и либы .
 

pvvx

Активный участник сообщества
И nRF24L01x жрет дофига (пики более 20 мА (по памяти)).

На TLSR при 1000 транзакций (TX+0дБм)в сек у вас выйдет среднее потребление 6..8 мА.
 

nikolz

Well-known member
И nRF24L01x жрет дофига (пики более 20 мА (по памяти)).

На TLSR при 1000 транзакций (TX+0дБм)в сек у вас выйдет среднее потребление 6..8 мА.
Спасибо,
К сожалению, пока не нашел примеров ESB и указанной Вами либ для TLSR82xx
------------------
По-моему, FSK -это способ модуляции, а ESB - это протокол передачи данных. Верно?
-----------------------
относительно ESB у NRF...
Это сказано в документации:
В устройствах серий nRF51 и nRF24L реализована аппаратная задержка в 130 мкс.
Если соединение ESB устанавливается только между устройствами серий nRF52 и/или nRF53, эту задержку можно сократить до 40 мкс.
Если значение параметра use_fast_ramp_up равно true, включается быстрый разгон, что приводит к уменьшению задержки разгона на 40 мкс.
Если вам нужно свести к минимуму задержку между заполнением TX FIFO и приёмом, включения быстрого запуска может быть недостаточно.
В этом случае вы можете использовать опцию CONFIG_ESB_NEVER_DISABLE_TX Kconfig. Она изменяет поведение драйвера ESB. Если пакет не был подтверждён, периферийное радиоустройство остаётся в состоянии TXIDLE, а не TXDISABLE, когда передача ожидает подтверждения. Использование этой экспериментальной функции может сократить задержку передачи до 100 мкс для 32-битной (четырёхбайтовой) полезной нагрузки.
--------------------
Если я правильно понял, то в этом случае интервал передачи равен 0.1ms + длительность посылки. В итоге будет меньше 1 ms. Верно?
----------------
про потребление NRF24L01x
в документации сказано:
7 mA при мощности -18dBm и 11.3 mA при мощности 0dBm
У меня расстояние не более 2 метров. Возможно хватит и -18dBm т е 7 mA.
------------------
Но постараюсь сделать все на TLSR.
 

pvvx

Активный участник сообщества
Уже описывал где-то подробно, а тут только вывод:
На ESP + NRF24L01x не выходит более 150 транзакций в секунду на либах из интернета даже при некоторой оптимизации. В Arduino вариантах вообще...
К чипу интерфейс SPI, а задержки обращения к SPI у ESP8266/ESP32 громадные... Тем более если использовать стандартные функции из SDK - при SPI они грохают "кеш" проца и он работает со скоростью поступления команд и данных из SPI-FLash. А это 25Мегабайт в сек - т.е. менее 10 М команд (если считать что они в среднем 20 бит). Т.е. не шибче 10MHz какого древнего STM32...
Этой производительности уже не хватает на работу RTOS и WiFi.
 

pvvx

Активный участник сообщества
про потребление NRF24L01x
в документации сказано:
7 mA при мощности -18dBm и 11.3 mA при мощности 0dBm
У меня расстояние не более 2 метров. Возможно хватит и -18dBm т е 7 mA.
Это наверно из даташита nRF -> необходимо читать всё и что писано мелким шрифтом и заковыристо.
Но проще тестером - будет за 20 мА и более. Проверено на разных NRF24L01 и каких-то новых, якобы оптимизированных...
Т.е. CR2032 при 50..60% уже не даст такой ток (будет падать ниже 2.0В).
 

pvvx

Активный участник сообщества
С FSK я не разбирался - есть какой-то "FSK_Demo" от Telink.
Там пачка демок:
\FSK_Demo\gen_fsk_rx
\FSK_Demo\gen_fsk_srx
\FSK_Demo\gen_fsk_srx2tx
\FSK_Demo\gen_fsk_stx
\FSK_Demo\gen_fsk_stx_dpl_packet
\FSK_Demo\gen_fsk_stx2rx
\FSK_Demo\gen_fsk_tx
\FSK_Demo\src

По конфигурации-инициализации не сказать, что это только модуляция...
C:
    //generic FSK Link Layer configuratioin
    gen_fsk_datarate_set(GEN_FSK_DATARATE_2MBPS); //Note that this API must be invoked first before all other APIs
    gen_fsk_preamble_len_set(4);
    gen_fsk_sync_word_len_set(SYNC_WORD_LEN_4BYTE);
    gen_fsk_sync_word_set(GEN_FSK_PIPE0, sync_word); //set pipe0's sync word
    gen_fsk_pipe_open(GEN_FSK_PIPE0); //enable pipe0's reception
    gen_fsk_tx_pipe_set(GEN_FSK_PIPE0); //set pipe0 as the TX pipe
    gen_fsk_packet_format_set(GEN_FSK_PACKET_FORMAT_FIXED_PAYLOAD, sizeof(tx_payload));
    gen_fsk_radio_power_set(GEN_FSK_RADIO_POWER_0DBM);
    gen_fsk_channel_set(7); //set rf freq as 2403.5MHz
    gen_fsk_radio_state_set(GEN_FSK_STATE_TX); //set transceiver to basic TX state
    gen_fsk_tx_settle_set(149);
    WaitUs(130); //wait for tx settle
 

nikolz

Well-known member
Благодарю.
----------------
В доке сказано, что эта версия SDK поддерживает чипы TLSR8208 (B80) (A1 / A4), версии TLSR8208 B (B80B) (A0 / A1), B85, B87.
-----------
Подойдет ли для 826x?
 

nikolz

Well-known member
pvvx,
Решил для начала сделать на протоколе BLE.
------------------------------
Проясните, плиз, следующее:
-----------------
Если правильно понял, то
1) Первый модуль с датчиком посылает циклически рекламу, потом ждет запрос от второго модуля.
Если запрос есть то переходит в режим slave, отсылает данные по запросу и возвращается в режим рекламы.
Вопрос:
Возможно ли, чтобы это устройство не переходило в режим рекламы из slave, а возвращалось в режим ожидания запроса от второго модуля?
Т е реклама посылается лишь для обнаружения мастером этого устройства.
Потом делается лишь отправка данных по запросам мастера.
-------------------
2) Второй модуль сканирует , принимает рекламу и посылает запрос, потом переходит в режим мастера, принимает данные и завершает обмен возвращается в режим сканирования. Снова соединяется и переходит в режим мастера и т д в цикле.
Вопрос:
Возможно ли , что бы второй модуль не сканировал рекламу,
а посылал запрос на соединение по мак.адресу по умолчанию.
----------------------
Если желаемое возможно, то набросайте пример или дайте ссылку.
 

pvvx

Активный участник сообщества
Ваш сленг в BLE не понять.
Для BLE вам надо два проекта - один master, другой slave которые будут производить сonnect.
При включении один шлет BLE рекламу (к примеру с шагом 100 мс), второй сразу её ловит, т.к. по старту находится в режиме сканирования.
Выловив самую первую BLE рекламу мастер посылается запрос на соединение. И через несколько мс (не более шага посылки рекламы) оба уже в режиме соединения.
Мастер обычно сканирует всю таблицу UUID, если это первое соединение. При повторе соединения, по спецификации BLE, он должен помнить таблицу того к которому уже подключался и интервалы соединения описанные в ней.
Обычно тот, к которому присоединились должен дать мастеру команду смены интервалов соединения на более мелкие. Мастер подтверждает и переключает интервалы. Интервалы соединения по умолчанию описаны в специальном UUID у slave - но ардуино-поколение не читает спецификаций. И бездари программеры в Windows и особенно в Linux обычно сильно ленивы и тоже не читали спецификаций и каждый раз производят полное чтение таблиц UUID, начинают соединение со своими любимыми интервалами и производят весь комплекс согласований по новому, убивая время пользователя...
Но вам вообще не нужно читать таблицу UUID и согласовывать интервалы соединения, т.к. вы знаете, что для этого MAC вам нужен конкретный UUID и его крос-номер известен в исходниках, как и интервалы соединения.
В таком варианте соединение происходит молниеносно.
 

pvvx

Активный участник сообщества
И если всё сделали правильно, то после соединения при PHY 1M и минимальном интервале соединения имеете двусторонний поток за 100 килобайт в сек. Для PHY 2M примерно в два раза больше...
При потере связи (интервал таймаута описывается в интервалах соединения), соединение возобновится по прошествии этого таймаута + до одного периода рекламы.
Но для потери связи ещё надо постараться - включить какую глушилку на все каналы BLE.
 

nikolz

Well-known member
И если всё сделали правильно, то после соединения при PHY 1M и минимальном интервале соединения имеете двусторонний поток за 100 килобайт в сек. Для PHY 2M примерно в два раза больше...
При потере связи (интервал таймаута описывается в интервалах соединения), соединение возобновится по прошествии этого таймаута + до одного периода рекламы.
Но для потери связи ещё надо постараться - включить какую глушилку на все каналы BLE.
Благодарю за ответ.
--------------
Мне непонятен такой момент.
----------------
В документации TLSR прочитал, что если не разрывать соединение, то BLE автомат блокирует прерывания, чтобы не нарушать синхронизацию. Получается, что необходимо на каждый отсчет датчика устанавливать соединение передавать 4 байта принимать подтверждение и разрывать соединение. Все верно?
---------------------
Кроме того, существует аппаратная задержка 130 мкс, которая указана в NRF (с чего копировали TLSR) В данном случае будет два переключения что даст примерно 300 мкс задержки. Все верно?
--------------------
Пока мне непонятно какими функциями и в какой последовательности заставить автомат BLE slave не включать рекламу а переходить в режим ожидания запроса от мастера после разрыва соединения, а мастера заставить переходить в режим запроса соединения после завершения соединения, без перехода в режим сканирования.
--------------------
100 килобайт в секунду это хорошо.
У меня есть две задачи. В одной можно передавать блоками в другой нельзя.
Сейчас я решаю вторую, в которой я не могу накапливать данные для передачи,
так как задержка приема данных вторым модулем должна быть минимальной.
Т е второй модуль должен обрабатывать каждое значение от первого до прихода нового отсчета с датчика,
либо просто пропускать необработанные в реальном времени данные.
 

pvvx

Активный участник сообщества
В документации TLSR прочитал, что если не разрывать соединение, то BLE автомат блокирует прерывания, чтобы не нарушать синхронизацию. Получается, что необходимо на каждый отсчет датчика устанавливать соединение передавать 4 байта принимать подтверждение и разрывать соединение. Все верно?
Нет.
Но можно действовать и как описали. Но тогда между каждым соединением пройдет n-секунд.

Кроме того, существует аппаратная задержка 130 мкс, которая указана в NRF (с чего копировали TLSR) В данном случае будет два переключения что даст примерно 300 мкс задержки. Все верно?
Про какую "задержку" идет речь?

В EBS передатчик передает фрейм. Приемник принимает и тут-же передает подтверждение.
Где задержка?
У передатчика есть тайм-аут ожидания приема подтверждения. Но это не "задержка", а тайм-аут ожидания подтверждения передачи для повтора передачи.
Этот тайм-аут должен быть рассчитан на максимальное расстояние связи (скорость электромагнитной волны конечна) + аппаратное время переключения прием-передача (= пару мкс).

Всё остальное в исходниках "Demo"- это для Ардуинщиков - типа для примера и отладки.

---
Комментировать как работает BLE и какие функции есть в SDK Telink не вижу смысла. На то у них есть открытая для всех документация.
 

pvvx

Активный участник сообщества
Тайм-аут в ESB вставляют по причине того, что используют кривое ПО и устаревшее низкоскоростное аппаратное оборудование, типа ESP. Там после приема сообщения уходят миллисекунды на то, чтобы переключить приемник на передачу подтверждения.
Ардуинщики обычно создают дополнительную задержку, т.к. приучены писать программы неверно и использовать отсебятенные алгоритмы, вместо чтения спецификации.
У приемника фрейм ответа (подтверждения) должен быть заготовлен заранее, т.к. в ESB и прочих протоколах (BLE, Zigbee, WiFi, ...) используется аппаратная функция rx-tx или tx-rx в радио части чипа. Т.е. на ходу, после приема создавать ответ и подготавливать периферийные устройства чипа (DMA и прочие настройки RF части) на передачу ответа нет времени. Принимающий должен ответить сразу после приема, через аппаратный промежуток переключения RF части с приема на передачу. А у современных чипов это пара мкс.
Аналогично работает и USB.
 
Сверху Снизу