Разработка ‘библиотеки’ малого webсервера на esp8266.

Sanya_kv

New member
В программе терминала. Она имеет десятки ошибок.
Не факт. Возможно проблема и в LwIP стеке. Находил описание проблемы на форуме electronix.ru. Суть проблемы в следующем, при передаче пакетов по WiFi или сложной топологии по Ethernet, пакеты могут приходить в разном порядке. Насколько я понял у LwIP по приёму есть проблемы, если пакеты приходят не в том порядке, котором были переданы. К сожалению самому эту проблему пока проверить не удалось.
 

pvvx

Активный участник сообщества
Не факт. Возможно проблема и в LwIP стеке. Находил описание проблемы на форуме electronix.ru. Суть проблемы в следующем, при передаче пакетов по WiFi или сложной топологии по Ethernet, пакеты могут приходить в разном порядке. Насколько я понял у LwIP по приёму есть проблемы, если пакеты приходят не в том порядке, котором были переданы. К сожалению самому эту проблему пока проверить не удалось.
Нашел - опять не работает ets_timer_arm_new(&uart0_rx_buf_timer, 400, 0, 0); надо подобрать другое число :)
Но если использовать RTS - всё будет Ok.
Так всё хорошо: ets_timer_arm_new(&uart0_rx_buf_timer, 0, 0, 0); :)
Но иногда оно не запускает таймер и передача отключается навсегда в данном соединении. Походит на очередной привет от Espressif...
А требуется задержка до 128 chasr * 10 bits / 3000000 Baud = 0.000427 seс , чтобы поддерживать до 3Mbaud. Меньше можно, но лишний раз грузит CPU разборками с буфером.... Лучше всего - реакция в 200us на накопление символов в fifo rx UART перед сливом в TCP и чтобы не раздражало ожидание + нехилый джиттер ets_timer.
При ets_timer_arm_new(&uart0_rx_buf_timer, 0, 0, 0):
test.gif
Прием-передача текстового файла. Но в данной программе не работает дуплекс и тоже куча ошибок (обрывки по буферам COM). Зато пауз в межсивольную прием/передачу на COM не вставляет...
При частом использовании ets_timer_arm_new(&uart0_rx_buf_timer, 0, 0, 0) возникают пропуски - он не всегда отрабатывает. С числом 400us и другими подобранными - всегда. :)
Необходима смена алгоритма передачи принятых байт, чтобы в нем не участвовало ничего от Espressif. Для этого надо переписывать систему обращения к LwIP, используемую Web сервером (а лень плодить разные драйвера).
И тама правильно написано:
Цитата(akorud @ Aug 29 2014, 17:23)
LwIP - да, но надо понимать внутренности, конфигурацию и как все работает. Применяем в рабочих промышленных проектах, устройства подключаются к публичному Интернету. Уровень поддержки socket() настолько доработан, что libmicrohttpd пошла с пол-пинка. TFTP сервер и клиент из OpenBSD портировались за день.
ИМХО, из бесплатных лучше нет.
uIP - нет. В смысле пробовали и запретили к использованию.
Платформы - от M3 до ARM11.

Sanya_kv - Как вы хотите работать без сигнала RTS, если соединение, к примеру, идет через GSM? Там задержки более 5 сек подтверждения TCP пакетов :)
 
Последнее редактирование:

Algis

New member
Не факт. Возможно проблема и в LwIP стеке...
В этом случае нет, быстрая проверка показала, что 10кб данных от wifi на uart прходят без проблем, а от uart на wifi уже нет.
Данные теряется в sent_uart_rx_buf() недойдя до буфера стека,
здесь:

conn->ptrtx[conn->cntro++] = READ_PERI_REG(UART_FIFO(UART0));

проходят только остатки строки
 

pvvx

Активный участник сообщества
В этом случае нет, быстрая проверка показала, что 10кб данных от wifi на uart прходят без проблем, а от uart на wifi уже нет.
Данные теряется в sent_uart_rx_buf() недойдя до буфера стека,
здесь:

