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

Делюсь опытом Super fast WIFI UDP

nikolz

Well-known member
Немного истории.
---------------------
Прошло четыре года с тех пор ,
как я выложил свои результаты исследований энергопотребления ESP8266 на основе SDK.
--------------------
В ту пору общепринятым было время выхода из режима deep-sleep
и передача сообщения порядка 4 секунд.
Но у меня получилось время выхода из режима deep-sleep
и передача сообщения по UDP порядка 0.3 секунд,
что не удалось получить до настоящего времени никому в интернет.
------------------------------
Тогда гуру pvvx гневно утверждал,
что у меня неисправен роутер и такого быть не может,
так как он достиг в режиме AP 0.54 секунды.
Я не стал спорить о том, что и у кого неисправно.
----------------------------
Но вот прошло четыре года.
В инете достигли минимального времени 1 сек.
Меньшее время достигается либо протоколом ESP-NOW,
либо переделкой софта роутера и использованием служебных пакетов.
Что не является стандартом.
---------------------------
Получить мой результат ,без костылей, со стандартным SDK никто так и не смог.
=====================
Настало время рассказать как это сделать.
------------------------
При выходе из depp-sleep возможны три варианта подключения к WiFi
и передачи сообщений.
--------------------
1) логин и пароль - новые значения.
Время подключения и передачи сообщения UDP 4 секунды.
----------------------

2) логин,пароль и IP сохраняем в RTC.
Время подключения и передачи сообщения UDP 1.2 секунда.
----------------------

3) логин, пароль, IP сохраняем в RTC и отключаем dhcpc.
Время подключения и передачи сообщения UDP 0.3 секунды.
=============
Время рассчитывается с учетом интервала начального старта,
которое составляет в стандартном boot 0.12 секунды.
Если переписать загрузчик rboot, что я сделал,
или использовать RepiadLoader от pvvx, что у меня так и не получилось использовать,
то время можно еще сократить дополнительно на 0.04-0.06 секунды.
Сейчас у меня получается 0.26 секунды.
==================
Теперь вы можете уменьшить время активности своих устройств
и увеличить время работы от батарейки в 3 раза, если у вас вариант 2,
или в 13 раз, если у вас реализован вариант 1.
----------------------
Успехов
 

pvvx

Активный участник сообщества
Немного истории.
---------------------
Прошло четыре года с тех пор ,
как я выложил свои результаты исследований энергопотребления ESP8266 на основе SDK.
--------------------
В ту пору общепринятым было время выхода из режима deep-sleep
и передача сообщения порядка 4 секунд.
Это новая "история"? Ссылочки то можно было дать?
Хотя-бы такие: (RTL 2016 год, стандартный SDK) Скорость подключения модуля к внешней AP
Тогда гуру pvvx гневно утверждал
Что это? Обзывательство?
Я не "гуру". Не приписывайте мне того, чего нет.
что у меня неисправен роутер и такого быть не может,
так как он достиг в режиме AP 0.54 секунды.
Просьба провести тест: Уточнить время выдачи запроса IP (DHCP) роутером после соединения к AP c зависимостями и привести модели роутеров.
В "истории данного сайта" это уже было представлено многими (поищите)... и вывели - если опоздал и не уложился всеми стадиями соединения в один период beacon, то среднее для DHCP около 0.7 сек. Если нет - то десяток мс, но SDK ESP всегда опаздывает и проходит несколько beacon-ов...
Особенно всем хотелось бы видеть полную диаграмму всех шагов WiFi станции при выходе в эфир и присоединении к AP по стандарту, а не малиновых слонов на графике и глюков вашего роутера, считающего что в эфире помехи и ему не достучаться до вашей станции десятками секунд после последнего необъявленного обрыва связи (по вашим описаниям он её ищет вечно - часами, а должен очистить ресурсы для других соединений)... А тут вдруг она опять появилась и орет в эфир, рушит всю синхронизацию сети, сбивая чужие пакеты, ломая распределение участников...
Когда изучите, тогда и пишите :)
Успехов в изучении простых вещей.
 

pvvx

Активный участник сообщества
Я могу вам в десятый раз описать кратко, не внедряясь в дебри 802.1, разбив на глобальные стадии:

