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

нужна помощь! Как увеличить TCP_WND в ESP8666/Arduino?

думка

New member
Добрый день, друзья.
Помогите, пожалуйста, советом. Собрал симпатичный бум-бокс с WEB-радио на ESP8266+VS1053, но есть проблема с воспроизведением станций с большим пингом.
На ESP32 удалось победить заикания, увеличив размер TCP_MSS пакета до максимума IPv6 (1440 байт), но главным образом помогло увеличение окна TCP_WIND до 10хTCP_MSS. Заикания практически прекратились.
Правда, для этого пришлось подключать Arduino as component и собирать проект в ESP-IDF (благо, что в Platformio это сейчас делается весьма удобно).
Но с ESP8266 оказалось гораздо хуже.
Как известно, для ESP866 в Ардуино в Lwip сконфигурирован размер окна (максимум) в TCP_WND = (4 * TCP_MSS), где TCP_MSS 1460 байт. Получается 5840 байт.
И как я только не пытался его увеличить, не помогает ничего.
Т.е. макрос этот я могу переопределить: и в своей программе пробовал, и редактировал opt.h в sdk\lwip.... Он действительно переопределяется, и Serial.print(TCP_WND) выводит новое значение...
Да вот только по факту ничего не меняется! Wireshark неумолимо показывает, что размер окна остается прежним!
Пробовал и lwip v2 и v1.4, и "чистую" компиляцию... никакого эффекта.
Где они могли захардкодить этот параметр?? Как его изменить?...

Может, как-то можно в этот Arduino framework вставить исходный ESP8266_NONOS_SDK и полностью его пересобрать? Ктонибуть пробовал так делать?
Или посоветуете другие способы?
Спасибо!
 

думка

New member
Вроде нашел, где эти параметры захардкожены.
В репозитории ESP8666/Arduino/tools/sdk/lib/ лежат откомпилированные библиотеки вида liblwip2-1460.a для каждого из вариантов LWIP. В Platformio framework-arduinoespressif8266 ставят из собственного репозитория, и там еще добавлен вариант LWIP v1.4, но также в виде библиотечного файла... А вот кто, где и как эти библиотеки собирает, пока разобраться не могу.
Похоже, вопрос теперь нужно задавать так: народ, помогите скомпилировать библиотеки lwip для Ардуино фреймворка с собственными параметрами..)
 

pvvx

Активный участник сообщества
TCP_WIND более 4 x TCP_MSS на ESP8266 не используется.
Размер TCP пакета 1560 байт, но не везде установлено "новое" оборудование и старьё GSM сеть тянет размер меньше.
* "новое" - имеется в виду не из того века.
Если взять 10 x 1440 байт, то поучим, что требуется 14400 байтный буфер в LwIP для каждого TCP соединения. И пока он не заполнится и не отошлет подтверждения (ACK) - он не отдаст из него ни байта. Ваши либы не используют буфер LwIP, а для обработки копируют данные из него. В итоге вам потребуется обьем свободной RAM в 14400 байт + объем буфера. И пока вы не выудите все байты из буфера размером в TCP_WIND у LwIP, он не сможет принять ни байта новых, а сеть будет занята передачей состояний TCP_WIND исчерпан, что при большом "пинг" всё усугубит ещё во много раз. Есть ли у ESP8266 столько свободной RAM в вашем "проекте"?

Стандартная передача в TCP требует подтверждения каждого пакета, но есть вариант с передачей вперед и в таком варианте обычно передается 2 пакета, после которых передатчик ожидает ACK.
Как "10хTCP_MSS" может исправить вашу проблему? - никак.
Вы не там создаете и не так делают буферизацию.
Да и "заикается" WEB-радио не всегда по причине малого буфера. Если у вас спешат часы вывода звука и они не корректируются, то никакой буфер вам не поможет - как из будущего взять данные? Тут решение только одно - встройте в код "машину времени". :)
 

pvvx

