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

Modbus TCP / RTU RS-485 + WEB server

pvvx

Активный участник сообщества
Web интерфейс с Modbus TCP и шлюзом на RTU RS-485.
Исходники и прошивки (начиная с версии 0.5.6 исходники и прошивки объединены с TCP2UART)
Вложена программа создания диска для Web-страниц (Windows).
Описание переменных находится в WebVars.xlsx архива и в самой прошивке Web-сервера.
Основа на библиотеке малого Web-сервера обсуждаемого в теме Разработка ‘библиотеки’ малого webсервера на esp8266.
Отличия проекта Modbus TCP RTU RS-485 от Web/TCP2UART всего в файле include\user_config.h, файлах web-диска (папка WEBFilesRS485) и webvars_rs485.xlsx.
Переключение проекта с TCP2UART на MODBUS RS-485 производится в include/user_config.h
Код:
#define PROGECT_NUMBER 1
// 0 -> проект "TCP2UART"
// 1 -> проект MODBUS-"RS485"
Создание файла диска в make_webfs_rs485.bat или с помощью WEBFS22.exe, установив опции каталогов и других переменных.

1) При прошивке всегда ставим размер Flash 512 Кбайт (4Mbit)! Реальный размер определяется автоматически самой прошивкой.
2) Если Flash на модуле более 512 Кбайт, то после подключения к AP "ESP8266" требуется заливка диска программой WEBFS22.exe или эксплорером набрав http://192.168.4.1/fsupload. Можно записать WEBFiles.bin и программатором по адресу 0x80000.

При первом старте, после прошивки программы или сбросу установок, имеем AP станцию:
SSID/Name: ESP8266
Password: 0123456789
Режим доступа к AP по умолчанию 'OPEN'.
Имя AP и её пароль является именем и паролем для входа на "защищенные" страницы сервера и используется для записи диска по http://192.168.4.1/fsupload.

Настройки Web и прочие аналогично обсуждаемому в теме "Разработка ‘библиотеки’ малого webсервера на esp8266".

ESP имеет встроенное устройство Modbus. Номер этого устройства задается на странице настройки. Описание modbus переменных вложено на первой странице по ссылке "Info" или смотрите WebVars_RS485.xlsx (он вложен в архив). Данное устройство имеет 1000 ячеек для обмена между интерфейсами. Доступ к ним возможен из Modbus TCP, со стороны Modbus RTU RS-485 и через Web. Пример обращения из Web к переменным дан в http://192.168.4.1/sample.htm (ссылка в Web: "Debug and Test" -> Page Sample).

Варианты подключения полудуплексного интерфейса по UART (RS-485) к ESP8266:
1) К микросхеме драйвера шины RS-485 - без развязки: ADM3072E или SN65HVD12D, с развязкой: ADM2483BRWZ, и т.д. Тогда используются 3 сигнала от ESP: RX, TX, WR/RD_ENABLE
2) Напрямую c внешним устройством, как RX и TX. Линия TX, при больших скоростях, может потребовать дополнительной подтяжки к +3.3В, т.к. во время приема переключается как вход. Сигнал WR/RD_ENABLE не используется.
3) Напрямую c внешним устройством по одному проводу. Линия TX соединяется с RX. Сигнал WR/RD_ENABLE не используется. Но вешнее устройство тоже должно уметь работать по одному проводу.


Сигнал WR/RD_ENABLE (направление передачи) выставляется в "1" когда идет передача c вывода TX. Всё остальное время (чтение данных с RS-485) на нем "0".

Далее пытаемся из ESP8266 сделать "Панель Оператора" с макросами и обращениями к шине RS-485 как master. Пока реализована простая схема работы с "транзакторами", но прорабатывается как и что сделать для расширенного варианта и приветствуются разные предложения по этому вопросу.

---