conn->ptrtx[conn->cntro++] = READ_PERI_REG(UART_FIFO(UART0));

проходят только остатки строки
Проверка показала, что ets_timer_arm_new(&uart0_rx_buf_timer, 100, 0, 0) = ets_timer_arm_new(&uart0_rx_buf_timer, 100, 0, 1), т.е. всегда в миллисекундах.
Кто написал эту глупость в osapi.h ?
Код:
#ifdef USE_US_TIMER
#define os_timer_arm_us(a, b, c) ets_timer_arm_new(a, b, c, 0)
#endif
#define os_timer_arm(a, b, c) ets_timer_arm_new(a, b, c, 1)
100ms.gif
Вот у вас символы и выпадают, т.к. не смотрите RTS, что их приема нет. А считывание завязано на таймер, который не работает как описано и дает вместо 100us 100ms, за которые буфер fifo UART rx уже заполнен.
Сменил исходники.
 
Последнее редактирование:

Algis

New member
Вот у вас символы и выпадают, т.к. не смотрите RTS, что их приема нет. А считывание завязано на таймер, который не работает как описано и дает вместо 100us 100ms, за которые буфер fifo UART rx уже заполнен.
Сменил исходники.
Работает отличнно! попробовал 100кб в обоих направлениях много раз, без потерь.
 

pvvx

Активный участник сообщества
Работает отличнно! попробовал 100кб в обоих направлениях много раз, без потерь.
Допилил RTS/СTS, как и писал ранее. С TCP2COM вроде всё, если ошибок не всплывет. Но скорость ограничена примерно 1Mbaud (не проверял, но будет просто выставляться RTS, когда таймер будет отрабатывать слишком долго и при плохой связи аналогично). В системе SDK нет таймеров на us, а использовать на это аппаратный не желательно, т.к. нужен для других целей. После выставления RTS в fifo rx свободно 15 символов... Общие буфера приема и передачи на 2 максимальных пакета TCP (2*MSS = 3120 байт). Приемный может быть больше (такова специфика, чтобы не потерять данные принимаемые по TCP и увеличивается до размера стека, т.к. в начале соединения он ограничен значением по умолчанию - что-то порядка чуть более 5кило для ESP8266 и когфига LwIP от Espressif-цев). При забитом буфере приема, соединение просто так не закрыть клиенту TCP пока UART (tx) не передаст большую часть данных из буфера (тоже такова специфика TCP и LwIP при малом размере стека и при низких скоростях UART, и если все-таки как-то :) 'абырвалг' соединение с полным буфером (методами brig), то новое соединение не открыть, пока не вылезут символы через UART и не отработает увеличение окна приема TCP...).
RTS/CTS работают при включенном 'flow control'. Тормозят ввод/вывод. При неактивном соединении RTS указывает, что ввода нет.
Предел отжирания памяти в heap TCP2COM до 9000 байт при всех забитых буферах:
TCP2COM_max_heap.gif
 
Последнее редактирование:

Algis

New member
Допилил RTS/СTS, как и писал ранее. С TCP2COM вроде всё, если ошибок не всплывет.
Супер!

была бы полезная еще одна простая фунциональность связанная с UART, чтобы подав строку на специальную GET или POST переменную она передавалась в UART, а ответ возвращался как содержание страницы, таким способом получится мост HTTP - UART.

Имея такой мост, легко сделать программу упраления какого нибудь устройства одним HTML/Javascript поместив все необходимое в WEBFiles

TCP2COM не подходят дла таких целей, потому что из Javascript пока нет возможности создавать "чистое" TCP соединение, XMLHttpRequest и WebSockets в браузерах имеет много ограничений из-за соображений безопасности.
 
Последнее редактирование:

A_D