Активный участник сообщества
При вашем запросе в 10хTCP_MSS от ESP8266 потребуется наличие дополнительной свободной памяти по минимуму от 32 килобайт. И это не ускорит прием и на 10%.
Для тупых алгоритмов реализованных в либах ESP8266 при 10хTCP_MSS потребуется от 3*10хTCP_MSS RAM + дополнения. Тогда, в каких-то ситуациях с сетью это может привести к улучшению. Но этот процент очень мал.
Используйте собственную буферизацию. Это гораздо эффективнее - не потребует переписывания с нуля всего SDK от Espressif.
 

enjoynering

Well-known member
Тоже пишу радио на esp8266 и vs1053 в среде Arduino. Уже есть полностью самописный драйвер для vs1053 который умеет почти все плюшки описанные в 90 страничном datasheet. Даже разнонял чип до нештатных 60МГц. Это даёт прирост скорости SDI SPI с 10МГц до 15МГц. Сейчас у меня кольцевой буфер в heap в 21КБ и ещё около 15КБ свободно на все остальное. Это мой потолок. Меньше 15КБ и esp8266 крашиться при обращении к встроенному серверу и html страницам. Играют почти все радиостанции, кроме 320kbps. Застрял на чтении списка и сохранения радиостанций. Понимаю, что это нужно делать через pointers и reference (для уменьшения расхода heap памяти) но видно пока мозгов не хватает реализовать. Уже было 4 неудачных попытки. Сейчас все 32 станции висят в heap и расходуют кучу места. Так вот вернемся к нашим баранам, я не специалист, но pvxx прав

пока он не заполнится и не отошлет подтверждения (ACK). пока вы не выудите все байты из буфера размером в TCP_WIND у LwIP, он не сможет принять ни байта новых
В ардуино даже есть функция, которая заставляет выставить ACK раньше чем заполнится буфер - setNoDelay(true).

Пы.сы. Ещё заметил, что увеличение выходной мощности wifi уменьшает заикание на высоких батрейтах. Минимум который советую не менее +10dBm
 

Вложения

думка

New member
Спасибо за ответ! Сейчас, при окне 5840 байт у меня кольцевой буфер на 40 кб. То есть, при 10хTCP_MSS у меня остается память на кольцевой буфер на 30кб. Должно хватить, по идее.
При малом TCP_WND, судя по снифферу и дебаг-логу, происходит примерно следующее: стрим заполняет окно 4-мя пакетами, затем останавливает передачу и ожидает пакетов от ESP. Когда ESP перетаскивает данные из TCP буфера в свой кольцевой буфер, он отправляет пакет на сервер с новым окном, и только после этого сервер возобновляет трансляцию стрима. При долгом пинге (и\или медленном сервере), такой перезапуск стрима занимает долгое время, дольше, чем воспроизводится кусок стрима размером 5840 байт. Это приводит к исчерпанию кольцевого буфера, и начинаются заикания.
Когда TCP_WND достаточно большое, то перезапуски стрима происходят гораздо реже, и порции данных в кольцевой буфер поступают больше, и он успевает наполняться с нужной скоростью.
Я, конечно, еще только разбираюсь с этими механизмами, но по внешним признакам выглядит именно так.
Повторюсь, тот же стрим на ESP32 c увеличенным размером окна играет вполне стабильно.
Кстати, я нашел на форумах похожие запросы на пересборку библиотек Ардуины, и предлагаемые методы требуют использования make на Linux. Я попытался запустить релиз gnumake для win64 - но безуспешно, ругается на ошибки Makefile... морально готовлюсь ставить виртуалку и разбираться с компилляцией под linux..)
 

enjoynering

Well-known member
Я тут бегло погуглил и вот что нашёл для Arduino (сам не пробовал и не проверял, так что это не точно).

Надо себе в проект из папки arduino/tools/sdk/lwip2/ include/скопировать файл lwipopts.h. В нем поменять размер окна TCP_WND и прекомпилировать sketch.