Пример работы с внутренними переменными Modbus:
ModbusTst.gif
modbus_data.gif
HTML:
Write Mdb[68] string 'Hello!'<br>~mdba68=Hello!~
Read Mdb[68] string: '~mdba68~'<br>
<hr>
Write Mdb[0] dword -12345678<br>~mdbd0=-12345678~
Read Mdb[0] unsigned dword = ~mdbud0~<br>
Read Mdb[0] signed dword = ~mdbsd0~<br>
Read Mdb[0] hex dword = 0x~mdbhd0~<br>
Read Mdb[0] unsigned word = ~mdbuw0~<br>
Read Mdb[1] unsigned word = ~mdbuw1~<br>
Read Mdb[0] signed word = ~mdbsw0~<br>
Read Mdb[1] signed word = ~mdbsw1~<br>
Read Mdb[0] hex word = 0x~mdbhw0~<br>
Read Mdb[1] hex word = 0x~mdbhw1~<br>
<hr>
Write Mdb[4] 1,2,3,4,,555<br>~mdbw4=1,2,3,4,,555~
Mdb[4] = 0x~mdbhw4~<br>
Mdb[5] = 0x~mdbhw5~<br>
Mdb[6] = ~mdbxw6~<br>
Mdb[7] = ~mdbxw7~<br>
Mdb[8] = 0x~mdbhw8~<br>
Mdb[9] = 0x~mdbhw9~<br>
ESP8266 на шине Modbus RTU RS-485 как slave и данные в буфере обмена mdb[0..1000] имеют доступ со стороны внешнего устройства... Так-же доступ к любым внутренним переменным Modbus ESP имеется через Modbus TCP или Web.

Help:
Вики: Modbus
Установки Modbus.
Буфер обмена на 1000 ячеек Modbus ESP.
Modbus транзакторы.
Про Modbus буфер RTC памяти

 
Последнее редактирование:

PycLan

New member
Для решения задачи контроля-управления через web получается такая схема:
UART0(MASTER) <> ESP 100-ячеек (SLAVE) <> Modbus TCP (MASTER)
Железка на UART0 все время сканирует значения в заданных ячейках и в зависимости от их значения выполняет команды по заданным функциям (выполнить что-либо, считать температуру и поместить в заданную ячейку и т.д.)
Web интерфейс как бы является самым главным в этой цепочке типа Super master, по действиям пользователя он заполняет и считывает ячейки по заданному алгоритму и отображает все это дело на странице.

Все хорошо, но железка висящая на UART0 вынуждена все время обращаться к ESP.

Хорошо бы в нашем случае иметь такую схему:
UART0(SLAVE) <> (MASTER)ESP 100-ячеек (SLAVE) <> Modbus TCP (MASTER)

Для работы такой схемы нам нужно выделить ячейки:
Ячейки для передачи ведомому UART0(SLAVE)
1 - для адреса устройства
2 - команды (функции)
3 - данных
Ячейки для приема ответа от ведомого UART0(SLAVE)
1 - для адреса устройства
2 - команды (функции)
3 - данных

Дальше алгоритм такой:
Web интерфейс по действиям пользователя или по заданному алгоритму заполняет ячейки для передачи в UART0(SLAVE).
ESP для себя выставляет флаг – «новые данные для передачи».
Web ждет ответа от UART0(SLAVE) - появления в ячейке адреса (в ячейках ответа) устройства, которому была отправлена команда (функция).
После заполнения последней ячейки Web-ом, ESP отправляет пакет устройству UART0(SLAVE) с заданным в ячейке адресом.
ESP сбрасывает флаг – «новые данные для передачи».
UART0(SLAVE) отвечает с результатами команды (функции).
Web интерфейс получив ответ, действует по своему алгоритму.

В пакете ответа, можно задавать команду для ESP в какие из 100 ячеек скопировать ответ из ячейки(ек) приема данных…
Ну или в зависимости от номера функции, ESPвсегда будет копировать ячейку(и) данных в назначенные ячейки из 100.
 
  • Like
Реакции: TRO

pvvx

