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

Modbus TCP / RTU RS-485 + WEB server

Dmitry P

New member
pvvx, спасибо за очередной классный проект! Ветку вроде перечитал, но не совсем понял, как работает в режиме шлюза RTU - TCP в части трансляции запросов. Используются фиксированная структура регистров на стороне TCP и конфигурируемая на стороне RTU, либо запросы транслируются с изменением заголовков и буферизацией?
 

Alex

Member
Я не большой специалист в эклипсе.
На этот Ваш проект он так ругается:
Program "xtensa-lx106-elf-g++" not found in PATH esp8266rs485 Project Properties, C++ Preprocessor Include.../Providers, [CDT Cross GCC Built-in Compiler Settings] options C/C++ Scanner Discovery Problem
Program "xtensa-lx106-elf-gcc" not found in PATH esp8266rs485 Project Properties, C++ Preprocessor Include.../Providers, [CDT Cross GCC Built-in Compiler Settings] options C/C++ Scanner Discovery Problem

Хотя все нормально собирается. Глаза просто мозолит :). Как это поправить? Или забить?
 

pvvx

Активный участник сообщества
pvvx, спасибо за очередной классный проект! Ветку вроде перечитал, но не совсем понял, как работает в режиме шлюза RTU - TCP в части трансляции запросов. Используются фиксированная структура регистров на стороне TCP и конфигурируемая на стороне RTU, либо запросы транслируются с изменением заголовков и буферизацией?
Дописал в прошлом посту.
А со стороны TCP esp всегда выглядит как slave c указанным адресом (id). Всё остальное из TCP соединения просто проходит на RS-485 и обратно.
Переключение master/slave относится только к RS-485 и работе "транзакторов" (в slave они отключены).
На этот Ваш проект он так ругается:
Program "xtensa-lx106-elf-g++" not fo...
Хотя все нормально собирается. Глаза просто мозолит :). Как это поправить? Или забить?
Не знаю, но там два варианта сборки. В данном проекте пока работает сборка только через Makefile. До другого - с автоматическим созданием Makefile средствами еклипсы пока не добрался (не поправил под этот проект) - может он и орет... и у меня такого нет.
 
Последнее редактирование:

Dmitry P

New member
Дописал в прошлом посту.
А со стороны TCP esp всегда выглядит как slave c указанным адресом (id). Всё остальное из TCP соединения просто проходит на RS-485 и обратно.
Переключение master/slave относится только к RS-485 и работе "транзакторов" (в slave они отключены).
Номер слейва тоже транслируется из TCP в RTU и должен совпадать и в TCP и в RTU?
 

pvvx

Активный участник сообщества
Номер слейва тоже транслируется из TCP в RTU и должен совпадать и в TCP и в RTU?
Да. А как иначе? Иметь таблицу перекодировок всех 248 slave? :confused:
У нас bridge (мост) Modbus TCP <-> Modbus RTU RS-485, а не просто пересылка к одному устройству. Например сообщение с id = 0 пройдет всем (и ESP). Не обращайтесь к другим устройствам с TCP - TCP будет работать только с переменными ESP.

Если RTU у ESP master, то с TCP ожидается только второй master. Шина RTU распределяется на обоих - она имеет fifo на транзакции (передача-ответ) до 20 килобайт. Запросы и ответы к ESP не проходят RTU <-> TCP, т.к. выбираются из потока ESP.

Если внешнее устройство на RS-485 master, ESP slave, на TCP должны быть тоже slave. Запросы и ответы к ESP не проходят из RTU в TCP. Но тут с TCP ещё не проработано до конца. Всё в прогрессе... мелочей ещё много - названия кое как в HTML и т.д... :)

По принципу работы ориентируемся на такую схему:
Сделали в своем внешнем slave контроллере область данных для передачи и они всегда, несколько раз в секунду будут дублированы в том буфере обмена ESP (master). И наоборот - объявленный для передачи блок в буфере ESP будет записан в slave. По тому какие байты, какие там строки - пофигу. Они будут в памяти обоих устройств в автоматическом, заданном заранее режиме. Передача отдельных кусков/изменений значений/переключений на slave по запросу из web доступно всегда.
 
Последнее редактирование:

Dmitry P