Для проверки с тело программы добавить вывод printf("TCP_MSS: %u", TCP_MSS);
 

pvvx

Активный участник сообщества
Когда TCP_WND достаточно большое, то перезапуски стрима происходят гораздо реже, и порции данных в кольцевой буфер поступают больше, и он успевает наполняться с нужной скоростью.
Зачем работать на грани?
А если будет потеря одного пакета - всё - щелкание?
Возьмите RTL8722DM - там всё встроено - кодек аж с выходами на наушники + 2 мегабайта DRAM, да и жрет он меньше ESP8266 и WiFi 5ГГц тянет.
 

enjoynering

Well-known member
А если RTL8722DM пакет потеряет, то щёлканья не будет?

Ахаха и цена на RTL8722DM - $24 плюс доставка. Цена однолатного компа с 4-я ядрами на Armbian. Отличный совет.
 

pvvx

Активный участник сообщества
А если RTL8722DM пакет потеряет, то щёлканья не будет?
Нет не будет - буфер на несколько минут.
Ахаха и цена на RTL8722DM - $24 плюс доставка. Цена однолатного компа с 4-я ядрами на Armbian. Отличный совет.
Ну если покупать чип с квартирой, то да.
Armbian c квартирой подороже будет.
Любой чип с MP3 с ценой менее $1 с eval-board стоит из $100
 

pvvx

Активный участник сообщества
А если RTL8722DM пакет потеряет, то щёлканья не будет?

Ахаха и цена на RTL8722DM - $24 плюс доставка. Цена однолатного компа с 4-я ядрами на Armbian. Отличный совет.
Пришлите мне пачку "однолатного компа с 4-я ядрами на Armbian" хотя-бы за спекульную цену RTL8722DM с внешней антенной
 

enjoynering

Well-known member
я вам покажу, но вы же опять опять начнете растекаться словоблудием по клавиатуре. вот первый попавшийся - orange pi zero. С доставкой $17.39 (по вашей ссылке за $6 нет в наличии. ну и вы как всегда забыли, что без спец программатора, который тоже стоит денег, ваш RTL8722DM не прошить)

Нет не будет - буфер на несколько минут.
а дырка в буфере сама зарастет. :)
 

pvvx

Активный участник сообщества
я вам покажу, но вы же опять опять начнете растекаться словоблудием по клавиатуре. вот первый попавшийся - orange pi zero. С доставкой $17.39 (по вашей ссылке за $6 нет в наличии. ну и вы как всегда забыли, что без спец программатора, который тоже стоит денег, ваш RTL8722DM не прошить)
1350 рублей стоит ваша orange pi zero. Прям как ESP32 с PSRAM.
А указанный вам модуль стоит 440 руб и для программирования требует COM порт или SWD программатор. RtlDtool.py уже давненько выложил, но можете воспользоваться оф. ПО от Ameba или Arduinio.
Чтобы из него сделать проигрыватель требуется подвести питание в 3.3В и подключить разъем на стерео наушники или усилитель на динамики.
Немного сложнее из него сделать USB-SoundBlaster - надо припаять ещё разъем USB и прошить готовым примером. После этого в windows или ком-ещё появится новый выход audio...
а дырка в буфере сама зарастет. :)
Вы с луны свались? Стек TCP перезапросит потерянный пакет.
Но вашего буфера в ESP32 и и тем более в ESP8266 не хватит...
 

думка

New member
Я тут бегло погуглил и вот что нашёл для Arduino (сам не пробовал и не проверял, так что это не точно).

Надо себе в проект из папки arduino/tools/sdk/lwip2/ include/скопировать файл lwipopts.h. В нем поменять размер окна TCP_WND и прекомпилировать sketch.