Активный участник сообщества
PycLan - в вашей схеме отпадает логирование и набор статистики. А я пока к этому иду. Мне нужен набор с десятка датчиков длинною в год и дискретом усредненных точек от получаса минимум. Flash хватает и на более детальный лог - с шагом в минут 5 (вроде пересчитывал для 4 и 16 Мегабайт Flash - до истечения гарантированных количеств записи/стирания на это уйдут десятки лет).
А с мастером на RS-485 пока не решено, кроме варианта Modbus TCP. Там требуется описание заданий, которые будут циклически выполняться... к примеру по таймеру. Тогда web ничего не ждет - данные всегда опрощены.
 
Последнее редактирование:

PycLan

New member
PycLan - в вашей схеме отпадает логирование и набор статистики.
Так мы выбираем в настройках - UART0 MASTER или SLAVE, само сабой мы не делаем фиксированно UART0 слейвом.
Или речь идет о том, что устройство на линии 485 будучи SLAVEом не может само послать данные лога в ESP?
Так и 10 датчиков будучи MASTER не могут посылать данные логов, бо коллизия будет.
Тут само сабой напрашивается Slave и таблица настройки по Web: адрес железки, период опроса и т.д.
Аж на 247 адресов если стремится к универсальности.
Ну и таймер, как Вы писали, вызывающий процедуры опроса датчиков по заданному времени и адресу.

Или городить умные датчики, которые увидев передачу данных, от датчика с адресом СВОЙ АДРЕС - 1, начинают свою передачу лога.
Тоды первому датчику нужно знать номер последнего, ну надежность такой цепи уменьшается как у гирлянды, сгорает одна лампочка, тухнет вся гирлянда.
Для исключения затыка, каждый "живой" датчик, после любой передачи на линии, запускает таймер ожидания на время, равное передаче лога одним датчиком умноженное на СВОЙ АДРЕС – АДРЕС ПОСЛЕДНЕГО АКТИВНОГО ДАТЧИКА. Если за время ожидания в цепочке есть другие "живые" датчики, таймер обнуляется и заряжается по новому до тех пор пока СВОЙ АДРЕС - 1.
Тогда web ничего не ждет - данные всегда опрощены.
Это как вариант чтобы web не ждал и таймер не нужен.
В пакете ответа, можно задавать команду для ESP в какие из 100 ячеек скопировать ответ из ячейки(ек) приема данных…
Ну или в зависимости от номера функции, ESPвсегда будет копировать ячейку(и) данных в назначенные ячейки из 100.
Web просто посылает команду, а потом продолжает считывать свои ячейки из 100.
ESP сама положит ответ в нужные ячейки.
 
Последнее редактирование:

pvvx

Активный участник сообщества
Это как вариант чтобы web не ждал и таймер не нужен.
Панель оператора видели? Вот в ней и задаются макросы опроса и прочее. В этом направлении и думаю, как сделать, но экран у нас в WEB - это всё различие от обычной пром. панели оператора. И не надо никаких таблиц на 247 устройств.
О - для примера вспомнил самую дешевую - Samkoon. Там макросы вообще только на СИ. Создается проект, транслируется и заливается в панель....
Если сильно постараться, то и редактор на java или web-flash можно написать и закинуть прямо в Web ESP8266.
Что вас всё тянет на решения, подобные АрДурине? Нужно всего-то до двух макросов - один исполняющийся в цикле, другой по таймеру. "Велосипед" давно изобретен и позволяет делать всё. Но у нас не проф. панель, по тому будут некоторые ограничения. В основном они связаны с перерисовкой страницы на Web, когда сменились данные... но это решаемо на javascript.
А пока видно, что вы не знакомы с современными панелями оператора и их решениями вопросов как и что делается для многопользовательского опроса и отображения данных.
---
Более подробно.

Обычно существуют такие макросы:

1) Исполняющийся по инициализации.

2) Работающий в цикле

3) Срабатывающий по таймеру

4) Срабатывающий по событию (изменения в ячейке)