Active member
Ну, хоть и ветка про SDK - приведу результаты маленького эксперемента тут, так сказать с чем больше всего связан с того и начинаю - с железа :)
как я писал выше, хотя никого не затронуло - про разводку и емкости в питании мне не понравилось. Так же была фраза в каком то из топиков (кажется Ваша, pvvx ) - что мол схемы дети рисуют, что по модулям оч близко к правде.
Итак, что я сделал:
взял сборку резисторов 8,2к (что было под рукой) и подтянул вывод 13 (MTDO) к земле, а выводы 32 (RST), 7 (CHEN), 15 (GPIO0) к питанию. Так же на вывод 7 (CHEN) подключен конденсатор 10nF на землю.
Снизу платы на дорожке питания и земляном полигоне снята маска и напаяна цепочка конденсаторов такого номинала: 0,1uF + 10nF + 2,2nF

Попробовал на обоих модулях это сделать. Результат:
-Значение Power на рабочем ранее модуле теперь как вкопанное почему то - 4,43 . Работает так же хорошо, как и было. Напряжение на выводе VDD_RTC - 1,1245v
-Ранее сильно гревшийся модуль теперь перестал резко грется при попытке подключения к нему и теперь вполне стабильно работает (хотя всеравно чуть теплее чем первый) и значение Power так же осталось 4,45. Подключение к этому модулю теперь стабильное и быстрое. Напряжение на выводе VDD_RTC - 1,1275v

Такие результаты.
 

Вложения

Последнее редактирование:
  • Like
Реакции: MSW

shadows

New member
Проверка показала, что ets_timer_arm_new(&uart0_rx_buf_timer, 100, 0, 0) = ets_timer_arm_new(&uart0_rx_buf_timer, 100, 0, 1), т.е. всегда в миллисекундах.
Кто написал эту глупость в osapi.h ?
Код:
#ifdef USE_US_TIMER
#define os_timer_arm_us(a, b, c) ets_timer_arm_new(a, b, c, 0)
#endif
#define os_timer_arm(a, b, c) ets_timer_arm_new(a, b, c, 1)
В IOT SDK есть кусок
Код:
3.2.9. system_timer_reinit
Function: Reinitiate the timer when you need to use microsecond timer
Not es: 1. Define USE_US_TIMER;
2. Put system_timer_reinit at the beginning and user_init in the first 
  sentence.
Function definition:
void system_timer_reinit (void)
вот кусок дизасма Libmain.a, (не совсем ясно че лежит в dword_7E8 ) но похоже перконфигурируется делитель таимера. после этого возможно все заработает.
Код:
.irom0.text:000007E5                 .byte 0, 0, 0
.irom0.text:000007E8 dword_7E8       .int 0                  ; DATA XREF: system_timer_reinitr
.irom0.text:000007EC dword_7EC       .int 0x60000600         ; DATA XREF: system_timer_reinit+Br
.irom0.text:000007F0
.irom0.text:000007F0 ; =============== S U B R O U T I N E =======================================
.irom0.text:000007F0
.irom0.text:000007F0
.irom0.text:000007F0 system_timer_reinit:
.irom0.text:000007F0                 l32r            a5, dword_7E8
.irom0.text:000007F3                 movi.n          a4, 0
.irom0.text:000007F5                 s8i             a4, a5, 1
.irom0.text:000007F8                 movi            a2, 0x84
.irom0.text:000007FB                 l32r            a3, dword_7EC
.irom0.text:000007FE                 memw
.irom0.text:00000801                 s32i.n          a2, a3, 0x28
.irom0.text:00000803                 ret.n
.irom0.text:00000803 ; End of function system_timer_reinit
 

pvvx

Активный участник сообщества
В IOT SDK есть кусок
Код:
3.2.9. system_timer_reinit
Function: Reinitiate the timer when you need to use microsecond timer
Not es: 1. Define USE_US_TIMER;
2. Put system_timer_reinit at the beginning and user_init in the first
  sentence.