New member
Т.е. мост получается прозрачным, если использовать прошивку с ESP в качестве WIFI удлинителя для контроллеров с RS-485 modbus slave?
Modbus TCP master может читать любые регистры в RTU RS-485 slave, раз идет трансляция?
И как, кстати, ESP будет различать, из внутренних переменных брать, или в rs-485 посылать? По slave id?

Сейчас идут http://www.ebay.com/itm/381374648970?_trksid=p2057872.m2749.l2649&ssPageName=STRK:MEBIDX:IT , проверю как будет работать с пром.оборудованием.
 

pvvx

Активный участник сообщества
Т.е. мост получается прозрачным, если использовать прошивку с ESP в качестве WIFI удлинителя для контроллеров с RS-485 modbus slave?
да.
мост получается прозрачным и если использовать прошивку с ESP в качестве WIFI удлинителя для контроллера master на RS-485, даже если на шине RS-485 есть и ещё slave. Тут одна пока недоделка - TCP пока не обучен быть клиентом, т.е. сам не выходит на связь. Это позже приделаю.
Получается аналог - как будто к шине RS-485 включен ещё провод - разветвление. И таких контролеров (мостов, по типу ESP) на шине RS-485 может быть 247 штук и ещё как sniffer-ы на TCP. Но master в системе один.
Так-же может работать практически бесконечная цепь из звеньев RS-485<->ESP<->TCP<->ESP<->RS-485 - ограничение только тайм-аут ответа :)

Modbus TCP master может читать любые регистры в RTU RS-485 slave, раз идет трансляция?
да.
И как, кстати, ESP будет различать, из внутренних переменных брать, или в rs-485 посылать? По slave id?
да. Это же modbus - id всегда указывает устройство к которому обращается master и в системе не может быть второго устройства с id совпадающим с ESP.
Сейчас идут http://www.ebay.com/itm/381374648970?_trksid=p2057872.m2749.l2649&ssPageName=STRK:MEBIDX:IT , проверю как будет работать с пром.оборудованием.
А где там направление шины RS-485 - прием или передача? Тупо по активному сигналу TX? Плата то не дуплексная - нет раздельных входов и выходов RS-485.
 
Последнее редактирование:

Dmitry P

New member
А где там направление шины RS-485 - прием или передача? Тупо по активному сигналу TX? Плата то не дуплексная - нет раздельных входов и выходов RS-485.
Посмотрел фотки внимательнее, скорее всего, там стоит MAX 13487, у которого есть некий блок State machine, который определяет направление передачи
вот что пишут по практике
http://we.easyelectronics.ru/GYUR22/max13487-part2.html
 
Последнее редактирование:

WebMiCo

New member
Круто у Вас, но крайне не хватает инструкции с картинками по логике работы. И немного не логично (в стиле ардуино;-). На мой взгляд подобное должно быть в таких вариантах:
1)МодбусТСП как сервер, ESP транслирует все запросы в RS как мастер - использовать для подключения своих подделок к WiFi. Для этого достаточно моего скетча.
2)МодбусТСП как сервер, RS как слейв, но! раз уж Вы высчитываете микросекуды, то ESP должна парсить ВЕСЬ трафик на RS и строить на его основе в себе состояние всех опрашиваемых мастером-RS регистров RS-устройств. Плюс несколько своих регистров для возможности послать команду. А если все это еще и по вэбу можно будет наблюдать, то будет просто замечательно. Своего рода "глазок" в RS-сеть.

В других вариантах трудно представить реальное применение.
 

pvvx

Активный участник сообщества
Вроде первая полная версия для тестов готова. v0.0.3. Работает во все стандартные стороны
Modbus TCP Client/Server
Modbus RTU - RS-485 Slave/Master ESP8266
Внутреннее устройство ESP в режиме master не может опрашивать TCP, только свою сетку RS-485. Такого направления опроса транзакторами мне пока не требуется :) Но и это легко реализовать...
-------
Надо писать Help по работе самой ESP с modbus, но это так лениво :)
В других вариантах трудно представить реальное применение.
У вас странный подход. :) У меня всё по стандарту, как положено для Modbus TCP Bridge и устройства Modbus RTU на шине полудуплекс с RS-485. По тому и картинки не требуются - всё по стандарту - описаний к этому куча и ничего рисовать и писать не требуется.:p
Тем более, то, что вы описываете реализуется, если ESP master.
 
Последнее редактирование:

pvvx