Работа с шиной Modbus обычно осуществляется по макросу типа 3 или 4. Для коммуникации задается: адрес устройства, команда (чтение или запись), адрес операндов и их ко-во, адрес приема ответа. Т.е. всего до 5 параметров, типа – mdb(2, 6, 92, 2, 90) -> запросить устройство 2, команда Modbus 06, передаваемые значения 2 шт с адреса 92, ответ положить в 90.

Например на странице взводим бит в N-ой ячейке, тогда по нему, в главном цикле опроса, вызывается передача транзакция по Modbus и бит сбрасывается.

Но макросы требуют поддержки элементарной математики с ячейками и надо писать интерпретатор этих скриптов. Вот и всё.
 
Последнее редактирование:

pvvx

Активный участник сообщества
Кто нибудь уже испытал текущую прошивку? Какие ошибки есть и прочее?
От ответов зависит создавать или нет репозиторий на git с исходниками. Может оно никому не нужно?
 
Последнее редактирование:

aloika

Active member
Кто нибудь уже испытал текущую прошивку? Какие ошибки есть и прочее?
Тема мне очень интересна, дозреваю.
Надо бы мне еще осознать область применения этой разработки.

Сейчас я вижу следующее:

1. Датчик/исполнительное устройство с настройкой, допустим по web и передачей данных(приемом команд) по RS-485 Modbus RTU. Тут сразу вопрос - я пока не уловил, где RS-485-то? Надо что-то внешнее ставить или прямо к ESP подключать проводки "А" и "В" (простите за наивность)? Тогда устройство Slave, все понятно, а в качестве мастера - контроллер, или компьютер со скада-системой, или компьютер с OPC-сервером, допустим, и каким-то самописным интерфейсом (я так делал, интерфейс на Delphi был, собственно вот http://galsen.ru/catalog/set/52/253/1145/ и вот http://galsen.ru/catalog/set/40/233/1110/).

2. Панель оператора, о чем вы говорили. Это круто, но непонятно :) Она же должна быть Maser'ом, да? Ну и потом. Надо делать как минимум две условные части - интерфейс и логику работы, эти самые макросы. Сделать красивый интерфейс - задача та еще, то, что делается в Делфи за 15 минут, в веб надо городить и городить... Т.е. не быстро и не просто, а если стоит задача еще и корректного отображения на разных экранах, то вообще. Т.е. чтобы панель "пошла в массы", надо городить какую-то систему быстрого создания интерфейсов. Ну это чисто веб-овская задача, конечно, к теме отношение опосредованное имеет, но тем не менее, это важно. Если я буду месяцы интерфейс в CSS/HTML/JS городить, зачем такая панель нужна. С макросами, наверное, даже попроще будет.

3. Веб-интерфейс для любого устройства, подключенного к ESP по UART (условного Ардуино). Тут да, задача сводится к написанию опять же интерфейса, внутрь прошивки ESP лезть не надо. Зато со стороны устройства в UART нужно подавать корректные команды Modbus, т.е. надо их там как минимум прописывать исходящие и корректно парсить входящие.
 

pvvx

Активный участник сообщества
1. Датчик/исполнительное устройство с настройкой, допустим по web и передачей данных(приемом команд) по RS-485 Modbus RTU. Тут сразу вопрос - я пока не уловил, где RS-485-то? Надо что-то внешнее ставить или прямо к ESP подключать проводки "А" и "В" (простите за наивность)? Тогда устройство Slave, все понятно, а в качестве мастера - контроллер, или компьютер со скада-системой, или компьютер с OPC-сервером, допустим, и каким-то самописным интерфейсом (я так делал, интерфейс на Delphi был, собственно вот http://galsen.ru/catalog/set/52/253/1145/ и вот http://galsen.ru/catalog/set/40/233/1110/).
Варианты подключения:
1) К микросхеме драйвера шины RS-485 - без развязки: ADM3072E или SN65HVD12D, с развязкой: ADM2483BRWZ, и т.д. Тогда используются 3 сигнала от ESP: RX, TX, RD/WR_ENABLE
2) Напрямую c внешним устройством, как RX и TX. Линия TX может потребовать подтяжки к +3.3В, т.к. во время приема переключается как вход. Сигнал RD/WR_ENABLE не используется.
3) Напрямую c внешним устройством по одному проводу. Линия TX соединяется с RX. Сигнал RD/WR_ENABLE не используется.