Function definition:
void system_timer_reinit (void)
Страшновато переинициализировать таймер - вдруг повлияет на уже работающие процедуры в SDK. Они все пользуются timer_insert() из Bios ROM.
Код:
40240bf0 <system_timer_reinit>:
40240bf0:    fe8251           l32r    a5, 402405f8 <xPortGetFreeHeapSize+0x50>  [0x3ffe8000] =  0x01010101
40240bf3:    040c         movi.n    a4, 0
40240bf5:    014542           s8i    a4, a5, 1
// 3ffe8000: 01 01 01 01 00 00 cd ab 01 00 00 00 ec 05 00 00
40240bf8:    84a022           movi    a2, 132
40240bfb:    fd9031           l32r    a3, 4024023c <_irom0_text_start+0x23c>  0x60000600
40240bfe:    0020c0           memw
40240c01:    a329         s32i.n    a2, a3, 40   [0x60000628] до этого = 0x00000088, пишет 0x84
40240c03:    f00d         ret.n
Она меняет "предшкалер" у таймера с DIVDED_BY_256 на DIVDED_BY_16 и меняет какой-то флаг в памяти. До 3ffe8000: 01 01 01 01 , после 3ffe8000: 01 00 01 01
До этого таймер работает с шагом в 0.0000032 сек (3.2us), а после в 200ns.
-------
Вставил в исходники, включил расчет задержек в TCP2COM ... счас заменю свалку...
 
Последнее редактирование:

pvvx

Активный участник сообщества
Ну, хоть и ветка про SDK - приведу результаты маленького эксперемента тут, так сказать с чем больше всего связан с того и начинаю - с железа :)
как я писал выше, хотя никого не затронуло - про разводку и емкости в питании мне не понравилось. Так же была фраза в каком то из топиков (кажется Ваша, pvvx ) - что мол схемы дети рисуют, что по модулям оч близко к правде.
Это очень хорошо, что дети рисуют - пусть развиваются, но верить таким рисункам не стоит :)

Итак, что я сделал:
взял сборку резисторов 8,2к (что было под рукой) и подтянул вывод 13 (MTDO) к земле, а выводы 32 (RST), 7 (CHEN), 15 (GPIO0) к питанию. Так же на вывод 7 (CHEN) подключен конденсатор 10nF на землю.
Снизу платы на дорожке питания и земляном полигоне снята маска и напаяна цепочка конденсаторов такого номинала: 0,1uF + 10nF + 2,2nF

Попробовал на обоих модулях это сделать. Результат:
-Значение Power на рабочем ранее модуле теперь как вкопанное почему то - 4,43 . Работает так же хорошо, как и было. Напряжение на выводе VDD_RTC - 1,1245v
-Ранее сильно гревшийся модуль теперь перестал резко грется при попытке подключения к нему и теперь вполне стабильно работает (хотя все равно чуть теплее чем первый) и значение Power так же осталось 4,45. Подключение к этому модулю теперь стабильное и быстрое. Напряжение на выводе VDD_RTC - 1,1275v
Такие результаты.
Поменяйте значение делителя для пересчета значений adc vdd в напряжение.
Надо найти, где сидит встроенный корректор. Возможно он прошит и в ROM или "OTP" блоках чипа и вообще не устанавливалось. Партии чипов разные и разное показание.
 

pvvx

Активный участник сообщества
была бы полезная еще одна простая фунциональность связанная с UART, чтобы подав строку на специальную GET или POST переменную она передавалась в UART, а ответ возвращался как содержание страницы, таким способом получится мост HTTP - UART.
Всё в ваших руках. Впишите в исходники :)
Оно и счас без моста работает. Пример приведен в sample.htm. Там прямо в регистры UART пишет :)
Вы можете находу сменить и уровни защелок RTS на другое ко-во символов в fifo и т.д. Они устанавливаются только при инициализации...
Отдача страниц из UART - это как-то криво в связи со скоростью UART и неопределенностью, где конец и сколько куда. Для этого требуется спецфический формат передачи и т.д. Т.е. всё становиться заточенным на определенный проект, а тут просто свалка часто встречающихся вариантов...
Делать Telnet аля HTTP таким образом тоже не красиво.
Для отдачи логов надо резервировать статический буфер в памяти, который отображать на странице, путем добавления строк из него, что пока не охота, т.к. связано с многозадачностью - соединений может быть много и все они должны работать с этим буфером совместно (к примеру UART то однозадачный...).
 
Последнее редактирование:

Algis

New member
Всё в ваших руках. Впишите в исходники...
Сделаю, но ваши знания SDK и опыт в прогаммировании на С лучше моих, и то что вы делаете доступно всем в исходниках "из коробки".

Отдача страниц из UART - это как-то криво в связи со скоростью UART и неопределенностью, где конец и сколько куда. Для этого требуется спецфический формат передачи и т.д. Т.е. всё становиться заточенным на определенный проект, а тут просто свалка часто встречающихся вариантов...
Это получилось бы заточенным для JSON формата, родного для javascript приложений и для всего веба, которые имели бы доступ к UART через AJAX запрос.
Такая функциональность, для людеи знающих javascript лучше чем С, дала бы возможность меньше вмешиваясь в прошивку сделать приложение управления самодельных устройств.
 
Последнее редактирование:

pvvx

Активный участник сообщества
Сделаю, но ваши знания SDK и опыт в прогаммировании на С лучше моих, и то что вы делаете доступно всем в исходниках "из коробки".
У меня нет опыта программирования на С. Я пишу на всех языках программирования, которые необходимы и лучше подходят для реализации проектов. По этой причине многое в них не знаю - только поверхностно. По СИ у меня не было ни одной книжки... Я считаю, что у вас возможностей больше - вся информация ныне есть в инет.
Это получилось бы заточенным для JSON формата, родного для javascript приложений и для всего веба, которые имели бы доступ к UART через AJAX запрос.
Такая функциональность, для людеи знающих javascript лучше чем С, дала бы возможность меньше вмешиваясь в прошивку сделать приложение управления самодельных устройств.
JSON формат не актуален - он не поддерживает POST, т.е. устарел и не является 'родным' для javascript.
https://ru.wikipedia.org/wiki/Cross-origin_resource_sharing
До недавнего времени основным способом преодоления ограничений, наложенных в same-origin-policy относительно XSS запросов, было использование JSONP. Сам JSONP имеет неустранимое ограничение — позволяет только получение данных GET методом, то есть отправка данных через POST метод остается недоступной.
https://ru.wikipedia.org/wiki/JSONP
JSONP или «JSON with padding» (JSON с набивкой) это дополнение к базовому формату JSON. Он предоставляет способ запросить данные с сервера, находящегося в другом домене — операцию, запрещённую в типичных веб-браузерах из-за политики ограничения домена.
https://ru.wikipedia.org/wiki/JSON
Заметим, что данный пример применения XMLHttpRequest не является универсальным для всех браузеров (для браузеров, основанных на Internet Explorer, Opera, Safari и Mozilla, в коде должны быть те или иные отличия). Возможности применения XMLHttpRequest ограничены из-за правила ограничения домена (same origin policy): URL ответ на запрос должен находиться в том же DNS домене, что и сервер, на котором находится страница, запрашивающая ответ. В качестве альтернативы применяется подход JSONP, включающий в себя использование закодированного вызова функции, передающегося между клиентом и сервером, чтобы клиент мог загружать закодированные в JSON данные со сторонних доменов, и уведомлять о завершении вызывающую сторону, хотя это приводит к некоторым рискам для безопасности и дополнительным требованиям к серверу.
:) :) :)

