• Уважаемые посетители сайта esp8266.ru!
    Мы отказались от размещения рекламы на страницах форума для большего комфорта пользователей.
    Вы можете оказать посильную поддержку администрации форума. Данные средства пойдут на оплату услуг облачных провайдеров для сайта esp8266.ru
  • Система автоматизации с открытым исходным кодом на базе 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.
 
Сверху Снизу