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

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

AlexMelven

New member
надо к серверу создать аналог ESP TOUCH или типа того. Все-таки управление со смартфона через программу весьма нужная вещь. Чтобы все девайсы в кучу собирать в одной программе и ими управлять. Раз у китайцев это все криво и не работает, надо свое сделать, но рабочее. Тем более что в данном проекте китайские библиотеки более использоваться не будут из-за кривости.
 

pvvx

Активный участник сообщества
Сделал более менее нормальный Modbus RTU RS-485 и шлюз Modbus TCP, но не закончил с HTTP управлением всем этим делом. Будет отдельная прошивка без TCP-UART. Пока не доделал, принимаются заявки-хотелки для такой версии.
Драйвер RS-485 жрет более отложенных 500 запросов - имеет стек запросов и может создавать аналогичный стек ответов (связанных по ID от запросов)... Т.е. полностью мультизадачный и работающий по прерываниям и task-ам...
Используется RX - TX и комбинация их swap, плюс /OUT_ENABLE на любом свободном GPIO (или он отключен). RX и TX можно соединять в один провод для "однопроводного" интерфейса к другому чипу, если не используется драйвер шины RS-485.
Пакет http://www.modbustools.com/download.asp работает без ошибок на любой скорости.
 
Последнее редактирование:

Andy Korg

Moderator
Команда форума
...Пока не доделал, принимаются заявки-хотелки для такой версии....
Дык, этааа..., а можно вынести передачу не обработанных переменных в web_int_callbacks.c и web_int_vars.c ? Например в web_int_vars.c что-то типа такого:
Код:
void ICACHE_FLASH_ATTR web_int_vars(TCP_SERV_CONN *ts_conn, uint8 *pcmd, uint8 *pvar)
{
.....
    else parseHttpSetVar(NULL, 0, web_conn, pcmd, pvar);
#if DEBUGSOO > 5
    else os_printf(" - none! ");
#endif
}
и где нибудь прототип:
Код:
/*
* Write httpvar to variable
*/
uint8 ICACHE_FLASH_ATTR parseHttpSetVar(
pHttpVar *ParentVar, uint8 ParentLen, 
WEB_SRV_CONN *web_conn, uint8 *pcmd, uint8 *pvar);
Ручками конечно то же могу добавить, но как бы освященное автором оно лучше было бы.
 

A_D

Active member
pvvx, а удалось ли побороть странную работу RTS\CTS выводов, которую описал тут или Вы их вообще не используете и сделали вывод RTS на таймере ? (в свое время удавалось на freemodbus под наши миландровские АРМы такое с таймером - работало вполне сносно до 128000 скорости, выше не проверял)
 
Последнее редактирование:

pvvx

Активный участник сообщества
pvvx, а удалось ли побороть странную работу RTS\CTS выводов, которую описал тут или Вы их вообще не используете и сделали вывод RTS на таймере ? (в свое время удавалось на freemodbus под наши миландровские АРМы такое с таймером - работало вполне сносно до 128000 скорости, выше не проверял)
Как описывал так и сделал. Не 100% но 95% :)
Первая демка: https://yadi.sk/d/E_TYGKB_mq224
Исходники пока зажал. Надо причесать, если пойдет...
Основа из описанного тут http://esp8266.ru/forum/threads/modbus-rtu-rs-485.529/#post-11711
~rs485_timeout~ указывает максимально время передачи или приема. Желательно ставить немного менее, чем назначена пауза ответа у запрощающего на Modbus TCP. При неответе устроства на RS-485 через эту задержку будет обработан следующий пакет для передачи из очереди. Максимальная очередь определена размером памяти. Примерно 500 пакетов может находиться в ожидании на передачу - прием ответа на них. Такой пока драйвер - для мультизадачки. Закидываем пакетами, а он исполняет, по мере очереди и вызывает функцию приема после каждого приема ответа. Есть возможность и туда включить fifo оветных пакетов (уже реализовано в драйвере, но для Modbus TCP шлюза не используется - сразу отсылает). Запросный пакет имеет ID - в ответе тоже есть тот ID, после которого принят ответный пакет... Таймаут на передачу может возникнуть при постоянном шуме на линии...
Если ничего не отсылается в rs485, то прием пакетов и передача в Modbus TCP всё равно работает. Выходит типа сниффер.
Пакет http://www.modbustools.com slave через FT2232 дает паузу перед ответом не менее 50 ms - тормоз :(
ModbusTest1.gif
После вывода последнего бита, сигнал RX_ENABLE на драйвер шины протягивается минимум на 24 бита (передел 32 при паузе в 3.5 символа). Затем уже вычисляется остаток на таймере. При скорости более 19200 ставится дополнительная фиксированная задержка. Она тоже частично протягивается на RX_ENABLE, остаток вычисляется на таймере. Эта протяжка от того, что по другому очень криво выйдет на ESP8266 и она задает минимальную задержку между символами сообщений (конкретнее - дискретом по 8 бит, по тому что только так умеет считать паузу аппаратный UART у ESP8266). Мешать протоколу она не должна, т.к. после сообщения следующее должно выйти не ранее полной паузы. Всё описано в теме ModBus RTU (RS-485)
 