Короче - JSON не поддерживается в современных браузерах и вымирает как мамонты.
XML спасет строка в web-сервере: tcp_puts("Access-Control-Allow-Origin: *\r\n");
Всё читается и передается куда угодно и очень легко отлаживать web страницы на компе, посылающие запросы к данным c Web на устройстве (хоть GET, хоть POST :) ).
Но самое главное ограничение у JSON - общая длина заголовка HTTP запроса. Она у всех ограничена, а POST с multipart/form-data ничем не ограничен. Ой - нет.- ограничен размером числа за Content-Length в заголовке HTTP в аски символах... в либах atoi() :)
atoi() не возьмет 100 значное число.... :(
----
Новая версия переехала на SDK 0.9.5 + Unofficial Development Kit for Espressif ESP8266 v1.0.8 (c) by CHERTS.
Изменены маке файлы.
 
Последнее редактирование:

Algis

New member
У меня нет опыта программирования на С. Я пишу на всех языках программирования, которые необходимы и лучше подходят для реализации проектов. По этой причине многое в них не знаю - только поверхностно. По СИ у меня не было ни одной книжки... Я считаю, что у вас возможностей больше - вся информация ныне есть в инет.
У меня то же самое, не было ни одной книги по програмированию, и не учился специально. Hо как-то лет 15 назад заинтересовался и постепенно втянулся полностью...
JSON формат не актуален - он не поддерживает POST, т.е. устарел и не является 'родным' для javascript.
JSON (JavaScript Object Notation) - формат описания обьектов в JavaScript, из-за своей компактности (особенно в сравнении с xml, при той же самой фунциональности) очень удобен для описания структурированных данных, и широко используется в вебе... ну неважно...

Вот, добавил передачу данных на UART и обратно через HTTP, и попробовал сделать дистанционное управление для контроллера отопительной системы,
команды посылаются в виде эскейп последовательностей типа: \x1B\n0?5\x1B\r а возвращается в виде массивов данных в JSON
Очень все хорошо получается, уже никак нельзя ваш проект называть "свалкой файлов" :) спасибо.
 

Вложения

pvvx

Активный участник сообщества
Очень все хорошо получается, уже никак нельзя ваш проект называть "свалкой файлов" :) спасибо.
Там нет никакой стабильности - значит свалка. И времени её разгрести нет, по причине отсутствия исходников и прочей информации по чипу.
 

Lstt

Member
У меня то же самое, не было ни одной книги по програмированию, и не учился специально. Hо как-то лет 15 назад заинтересовался и постепенно втянулся полностью...

JSON (JavaScript Object Notation) - формат описания обьектов в JavaScript, из-за своей компактности (особенно в сравнении с xml, при той же самой фунциональности) очень удобен для описания структурированных данных, и широко используется в вебе... ну неважно...

Вот, добавил передачу данных на UART и обратно через HTTP, и попробовал сделать дистанционное управление для контроллера отопительной системы,
команды посылаются в виде эскейп последовательностей типа: \x1B\n0?5\x1B\r а возвращается в виде массивов данных в JSON
Очень все хорошо получается, уже никак нельзя ваш проект называть "свалкой файлов" :) спасибо.
А можно более подробнее, очень интересно, сам хочу использовать модули (которые ещё в пути) для банального управления силовыми нагрузки (возможно диммирование)... Ещё бы как-нибудь это к Андроиду привязать...
 

Algis

New member
А можно более подробнее, очень интересно, сам хочу использовать модули (которые ещё в пути) для банального управления силовыми нагрузки (возможно диммирование)... Ещё бы как-нибудь это к Андроиду привязать...
Для вкл/выкл, достаточно в Web директории сделать htm с формой в которой столько checkbox'ов сколько виводов модуля вы хотите виделить для этого,
названия им дать например gpio1, gpio2, gpio3 а в web_int_vars.c добавить условие
Код:
else if(!os_memcmp((void*)cstr, "gpio", 4)) {
....
}
со своим обработчиком этого типа переменных, управляющим соответстующие выводы модуля.
Ели выводов не хватает, поставить сдвиговщй регистр, дальше уже обычьные или твердотельные реле.
С диммированием сложнее, придется через оптрон ловить пересечение нуля в сети и от этого осчитывать момент включения вывода,
 
Последнее редактирование:
  • Like
Реакции: Lstt

Lstt

Member
Спасибо за ответ! Здесь нашел работоспособную схему для Arduino, как раз с детектором нуля http://wiki.dxarts.washington.edu/groups/general/wiki/4dd69/AC_Dimmer_Circuit.html , как Вы считаете, её можно задействовать, я так понимаю, необходимо постоянно опрашивать вход, для определения этого момента, а для простого включения выключения, думаю тоже использовать обычную симисторную схему с драйвером для гальванической развязки, вот хочется только ещё диммирование прикрутить...
 
Сверху Снизу