К вашему проекту имеющаяся прошивка уже подключается как беспроводный удлинитель - через WiFi, а соединение делаете по Modbus TCP.
2. Панель оператора, о чем вы говорили. Это круто, но непонятно :) Она же должна быть Maser'ом, да? Ну и потом. Надо делать как минимум две условные части - интерфейс и логику работы, эти самые макросы. Сделать красивый интерфейс - задача та еще, то, что делается в Делфи за 15 минут, в веб надо городить и городить... Т.е. не быстро и не просто, а если стоит задача еще и корректного отображения на разных экранах, то вообще. Т.е. чтобы панель "пошла в массы", надо городить какую-то систему быстрого создания интерфейсов. Ну это чисто веб-овская задача, конечно, к теме отношение опосредованное имеет, но тем не менее, это важно. Если я буду месяцы интерфейс в CSS/HTML/JS городить, зачем такая панель нужна. С макросами, наверное, даже попроще будет.
Для любого устройства требуются свои страницы с картинками или без и своими подписями. Все равно придется рисовать их в HTML самому, под конкретное устройство. Сложности с выводом переменных и кнопками в HTML + javascript нет.
3. Веб-интерфейс для любого устройства, подключенного к ESP по UART (условного Ардуино). Тут да, задача сводится к написанию опять же интерфейса, внутрь прошивки ESP лезть не надо. Зато со стороны устройства в UART нужно подавать корректные команды Modbus, т.е. надо их там как минимум прописывать исходящие и корректно парсить входящие.
Ардуино не умеет работать с Modbus RTU. Она не умеет считать задержки в 3.5 символа.
 

A_D

Active member
pvvx, пробовал не последнюю версию еще - никаких замечаний не возникло касательно работы прошивки. Есть же мысли по поводу логики работы - в основном присоеденяюсь ко 2му посту из темы.
Великолепным решением было бы создание моста-преобразователя Modbus-RTU в Modbus-TCP, с ограничениями конечно на количество обрабатываемых ячеек по причине того, что в ESP8266 будет сразу Slave TCP и Master RTU с общей таблицей ячеек. А в коде почему бы не задавать сразу дефайнами какое количество и чего может обрабатывать ESP по такому типу:

Код:
#define M_DISCRETE_INPUT_START        0
#define M_DISCRETE_INPUT_NDISCRETES   10

#define M_COIL_START                  0
#define M_COIL_NCOILS                 10

#define M_REG_INPUT_START             0
#define M_REG_INPUT_NREGS             10

#define M_REG_HOLDING_START           0
#define M_REG_HOLDING_NREGS           10
из чего сразу ясен диапазон и начальные адреса Slave устройств с которыми работать можно.

Вот кстати два примера, на которых делал мост на арме, без ОС даже (в связи с чем возникли проблемы с необработанными запросами - они просто игнорировались мастером, но это к слову) USB - Modbus сеть. В контроллере Modbus Master циклично опрашивает все Slave и обновляет у себя данные в регистрах Input и т.д. По запросу с USB выдает нужную ячейку, а так же если запрос на запись в Slave - то цикл приостанавливается и производится запись в конкретное устройство, далее всё по кругу.. топорно, но работает - проверено на имитаторе с 5ю датчиками на шине и 128000 скоростью.

И попробую помочь, чем смогу - вот мною найденные примеры когда надо было реализовать Modbus Master (оказалось что это действительно проблема, в основном только детские примеры тяп ляп под адурино и находились... в гит хабе вообще куча копий одного и того же было..):
Первый пример с китайской RTOS. - вначале он мне показался замудреным, но в итоге его и переделал под не RTOS вариант с проблемой возникшей выше из этого.
Второй вариант - этот мне посоветовал автор первого проекта выше, как пример реализации без RTOS - из него взял некоторые идеи, но что то там не так было, не помню уже..
 