Активный участник сообщества
Посмотрел фотки внимательнее, скорее всего, там стоит MAX 13487, у которого есть некий блок State machine, который определяет направление передачи
вот что пишут по практике
http://we.easyelectronics.ru/GYUR22/max13487-part2.html
Там на осцилле и видно, что сигнал не переключается в обратную сторону, а передается только активный уровень TX. Т.е. не замыкает или не дает отрицательного подпору на шину, когда бит передачи TX неактивен. Такая линия обязана иметь низкую эл.емкость. Её max не утруждает себя разряжать или перезаряжать. От этого возможны только низкие скорости передачи. Можно было поставить CAN драйвер - он работает аналогично :)
 

Dmitry P

New member
Там на осцилле и видно, что сигнал не переключается в обратную сторону, а передается только активный уровень TX. Т.е. не замыкает или не дает отрицательного подпору на шину, когда бит передачи TX неактивен. Такая линия обязана иметь низкую эл.емкость. Её max не утруждает себя разряжать или перезаряжать. От этого возможны только низкие скорости передачи. Можно было поставить CAN драйвер - он работает аналогично :)
Спасибо за разъяснения! Скорости проверим, но больше 19200 обычно и не надо :)
Интересно, 115200 потянет?
 

pvvx

Активный участник сообщества
Спасибо за разъяснения! Скорости проверим, но больше 19200 обычно и не надо :)
Интересно, 115200 потянет?
На короткие дистанции кабеля всё потянет, если стоят терминаторы.
Я совмещал когда-то выходы CAN драйвера и RS-485 в одном устройстве - работало и так и сяк (и на RS-485 и на CAN и если даже наоборот - шина RS, а работаем на CAN драйвере... :) ). Но безусловно это не для сертификации... Для дома для семьи потянет :)
 

pvvx

Активный участник сообщества
Help. Установки Modbus:
modbus_setup.gif

Baud– скорость передачи бита на шине RS-485. Равна bps – бит в секунду. Задается от 300 до 1000000 bps.

Parity– выбор варианта передачи бита parity. Если равно “none”, то передается 2 стоп бита, один за место parity (стандарт Modbus RTU использует 11 бит на символ). Устанавливается и нестандартная передача в 1 стоп бит (10 бит на символ).

MaxTimeout– максимальное время ожидания ответа от slave устройства. Обычно выставляется в 3000000/bps + время реакции устройства. Задается от 1 до 65535 мсек.

AltTp > 19200 – альтернативная установка времени паузы между сообщениями на шине RS-485, если скорость более 19200 Baud. При включении задает паузу всегда равной времени передачи 3.5 символа (11*3.5/bps). Если отключена – при скорости более 19200 Baud устанавливается пауза между сообщениями в 1.75 мсек.

Add msg pause – дополнительное время между сообщениями на шине RS-485 в мксек. Задается для опроса тупых устройств работающих не по стандарту Modbus RTU. Прибавляется к стандартной задержке. Задается от 0 до 65535 мксек.

Swap TXD<>RTS, RXD<>CTS – переключение ножек TX и RX у ESP8266 в альтернативный вариант: TX = GPIO15, RX= GPIO13. В стандартном варианте (галочка снята): TX = GPIO1, RX= GPIO3.

PinRD_ENA– выбор на какой GPIO выводится сигнал микросхеме драйвера RS-485 на переключение направления передачи. Уровень “0” указывает направление приема, уровень “1” – передача. При выборе “NONE” сигнал не используется.

IntDevID – номер (id) устройства Modbus ESP. Задается от 1 до 255. В стандарте Modbus номера 0, 248..255 зарезервированы.

ModbusTCPClient/ServerIP– номер внешнего ip для соединения Modbus TCP в режиме клиент. Если номер задан как 127.0.0.1 или некорректно (“none”), тогда ESP Modbus TCP работает как сервер.

Modbus TCP port – номер порта для клиента или сервера Modbus TCP. Обычно 502. Задается от 5 до 65535.

Modbus TCP recved timeout – таймер неактивности соединения Modbus TCP после его открытия для его закрытия в секундах. При 0 – бесконечное ожидание. Задается от 0 до 65535.

Modbus TCP close timeout – таймер отсчета времени после последней передачи или приема неактивности соединения Modbus TCP для его закрытия в секундах. При 0 – бесконечное ожидание. Задается от 0 до 65535.