1. Включить питание. Дождаться, когда все PLL и аналоговые потроха выдут на стабильный режим работы.
2. Произвести сканирование WiFi эфира. Типов бывает 2 – активный и пассивный.
3. Объявить о выходе в эфир. Есть зависимости от п.п.2.
4. Подправить частоту WiFi по преамбуле beacon той AP, которой будем соединяться или другими методами. Т.е. ждем до периода becon (0.1024 сек по умолчанию или как выставили на AP) и всегда имеем джиттер на синхронизацию со временем следования маяка от AP.
5. Синхронизоваться (уточнить параметры AP) и начать перепалку пакетами с AP для соединения и всяких там согласований о шифрации, паролях и прочим. (если AP не занята другими клиентами, более приоритетной передачей…)
6. Тут уже WiFi транспортный уровень для IP и надо получить IP от роутера.
7. Передавать-принимать IP пакеты (UDP, TCP т.д.). Передача от станции ведется исключая активности во время и на время следования beacon от AP, учитывая арбитраж от AP.
8. Объявить и завершить соединение с AP (или перейти в спящий режим DTIMn, договорившись с AP). Многие автоматом переходят в спящий режим в зависимости от профиля. Их несколько стандартных и все параметры к ним описаны и обычно задаются в SDK (в ESP - нет). Обычно умолчанию, автомат тратит на анализ, что трафика нет пару секунд, включая согласование с переходом в “спящий режим” с AP. ESP в режиме “Modem” – от 10 сек…
9. Если в спящем режиме, то надо проснуться как договорились с AP (после пропуска n beacon)и включить приемник загодя c указанной тут точностью (-25 us для Low-cost ширпотреба) .

  • Время, затрачиваемое дешевыми роутерами на любой стадии зависит от объема их RAM, т.к. в свободной RAM в Linux размещены “кеши”. Если она уже выедена другими задачами, то для дешевых роутеров с 64..128МБ RAM это дает доп. задержки на каждой стадии/задаче к 20 ms. При наличии в “кеш” всего необходимого – пару ms. Даже по этому параметру у вас не видно +- в соединении, а в итоге, если специально не озаботиться, оно достигает нескольких периодов beacon...
 

clinkme

Member
Настало время рассказать как это сделать.
Успехов
Написано много, а полезной информации нет (либо я не смог ее понять).
При выходе из deep-sleep происходит полная инициализация (кроме RTC понятно).
В любом случае при этом надо вызывать
wifi_station_set_config(&conf);
При чем тут RTC? Или Вы хотите сказать, что все задержки связаны с чтением этой conf из flash?
C таким же успехом конфигурацию можно просто в коде забить константами, тогда это еще быстрей будет (поскольку она окажется в RAM).
 

nikolz

Well-known member
Написано много, а полезной информации нет (либо я не смог ее понять).
При выходе из deep-sleep происходит полная инициализация (кроме RTC понятно).
В любом случае при этом надо вызывать
wifi_station_set_config(&conf);
При чем тут RTC? Или Вы хотите сказать, что все задержки связаны с чтением этой conf из flash?
C таким же успехом конфигурацию можно просто в коде забить константами, тогда это еще быстрей будет (поскольку она окажется в RAM).
Я рассказал свой результат и объяснил Вам как смог.
У меня вообще нет проблем, тем более что Вы не поняли.
----------------------------
можете сделать быстрее, расскажите результат, а не свои фантазии.
это будет ваш опыт.
 

clinkme

Member
Я рассказал свой результат и объяснил Вам как смог.
У меня вообще нет проблем, тем более что Вы не поняли.
----------------------------
можете сделать быстрее, расскажите результат, а не свои фантазии.
это будет ваш опыт.
Когда человек делится своми достижениями, целью все-таки должно являться
донести информацию и обеспечить возможность их повторения другими (и как сверхзадача - превзойти их). Так устроена цивилизация.
Если задача - просто прокричать, что вы все м., а я весь в белом - тогда да...
Можете хотя-бы псевдо-кодом расписать ваши операции при выходе из deep sleep?
 

nikolz

Well-known member
Когда человек делится своми достижениями, целью все-таки должно являться
донести информацию и обеспечить возможность их повторения другими (и как сверхзадача - превзойти их). Так устроена цивилизация.
Если задача - просто прокричать, что вы все м., а я весь в белом - тогда да...
Можете хотя-бы псевдо-кодом расписать ваши операции при выходе из deep sleep?
это ваше мнение.
применяйте его к себе.
если мне надо будут нравоучения я пойду к батюшке в церковь.
------------
и не пытайтесь свои хотелки навязывать другим.
Не придумывайте того что не написано .
 

nikolz

Well-known member
А вы полагаете что у меня будет желание Вам что-то рассказывать после ваших нравоучений и наставлений?
Нахрена мне это надо?
Я общаюсь на форуме, если мне это интересно.
 

pvvx