pvvx

Активный участник сообщества
pvvx, пробовал не последнюю версию еще - никаких замечаний не возникло касательно работы прошивки.
Там есть ошибки/недочеты, даже в прошивке v 0.0.2. В git исходниках уже изменен порядок укладки Char от String, на обратный. Но тут как кому - это вроде не нормировано...
Есть же мысли по поводу логики работы - в основном присоеденяюсь ко 2му посту из темы.
А уже всё решено. Надо только писать и отлаживать... Основа описана в посту выше со слов "Более подробно".
Реализация натупейшая:
Для задания запросов организуем (хоть в памяти переменных) такие N структур для создания транзакций с полями:
  1. Адрес устройства (uint8)
  2. Номер команды(uint8)
  3. Кол-во слов передачи(uint8)
  4. Адрес данных во внешнем устройстве(uint16)
  5. Адрес данных для приема во внутреннее устройство(uint16)
К примеру возьмем 16 таких структур и к ним ячейка с 16 битами их старта. -> Если бит взведен, то стартует указанная транзакция. Низкоуровневый драйвер RS-485 уже с пеленок научен делать запрос и принимать ответ. Так-же у него есть очередь обработки поступающих транзакций с глубиной до чертиков Транзакция так назовем - это - сделать передачу и принять или нет ответ - приема нет, если отсылка была к нулевому устройству (это тоже уже драйвер разгребает на ходу). Так-же он разгребает ошибки приема и тайм-ауты. Короче если принята ошибка, то флаг старта не сбрасывается, а взводится флаг ошибки в аналогичном "слове ошибок". Ну тут уж как будет лучше...
16 таких структур - это всего 128 байт. Проектов, где опрос требовал большее разнообразие транзакций - не видел, тем более что эту таблицу можно менять на ходу. Это с самим приемом-передачей, а запускаются они по макросу таймера или в главном циклическом макросе. Временно макросы можно не делать, а сделать это как сделано в панелях оператора - просто вызывается процедура c передачей в параметрах указателя на область обмена (ну те 100 или далее 1024 ячейки). А процедура самым беспечным образом транслируется СИ компилятором и впихивается в проект.
Вот например, что был за макрос в Samkoon:
Код:
#include "MacroInit.h"

#include <time.h> // это я приписал для перерасчета time_t
void Macro_main(IN *p)
{
    MarcoInit
    if((unsigned int *)(LocalWord+1114) != 0) {
        strftime((char *)(LocalWord+300),10+10+4,"%d.%m.%Y %X", gmtime((time_t *)(LocalWord+1114)));
    }
    fvcc = vcc*0.000977; // пересчет VCC в float (Вольты) (fvcc и vcc назначены и привязаны к ячейкам  в другом месте... тут это не важно)
}
LocalWord - задано как p->pLW (дефайном в MacroInit.h) - это указатель в структуре IN на начало ячеек pLW (unsigned short).
Macro_main задано вызывать каждые 200 ms.
В 1114 адрес по таймеру (1 sec) командой коммуникации считывается блок из ESP (id=50) c 100 адреса 16 ячеек в панел в адрес 1100:
1.Source Address:50:3x100-->Destination Address:LW1100,Transmission mode:Word,Time triggered:rate1s,Transmitting data size=16
2.Source Address:50:3x68-->Destination Address:LW1068,Transmission mode:Word,Time triggered:rate1s,Transmitting data size=32
Второй считывает строку текста в 68...99 ячейках в 1000...
Страница тупо отображает данные из ячеек. На этом всё.
В итоге получаем в панели это:
 
Последнее редактирование:

A_D

Active member
pvvx, понял идею. Получается если TCP master опрашивает к примеру Input регистр 1 Slave устройства адресом = 2, то для ESP это событие с параметрами и вызывается(срабатывает) макрос типа 4, после его выполнения и выдается ответ TCP мастеру, верно ?
Но тогда не понял - зачем 3го типа макросы с цикличным опросом ? (если только в web к примеру задать такой макрос и тогда значение конкретной ячейки будет всегда максимально актуальным при запросе по TCP или просмотру по web, так?)