Modbus TCP connect reopen – Включение опции переоткрытия соединения при новом запросе, если соединение уже открыто. Старое соединение закрывается. Избавляет от многих глюков с потерями соединений на TCP и возникающими от этого тайм-аутами. Если отключена, то новый запрос на соединение при уже открытом соединении получит ошибку и не отработает.
 
Последнее редактирование:

pvvx

Активный участник сообщества
Help. Буфер обмена на 1000 ячеек Modbus ESP.
modbus_data.gif

Внутреннее устройство ESP имеет буфер обмена на 1000 ячеек Modbus ESP. Обращение к этим и другим переменным из Web организуется через переменные с начальным индексом “mdb…” – см. WebVars.xlsx или Info на самом модуле через Web (ссылка на странице Main).

Все переменные буфера и другие ячейки Modbus ESP всегда доступны с Modbus TCP.
На web имеется отладочный пример на странице http://aesp8266/protect/mdb.htm (есть ссылка из страницы Debug and Test). На нем в режиме реал-тайм отображаются первые 100 ячеек буфер обмена Modbus ESP. Так-же демонстрируется запись в ячейки. При подносе указателя к данным ячейки в таблице всплывающая подсказка показывает значение ячейки в HEX виде.

По принципу работы ориентируемся на такую схему:
Сделали в своем внешнем slave контроллере область данных для передачи и они всегда, несколько раз в секунду будут дублированы в этом буфере обмена ESP (master) за счет автоматической работы транзакторов. И наоборот - объявленный для передачи блок в буфере ESP будет записан в slave. По тому какие байты, какие там строки - пофигу. Они будут в памяти обоих устройств в автоматическом, заданном заранее режиме у транзакторов.

Для инициализации буфера вместе с транзакторами при старте ESP возможно использовать прямую загрузку всей области из бинарного файла на web-диске. Организуется путем считывания готового буфера "http://aesp8266/protect/mdb.bin" (есть ссылка из страницы Debug and Test) и записью его в диск в директорию /protected как mbdini.bin c добавлением строки в файл protect\init.ini "mdbfini=protect/mbdini.bin". Файл с бинарными данными для mdb не должен быть сжат gzip и желательно исключен из проверки на динамические переменные. Можно ему дать спец. расширение и/или вписать в список исключений для сжатия для WEBFS22.exe:
mbdini.gif
 
Последнее редактирование:

pvvx

Активный участник сообщества
Help. Modbus транзакторы.
В Modbus ESP имеется 10 транзакторов. Они предназначены для посылки команд и приема сообщений по шине RS-485. Работают только в режиме master. В них задается какие данные из ячеек буфера Modbus ESP отослать и/или куда прочитать. Их обслуживание производится по таймеру в 50 мсек. Более старший номер транзактора имеет меньший приоритет (обрабатывается последним в группе). Транзакторы расположены сразу за буфером Modbus ESP, с адреса ячеек 1000. Каждый транзактор имеет и занимает 10 ячеек.

Запись и запуск из web транзактора осуществляется командой
mdbtN=id,command,number,extaddress,intaddress,timer,errors[,fifo,tcnt] - где:
N - номер транзактора; ID - номер устройства на шине Modbus; Command - номер команды Modbus; Number - кол-во передаваемых ячеек; ExtAddress - номер ячейки у внешнего устройства; IntAddress - внутренний адрес Modbus ESP; Timer - делитель таймера; Error - счетчик ошибок приема/передачи транзактора. Если какой-то параметр пропущен (задано ",,"), то прошлое значение не меняется. Кол-во параметров может быть больше или меньше. Но не желательно затирать внутренние счетчики fifo и tcnt. Указывая error нулем, сбрасываем счет ошибок.
Одиночный запуск уже назначенного транзактора можно сделать командой записи ячейки "mdbw1010=1", где 1010 - это ячейка startflag у транзактора с номером 1. Адрес вычисляется как 1000 + 10*номер транзактора. Можно и запросить у web для javascript адрес начала блока транзакторов ~mdb_trna~ и их кол-во ~mdb_trns~.
Для примера отсылки строки "Hello!"внешнему контроллеру из web, можно воспользоваться такой командой "http://aesp8266/web.cgi?mdba123=Hello!&mdbt0=1,16,4,123,0,0,0". :)
modbus_trns.gif
TrnN - N номер транзактора;
StartFlag - ячейка, при записи в которую любого отличного от нуля числа вызывает одиночную транзакцию. Опрос по таймеру в 50 ms. При обработке запроса (засылке в fifo) сбрасывается в нуль.
ID - номер устройства на шине Modbus.
Command - номер команды Modbus. Из стандартных пока поддерживаются команды с номерами 3, 4, 6, 16. Для других номеров запрос будет составлен как id,cmd,x0,x1,... где xn - данные из ячейки с номером в IntAddr, кол-во n указывается в Number.
Number - кол-во передаваемых ячеек.
ExtAddr - номер ячейки у внешнего устройства.
IntAddr - внутренний адрес ячейки в Modbus ESP.
Timer - делитель таймера повтора транзакции. Если = 0 - одноразовая транзакция. Учитывает fifo - если сообщение ещё сидит в fifo (не отработано), то счет таймера стоит.
Error - счетчик ошибок приема/передачи транзактора. В основном указывает кол-во не полученных ответов из-за тайм-аута.
FifoCount - кол-во сообщений от данного транзактора находящихся в fifo. Равен кол-ву ещё не отработанных транзакций.
TimerCount - это внутренний счетчик делителя таймера (на странице не отображен).

