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