з\ы у меня тоже чего то не грузило архивы... говорит ошибка и всё. порылся, нашел оригиналы репозиториев на гитхабе - благо сохранились.
 

pvvx

Активный участник сообщества
A_D - очередь запросов транзакций и счас работает, не знаю как от ней избавиться - она иногда мешает, если в TCP сыпятся запросы чаше, чем таймаут при не ответе устройства :) У глупой программы приема возникает путаница ответных сообщений - нарушение очереди - запрос-ответ, хотя ей приходит правильный ID транзакции (Transaction Identifier) из запроса Modbus TCP :( Ну это я ещё не прокопал со всех сторон - врет сторонний софт или так делать незя :)
понял идею. Получается если TCP master опрашивает к примеру Input регистр 1 Slave устройства адресом = 2, то для ESP это событие с параметрами и вызывается(срабатывает) макрос типа 4, после его выполнения и выдается ответ TCP мастеру, верно ?
Но тогда не понял - зачем 3го типа макросы с ...
У нас достаточно 3 типа:
1) Стартовый - макрос/процедура инициализации. Он прописывает необходимые ячейки и задает параметры передач/транзакций.
2) Вечно исполняющийся макрос/процедура в цикле. Она опрашивает значения в ячейках и может запустить какую транзакцию, если надо по результатам или она задана пользователем с web путем смены какого бита/ячейки...
3) Таймерный макрос/процедура. К примеру исполняющийся каждые 100 ms. Он может крутить счетчик в ячейке и делить далее. Обычно опрашивает готовность, стартует транзакции и обрабатывает принятые значения в формат для вывода уже на HTML = просто перекодирует принятые значения из принятой ячейки в другую - для вывода. Это можно делать и в 2). Перекодировка и перестановка необходима, т.к. это прослойка отделяющая hard устройства исполнителя (slave) от операторской части. При смене оборудования меняется только этот код перекодировщика в соответствии с аппаратной частью другого slave... Но можно и без этого... кому как :)
Про то, что очередь (FIFO) запросов к низкому уровню драйвера RS-485 уже сделана - это понятно? Она организуется в Heap связным списком. Тест показал, что нормально всё пашет при расходе за 30 килобайт :) а это более 500 заготовок средненьких транзакций к драйверу уже в очереди на обслуживание... Ещё разумно не ограничил его. А то при отрыве slave, через тайм-уаты в 200 ms это выйдет ожидание опустошения очереди в 100 секунд :eek:
Сейчас напихивает FIFO только это https://github.com/pvvx/esp8266rs485/blob/master/app/mdbtcp/mdbrs485.c
А всё напиханное обрабатывает https://github.com/pvvx/esp8266rs485/blob/master/app/driver/rs485drv.c исключительно по прерываниям. Там ещё есть дырка... встает, при невыясненных причинах... но для этого надо ломать саму шину RS-485 - отрывать провода на ходу и т.д. ... :) Какое-то прерывание обрабатывается наперед правильного течения - это выловлю со временем, когда буду оптимизить его и дописывать для master...
 
Последнее редактирование:

pvvx