Отладка и просмотр транзакторов на Web в реал-тайм находится в http://aesp8266/protect/mdbtrn.htm (есть ссылка из страницы Debug and Test). На странице, кликание мышью на позиции в строке SartFlag вызывают одиночное срабатывание транзактора (=1), на позиции в строке Timer - останов таймера (=0), на позиции в строке Erros - сброс счетчика ошибок (=0). Ниже таблицы на странице дан пример записи транзактора.

Транзакторы к картинке заданы такой строкой "http://aesp8266/web.cgi?mdbt0=1,4,10,0,0,1,0&mdbt1=1,16,20,10,10,1,0". Шина RS-485 никуда не включена - от этого одни ошибки транзакций... Примеры с рабочими устройствами уже давались и ещё будут...

Пока в Help всё ещё не дописано - на сегодня хватит - лень, буду дописывать позже. :)
 
Последнее редактирование:

Dito85

New member
pvvx, спасибо! Замечательный проект! Давно искал что то подобное! Вот только не получается у меня настроить транзакторы. Беру строку из примера: http://aesp8266/web.cgi?mdbt0=1,4,10,0,0,1,0&mdbt1=1,16,20,10,10,1,0 после выполнения открывается страница с надписью:
ESP8266 Built-in Web server ©
В итоге таблица Modbus TRNs пустая (, соответственно запросы в RS485 не отправляются. Подскажите что не так делаю?
 

Dmitry P

New member
pvvx, в файле WebVars системные переменные должны начинаться с 1100 адреса.
 

pvvx

Активный участник сообщества
Беру строку из примера: http://aesp8266/web.cgi?mdbt0=1,4,10,0,0,1,0&mdbt1=1,16,20,10,10,1,0 после выполнения открывается страница с надписью:
ESP8266 Built-in Web server ©
А какая страница должна открываться? Обращения в примере сделаны к резервной, всегда присутствующей - она и показывается. Сделаете к другой - будет другая страница...
В итоге таблица Modbus TRNs пустая (, соответственно запросы в RS485 не отправляются. Подскажите что не так делаю?
Не знаю. Проект с git, нажато на ссылку из вашего поста:
trn01.gif
И пример изменения транзакторов уже встроен в данную страницу...
pvvx, в файле WebVars системные переменные должны начинаться с 1100 адреса.
Help исправил:
mdb1100.gif
Прошивку тоже обновил. Но они не всегда последней версии, более правильная и последняя при трансляции исходников по ссылкам из первого сообщения темы. Мне просто некогда всё обновлять каждый раз. Слишком много разных проектов у меня (и не только связанных с ESP8266 :) ), а я один. От этого могу натворить бардак... Так что пишите что не так и конкретно где и в какой прошивке или исходников (от куда)...
 
Последнее редактирование:

Dito85

New member
pvvx, вы писали, что для инициализации транзакторов при старте ESP нужно файл mdb.bin переименовать в mbdini.bin и записать его на диск в директорию protect. Так вот я настроил транзакторы, выкачал mdb.bin, переименовал его, а вот как его в ESP отправить в директорию protect? Всю голову сломал, подскажите как это делается?
 
Сверху Снизу