Активный участник сообщества
Когда человек делится своми достижениями, целью все-таки должно являться
донести информацию и обеспечить возможность их повторения другими (и как сверхзадача - превзойти их). Так устроена цивилизация.
Если задача - просто прокричать, что вы все м., а я весь в белом - тогда да...
Не стоит слишком высоко оценивать всё человечество, особенно по его примитивным обитателям...
Тут всё гораздо проще - сам ТС не может создать код или выдумать какой новый алгоритм, новое решение задачи и т.д.
По этому он выдумывает разные байки по теме как вы и описали - он типа что-то превзошел. Похвастался тем, чего у него нет.
И цель этого - чтобы вы создали, обучили или дали ему всё готовое. :p
Можете хотя-бы псевдо-кодом расписать ваши операции при выходе из deep sleep?
Глупый вопрос. См. первый абзац. :)
 

pvvx

Активный участник сообщества
При выходе из deep-sleep происходит полная инициализация (кроме RTC понятно).
В любом случае при этом надо вызывать
wifi_station_set_config(&conf);
При чем тут RTC? Или Вы хотите сказать, что все задержки связаны с чтением этой conf из flash?
C таким же успехом конфигурацию можно просто в коде забить константами, тогда это еще быстрей будет (поскольку она окажется в RAM).
В ESP8266 по вашему описанию не учитываются задержки заполнения кеш для кода и данных с SPI FLASH. При старте вся кеш (в IRAM) пуста. Большинство кода стартовых процедур инициализации исполняются линейно, при постоянной подгрузке из SPI FLASH. Т.е. скорость работы CPU ограничен скоростью отработки шины SPI. Это в теоретическом максимуме при QSPI 80 MHz составляет до:

80*0.6/2 = 24 МБ в сек. где 0.6 – это учет тактов на передачу заголовка адреса для запроса блока из spi-flash, а 2 – это что требуется 2 такта шины qspi для считывания байта.

Средняя длина кода (АСМ) команды для CPU ESP8266 составляет более 2.5 байта.
Итого в CPU поступает не более чем:

32/2.5 = 12.8 мега команд в сек.

Т.к. ещё не учтены многие другие задержки и прочие факторы типа прерываний отнимающих время исполнения основных задач, имеем что ESP8266 работает со скоростью 8..10 МГц CPU с другой архитектурой.
Длина исполняемого кода SDK, перелопачиваемая CPU при инициализации на сегодня (особенно в Arduino) разрослась за многие мегабайты. Туда надо добавить, что каждое обращения к процедуре чтения Flash вызывает опустошение всех 32 килобайт кеш памяти в IRAM, плюс любая запись в flash имеет неимоверную задержку во времени…

Наш Гуру @nikolz ещё не дошел до учета оптимизации по данным параметрам, которая была проделана более 3-х лет назад другими...
 

pvvx

Активный участник сообщества
И вот эти утверждения совершенно неверны:
C таким же успехом конфигурацию можно просто в коде забить константами, тогда это еще быстрей будет (поскольку она окажется в RAM).
Чтобы данные оказались в RAM (сегмент .rodata), требуется их загрузка boot-loader-ом. А он у Espressif загружает их с Flash в режиме однобитной шины SPI и при пониженной частоте процедурами из ROM с максимально выставленными задержками в протоколе работы с Flash (чтобы работала любая Flash). Отношение скоростей доступа к блокам при нормально сконфигурированной системы аппаратной трансляции/отображения QSPI Flash в память процессора от boot-loader-а в ROM составляет сотни единиц. Туда надо ещё прибавить время разборки boot-loader-ом заголовков и особенно низкоскоростной вывод в UART сообщений без использования FIFO UART. В итого скорость загрузки констант в RAM в среднем не более сотни килобайт в секунду.

При чем тут RTC? Или Вы хотите сказать, что все задержки связаны с чтением этой conf из flash?
Это спорно и зависит от объемов и особенно программной процедуры чтения из Flash или RTC, если таковая используется.

Чтение из RTC имеет узкое место в виде низкоскоростной шины, тактируемой в 26МГц, её FIFO и дополнительных команд для CPU опустошения реального cache (которого нет у ESP) вставленных неправильно сконфигурированным транслятором gcc любителями… (они ещё и увеличивают размер кода загрузки и т.д.)

Размещение константы в ICACHE_FLASH_ATTR (и типа, в сегменте кода) запросто конкурирует с чтением аналогичных данных по шине из RTC по фактическому адресу. Если используется процедура от любителей (Espressif) для чтения из RTC, то это в сотни раз дольше. Т.е. тут чисто программная зависимость…
 

p-a-h-a

Member
Ну такая себе тема. 1.5 года как отправляю данные на народмон. Старый код вкладывается в 0,5 сек (millis) по HTTP. Новый и 0,27 сек может вложиться. От роутера много зависит. Дома TP-link старенький на нем такие результаты. У девушки Netis на нем новый код 1,12 сек с редкими ускорениями до 0.27 сек. Замеры времени все по millis
Код заканчивает исполнение обновлением RTC памяти с записью милис и подсчетом crc32, на следующее пробуждение значения уходят в сеть. Таким образом считаю практически все до сна.