Активный участник сообщества
Сделал минимальную версию master. Пока тестирую и добиваю мелочи - а их ещё много.
Минимальная, т.к. пока 8 управляемых приемо-передатчиков (транзакторов :) ) и никаких скриптов - всё можно решить через web.
Транзакторы подключаются к таймеру (задается), каждый со своим временем (циклом) срабатывания отсылки новой транзакции с приемом. По таймеру учитывает и тай-ауты, если внешнее устройство не отвечает...
Так-же у каждого есть ячейка-флаг при записи в которую происходит одиночный пуск вручную.
Всё задается через Web или прямую загрузку бинариком общей памяти, вместе с установками транзакторов.
Пока остановился на 1000 общих ячейках + 8 штук транзакторов по 10 ячеек каждый (там находятся всякие конфиги для них - описание полностью - позже).
Через web транзактор задается примерно так: mdbt7=1,16,10,300,68,10 - это значит задать 7-й транзактор для обращения к утройству N1, команда 16 (Preset Multiple Registers), 10 штук регистров, запись во внешнем устройстве в адрес 300, с 68 адреса в нашем устройстве, 10 - делитель таймера в 50 мсек, а раз задан период - значит работать автоматически и по данной команде сразу старт. Если проще перевести - это значит записывать во внешнее устройство N1 по адресу 300 каждые пол секунды десять значений с нашего буфера с 68 ячейки. Так-же вешаем и другие команды приема и передачи, а на Web странице делаем отображение значений. Если надо одиночно или принудительно-внеочередно от таймера запустить какую транзакцию - записываем передаваемые данные в заранее размеченную область командой mdbwADDR=x1,x2,x3,... до 32 и пишем mdbw1010=1 - запустит транзактор N 1 (8 шт конфигов их идут последовательно с 1000 адреса по 1080, с шагом 10 ячеек)...
Вся память (кроме системных регистров) в 1080 общих регистров выгружается в бинарник mdb.bin. Его можно заполнить и положить в папку диска web и в init.ini написать mdbfini=имя_бинарного_файла. Тогда при старте модуля загрузится уже готовый конфиг для всего процесса... Можно и в init.ini прописать и mdbwADDR=x1,x2,x3,... mdbdADDR=x1,x2,x3,...
Во всех командах web с списками значений, типа ~a=1,2,3,,,6,~ можно пропускать значения. В данном примере 4 и 5 и 7 пропущены - значит значения содержащиеся в памяти позиций 4 и 5 и 7 не будут изменены.
Примерно такое выходит и скоро будет с уточнениями. Пишите предложения - может что ещё влепить... пока скриптов нет (а их возможно для большинства задач и не будет требоваться вообще :) )
 
Последнее редактирование:

A_D

Active member
pvvx, маленькая заметка по схеме из Вашего репозитория - у Вас на схеме перепутаны входы на 485 драйвере..
 

Вложения

pvvx

Активный участник сообщества
pvvx, маленькая заметка по схеме из Вашего репозитория - у Вас на схеме перепутаны входы на 485 драйвере..
Спасибо - заменю.
Текущий тест:
tst1.giftst2.gif tst3.gif
Вроде всё работает...
Скинуто в git... Жду вопросов :)
 
Последнее редактирование:

pvvx

Активный участник сообщества
Откопал тут "Owen Модуль ввода аналоговый МВА8"...
Тормоз однако. Паузу в 3.5 символа не понимает:
tst_owen_mba8_err.gif
но если с задержкой, то катит:
tst_owen_mba8.gif
Всё не по спецификации. Придется наверно задержки вставлять с ручным управлением...:mad:
------
Вставлено как Add msg pause
 
Последнее редактирование:

pvvx

Активный участник сообщества
Крайняя сборка не собирается. Нет файла mdbtab.h
Да, затерялся... Уже на месте.
Чтение и отображение показаний на страничку продержалось целую ночь. Но к устройству на modbus не подключены все сенсоры - не домашний оно, просто использовал для тесту:
tst4.gif
Со slave устройства на modbus через "транзактор" mdbt0=1,4,46,100,0,5,0 читается 46 переменных в память ESP 4 раза в секунду, а на страницу отображается уже через запрос переменных в mdb.xml с приводом к float... За ночь ошибок транзакций не накоплено. Кнопок управления пока не стал лепить - простой тест... Кнопка делается к примеру так:
http://sesp8266/web.cgi?mdbw200=0,0,1&mdbt1=1,16,3,200,200,0,0
Это чудо значит, записать 3 ячейки по адресу 200 и передать их в slave с id 1 тоже по адресу 200.
 
Последнее редактирование:
Сверху Снизу