Для проверки с тело программы добавить вывод printf("TCP_MSS: %u", TCP_MSS);
Спасибо, но этот совет, вероятно, мог бы сработать на Ардуине под Линух. Там, по слухам, даже есть опция такая в IDE - "Собрать LwIP1.4 из исходников", хотя сам не видел). Под Виндой используются готовые, уже откомпиллированные с заданными значениями параметров библиотеки, и переопределение этих макросов каким-либо из способов не приводит к изменению значений в самих библиотеках. Иными словами, проверка ваша покажет новые значения, а вот по факту все останется как было, полагаю) Я уже отмечал это в первых постах.
Нужно компиллировать библиотеки LwIP заново, но как сделать это под Виндой, я пока не разобрался... Даже если удалить эти файлы из фреймворка, просто вываливается ошибка линковщика - но компилляция не происходит(

pvvx, спасибо за рекламу RTL, они правда молодцы и чипы у них отличные. Пожалуй, если задуматься о каких-то коммерческих проектах, где важны надежность и производительность, то они выглядят предпочтительнее. Однако, для образовательных поделок на Ардуине, ESP все еще вне конкуренции. В том числе, благодаря своим багам) Меня, например, они сподвигли погрузиться с особенности TCP-стека и архитектуру библиотек Ардуино)) к тому же, мы отклонились от темы топика - я просил о помощи с доработкой уже готовой поделки, которая в целом играет неплохо, и вообще мне нравится) Менять плату там пока не хочется, постараюсь дожать ESP8266, посмотрим. на что он еще способен)
 

pvvx

Активный участник сообщества
А можно ссылку на RtlDtool.py? Заранее спасибо.
На форуме в соответствующей теме про RTL
Спасибо, но этот совет, вероятно, мог бы сработать на Ардуине под Линух. Там, по слухам, даже есть опция такая в IDE - "Собрать LwIP1.4 из исходников", хотя сам не видел). Под Виндой используются готовые, уже откомпиллированные с заданными значениями параметров библиотеки, и переопределение этих макросов каким-либо из способов не приводит к изменению значений в самих библиотеках. Иными словами, проверка ваша покажет новые значения, а вот по факту все останется как было, полагаю) Я уже отмечал это в первых постах.
Нужно компиллировать библиотеки LwIP заново, но как сделать это под Виндой, я пока не разобрался... Даже если удалить эти файлы из фреймворка, просто вываливается ошибка линковщика - но компилляция не происходит(
Я бы на вашем месте просто засунул бы файлы Lwip в директорию C:\Users\ИмяПользователя\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.7.4\cores\esp8266 и они бы собрались автоматом.
Но есть и другие более сложные варианты... :)
 

pvvx

Активный участник сообщества
Я тут бегло погуглил и вот что нашёл для Arduino (сам не пробовал и не проверял, так что это не точно).

Надо себе в проект из папки arduino/tools/sdk/lwip2/ include/скопировать файл lwipopts.h. В нем поменять размер окна TCP_WND и прекомпилировать sketch.

Для проверки с тело программы добавить вывод printf("TCP_MSS: %u", TCP_MSS);
Вообще-то вам, как великому Ардуинщику давно бы надо знать, что размер TCP_MSS в Дурине не выставляется в lwipopts.h, а выбирается в меню по типу либы:
1612858916876.png
 

pvvx

Активный участник сообщества
Спасибо, но этот совет, вероятно, мог бы сработать на Ардуине под Линух. Там, по слухам, даже есть опция такая в IDE - "Собрать LwIP1.4 из исходников", хотя сам не видел).
Вы плохо смотрели. Последний выбор в меню и есть собрать либу 'liblwip_src.a'
Но там всё равно грабли, которые вы не разрешите...
По этому для начала опишите какая у вас используется либа, какая операционка, какая версия Дурины и т.д. Всю подноготную, включая месяц рождения (шутка) :)
Только тогда вы сможете получить ответ. А пока этого нет - будем спамить и прикалываться над вами.
 

pvvx