Последнее редактирование:

pvvx

Активный участник сообщества
pvvx, понял, Спасибо - постараюсь вечером потестировать.
Там ещё не всё учтено... Полную версию с правильной отработкой очередей сообщений ещё доделываю...
-------------
Сделал и слепил пока так:
(RS-485 = 256000 bps - больше софт на компе не может)
Временная ссылка на использованную в видео тестовую прошивку -> https://yadi.sk/d/u0roQ8IZmuvf7
Тему другую что-ли открывать? В RS-485 и далее с ним "свалка" не особо главная уже :)
Надо уже функции ПЛК и встроенный в Web редактор программ делать...
Ядро RS-485 пашет до 1 мегабита, но проверить нечем. На низкую скорость - 1200 baud гонял в том, что на видео. Под рукой пока всё тормозное, а доставать и раскладывать старые тестовые платы - лень...
 
Последнее редактирование:

PycLan

New member
Добрый день!
aloika, в какой момент (в Вашем примере UARTCommander3) можно передавать из UART в WEB параметры Enable,speed,sensivity, setting_time, current_time?
 

PycLan

New member
Возможно проблемы с включением питания - сбросом и инициализацией.
Это возможно от путаницы старта после deep-sleep, для ускорения инициализации WiFi. Надо глядеть....
Сперва все работало, но как только закоментил не нужное в user_config.h, начались такие же проблемы. Откатился на 054a...
 

aloika

Active member
в какой момент (в Вашем примере UARTCommander3) можно передавать из UART в WEB параметры Enable,speed,sensivity, setting_time, current_time?
Честно говоря, не совсем понял вопрос. Пример в части UART->WEB работает так:

1. Заводим таймер, который через каждые 0,1 сек запускает parse_rx_buf(void)
2. Эта функция вычитывает приемный буфер UART и распарсивает то, что туда пришло за последние 0,1 сек.
3. Если туда пришла определенная ранее строка (а в этой строке содержатся все значения параметров), то заполняются поля структуры:

Код:
pcsw->enable=comm[2];
pcsw->speed=comm[3];
pcsw->sensivity=comm[4];
pcsw->curr_time=(comm[6]<<8)+comm[5];
pcsw->setting_time=(comm[8<<8)+comm[7];
Если туда пришло что-то не то, какой-то мусор или некорректное что-то, то поля структуры не меняются.

4. Теперь мы можем в любой момент прочитать поля этой структуры с тем, чтобы, например, отобразить их в WEB. Для этого "родную" функцию web_int_callback дополняем своей функцией. В самом конце web_int_callback пишем:

Код:
else swbd_web_int_callback(web_conn, cstr); //tcp_put('?');
Теперь можно определить свою функцию swbd_web_int_callback(web_conn, cstr) и прописать там свои колбэки. Можно, конечно, было всё это в основную функцию web_int_callback затолкать, но мне показалось красивее отделить "родное" (pvvx'а) от самодельного.

5. Определяем:

Код:
void ICACHE_FLASH_ATTR swbd_web_int_callback(WEB_SRV_CONN *web_conn, uint8 *cstr)
{
     if(!os_memcmp((void*)cstr, "swbd_", 5)) {
                      cstr+=5;
                      if(!os_memcmp((void*)cstr, "enable", 6)) tcp_puts("%u", pcsw->enable);
                      else if(!os_memcmp((void*)cstr, "speed", 5)) tcp_puts("%u", pcsw->speed);
                      else if(!os_memcmp((void*)cstr, "sensivity", 9)) tcp_puts("%u", pcsw->sensivity);
                      else if(!os_memcmp((void*)cstr, "setting_time", 12)) tcp_puts("%u", pcsw->setting_time);
                      else if(!os_memcmp((void*)cstr, "curr_time", 9)) tcp_puts("%u", pcsw->curr_time);
                      else tcp_put('?');
                          }
}
6. Ну и все. Теперь в тексте веб-странички можно написать, например, ~swbd_speed~, и на месте этой записи на реальной страничке отобразится текущая скорость.

Прилагаю доработанный пример. Он на основе более новой версии "свалки" и там в корне есть файл качалка.txt, где написано, что нужно изменить в исходной "свалке", чтобы получить эту функциональность. Таким образом, если хотите, можете легко адаптировать самую новую версию "свалки". Учтите только, что функционал TCP<->UART при этом отключается, так как мне он не нужен.

Там же пример странички (my.htm) c примером нового функционала.

Конечно, было бы, наверное, красивее из приемного буфера данные вычитывать по прерываниям, а не по таймеру. Но у меня ума не хватило, как это корректно сделать, положительного результата так и не смог добиться. Но меня и так устраивает, работает стабильно (при моей скорости поступления данных в UART).
 

Вложения

PycLan

New member
Спасибо, смотрю.
Просто отправляю для примера A5B50000000000000000, на странице ничего не меняется.
 

aloika

Active member
Ну тогда раскомментируйте в parse_rx_buf одну из строчек

//os_printf("%02x ",ch);
// uart1_put_char(ch);

и посмотрите, что реально вы принимаете в UART. До парсинга еще. Может, там совсем и не то, что вы отправляете.

Только потом обратно закомментируйте. А то это дело будет тормозить WEB.
 

PycLan

New member
Да в UART1 летит, то что отправляю с URT0, но на страницу это не доходит.
Отображает всегда дефолтные параметры: Enable: 0, speed: 4, sensivity: 2, setting_time: 15, current_time: 15.
 

aloika

Active member
Хм. У меня-то работает как-то... правда сейчас проверить не могу, но работало. В серийном устройстве прошивка именно эта, web-часть другая только.

ну выведите в уарт1 значения этих величин, раскомментируйте там

// os_printf("enable is %04x, speed is %04x, sensivity is %04x, curr_time is %04x, setting_time is = %04x\n" , pcsw->enable, pcsw->speed, pcsw->sensivity, pcsw->curr_time, pcsw->setting_time );

что будет писать?

посмотрите, может там в веб-части ошибка? оно может и не опрашивает? может я что-то там изменил когда...

Если не получится у вас, приду домой, проверю (залью этот веб). Но это часа через 4 будет, не раньше.
 
Последнее редактирование:

PycLan

New member
ну выведите в уарт1 значения этих величин, раскомментируйте там

// os_printf("enable is %04x, speed is %04x, sensivity is %04x, curr_time is %04x, setting_time is = %04x\n" , pcsw->enable, pcsw->speed, pcsw->sensivity, pcsw->curr_time, pcsw->setting_time );

что будет писать?
Тишина...
посмотрите, может там в веб-части ошибка? оно может и не опрашивает? может я что-то там изменил когда...
Enable: 0, speed: 4, sensivity: 2, setting_time: 15, current_time: 15 - а эти значения из ESP или web?
 

PycLan

New member
Получается, что почему-то даже на A5 условие не выполняется, не выводится ни одно сообщение STROKA- .. только копия передачи по uart1_put_char(ch);
Код:
uart1_put_char(ch);


         if ((ch==0xA5)&&(curr==0)) {comm[curr]=ch; curr++;  os_printf("STROKA-1\n"); continue;}
         else if ((ch==0xB5)&&(curr==1)) {comm[curr]=ch; curr++;  os_printf("STROKA-2\n"); continue;}
         else if ((curr>=2)&&(curr<9)) {comm[curr]=ch; curr++;  os_printf("STROKA-3\n"); continue;}
         else if ((curr==9)&&(ch==(uint8)(comm[2]+comm[3]+comm[4]+comm[5]+comm[6]+comm[7]+comm[8])))
                   {
             os_printf("STROKA-4\n");
...
 

aloika

Active member
Вот, всё работает.

В терминале в строке отправки надо писать $A5$B5$01$01$01$01$01$01$01$07
Если, конечно, этим терминалом пользуетесь.

Безымянный.png Безымянный1.png
 
Сверху Снизу