Код:
void RTCupdate() {
  rtcData.NumberOfTransmitted++;// Увеличиваем количество срабатываний
  rtcData.SendDataTime = millis();// Запоминаем время передачи
  rtcData.crc32 = calculateCRC32((uint8_t*) &rtcData.crc32 + sizeof(rtcData.crc32), sizeof(rtcData) - sizeof(rtcData.crc32)); //Считаем CRC32 c адреса после rtcData.crc32 и длинной rtcData минус rtcData.crc32
  ESP.rtcUserMemoryWrite(0, (uint32_t*) &rtcData, sizeof(rtcData));// Write struct to RTC memory
}
ESP.deepSleep(330e6, RF_NO_CAL);
Играюсь с ESPNOW
смотрю что по тому же принципу милис считает до 60 а фактически пакеты приходят каждые 233мс.
Делаю вывод что милис начинают считать примерно через 170мс после пробуждения.
 

p-a-h-a

Member
Господа, простите за грубость, а на кой черт после пробуждения какие-то манипуляции с wifi делать?
Код:
  if (rtcData.NumberOfTransmitted == 1) //// Если уже было подключение хоть раз то ssid и pass хранятся во флеше и берутся от туда раньше чем скетч начнет исполнятся. К этому моменту соединение с wifi установлено, назначаются ip адреса
  {WiFi.begin(ssid, password);}
Засыпайте правильно
ESP.deepSleep(330e6, RF_NO_CAL);
И не давайте есп задание куда-то подключаться после первого удачного подключения. Она сама запомнит где сиська. Потом просто опрашиваем датчики и в конце проверяем а есть ли интернет
Код:
  while (WiFi.status() != WL_CONNECTED) {
    delay(1);
    i++; if (i > 5000) {
      RTCupdate();
      ESP.deepSleep(Recall, RF_NO_CAL);//СПИМ если не было соединения в течении 5 секунд. Если у вас плохой конект с wifi то следует увеличить число до 10000
    }
  }
Если есть то передаем данные, нет - перезагружаемся или спим.
 

pvvx

Активный участник сообщества
Господа, простите за грубость, а на кой черт после пробуждения какие-то манипуляции с wifi делать?
По тому, что нормальный AP закроет соединение через N*0.1024 сек, где N - это договор с AP о кол-ве пропущенных beacon для спящего устройства. N не достигает и десятки. Типично используется 3, т.е. 0.3072 сек. Далее, если устройство не ответило и не переназначило новый цикл сна, AP будет считать что устройство вышло из зоны приема и закроет соединение с ним.
На утверждение, что устройства больше нет (не в зоне видимости), AP истратит ещё несколько запросов-передач с периодами beacon (102.4 мс).
В итоге deep-sleep не может продолжаться более пары секунд, до закрытия соединения на AP.
 

pvvx

Активный участник сообщества
Это связано с тем, что пока действует согласованный с устройством спящий режим в N*(период beacon), AP должна буферизировать поступающие пакеты на назначенный IP устройства, включая всякие мультикасты и т.д. Иначе у неё переполнится память буфера.
Так-же это связано с безопасностью...
А так-же в инет-сети есть время предельного тайм-ута на запрос. Для TCP это было принято до 120 сек, когда он был ещё совсем тормозным...
Т.е. , теоретически, если у AP бесконечные буфера, то держать безответное соединение более 120 сек нет никакого смысла, а требуется сообщить остальной сети по специальным протоколам, освободить DHCP и т.д., что такого IP более нет в её местной сети.
Старые кривописанные AP часто халтурили - просто выкидывают все пакеты для спящего устройства и долго не отключали соединение, что позволяет при пробуждении устройства после десятка секунд сна, таким как nicolz, продолжить сессию с такой AP.
Но те времена прошли безвозвратно. На дворе уже давно WiFi 6.
Типичный современный WiFi SoC при постоянном соединении с AP потребляет менее 1 мА, и выкрутасы, применяемые у ESP не требуются.
Так-же никому уже не нужны точечные замеры происходящие раз в несколько минут. За это время дом сгорит и качество таких данных никчемное, если они хотя-бы не усреднены за данный период. Да и для систем регулирования "климата" в доме и выполнения всяких сценариев "Умного Дома" уже требуется поток данных от датчиков с дискретностью шага менее 1 сек, чего WiFi устройства не могут обеспечить от малых батареек типа CR2032. По этой причине всё переползло на BLE/ZigBee, и уже давно вышедший стандарт BT 5.0 позволяет держать дальнюю связь с дистанциями в 1 км...
 
Сверху Снизу