Активный участник сообщества
увеличив размер TCP_MSS пакета до максимума IPv6 (1440 байт)
Во первых у IPv6 максимальный размер пакета 2^32-1 байт. Во вторых зачем вам для проигрывателя в местной интрасети IPv6 ? Чтобы подтормаживало? Роутер не может заняться перекидыванием IPv6<->IPv4 если ваша любимая станция работает только по IPv6? Может у вас ESP получает cтатический (фиксированный) внешний IP-адрес в глобальном инете, или всё-же через NAT и прочие брандмауэры?
... и таких вопросов может быть мульон, т.к. из ваших описаний непонятно, что вы там затеяли и какой вариант решения будет самым простым.

А кратко суть - для пересборки Lwip в Arduino для windows необходимо - иметь make.exe в path, выбрать нижний пункт в меню (указано ранее где).
Опции TCP_WND заданы в регистрах RTC, а не в "lwipopts.h" и прописано это по всем закрытым либам. А для ESP8266 все системные либы являются закрытыми. Привет от Espressif.
Значение в назначенном регистре TCP_WND прописывается в файле ...tools\sdk\lwip\src\core\init.c в void lwip_init(void).

Однако, для образовательных поделок на Ардуине, ESP все еще вне конкуренции. В том числе, благодаря своим багам) Меня, например, они сподвигли погрузиться с особенности TCP-стека и архитектуру библиотек Ардуино)) к тому же, мы отклонились от темы топика - я просил о помощи с доработкой уже готовой поделки, которая в целом играет неплохо, и вообще мне нравится) Менять плату там пока не хочется, постараюсь дожать ESP8266, посмотрим. на что он еще способен)
Это полностью навязанное вам чужое мнение. Практика показывает обратное. Хотя-бы на вашем примере в данной теме.
 

думка

New member
Вы плохо смотрели. Последний выбор в меню и есть собрать либу 'liblwip_src.a'
Но там всё равно грабли, которые вы не разрешите...
По этому для начала опишите какая у вас используется либа, какая операционка, какая версия Дурины и т.д. Всю подноготную, включая месяц рождения (шутка) :)
Только тогда вы сможете получить ответ. А пока этого нет - будем спамить и прикалываться над вами.
Вот спасибо, давно я в ArduinoIDE не заглядывал, пришлось даже установить) но, к сожалению, что-то пошло не так: при выборе этого пункта получаю ошибку:
"exec: "make": executable file not found in %PATH%"

т.е. make.exe все-таки какойто нужен дополнительно, в самом Arduino IDE его нет. Словом, вернулись к началу)

далее, насчет
Опции TCP_WND заданы в регистрах RTC, а не в "lwipopts.h" и прописано это по всем закрытым либам.
здесь тоже хотелось бы уточнить, о каких либах речь. Насколько я понимаю, при работе с оригинальным SDK (как RTOS, так и NON-OS), эти параметры можно менять. Во всяком случае, с этим нет проблем в esp-idf для ESP32. Причем, даже при сборке ардуиновского проекта через ESP-IDF plugin + Arduino component в Platformio (именно так я и действую). А "закрыты" они только в Ардуиновском фреймворке, поскольку здесь линкуются уже собранные библиотеки. Собственно, об этом я уже упоминал выше.
По сообщениям на форумах, собственная сборка LwIP1.4 для ардуин возможна пол Линухом, где установлен make. Хотя в makeEspArduino есть такая фраза в readme: "The makefile can be used on Linux, Mac OS and Microsoft Windows (Cygwin or WSL)." Вот только жаль, что ни сам этот пакет, ни тулчейн в Ардуине под виндос их не включает(

И последнее, что касается размера пакетов. По результатам экспериментов на ESP32 я заметил, что при TCP_MSS 1440 задержки стрима меньше. Возможно, это связано с настройками сетевого оборудования у моего провайдера. В любом случае, если научиться менять этот параметр, то можно будет поэкспериментировать и найти оптимальные размеры пакета и окна. Что я и собираюсь сделать)
 
Сверху Снизу