Просмотр полной версии : МАРШРУТНАЯ РЕТРАНСЛЯЦИЯ MODBUS
Василий Соловьев
29.08.2022, 12:45
Добрый день!
Дано:
ПЛК110-30[M02]
OPC-сервер Lectus OPC
Множество разнесенных территориально объектов связанных с диспетчерским пунктом (ДП) по радиоканалу, .
Задачи:
1) Организовать маршрутную ретрансляцию пакетов данных Modbus RTU с "верхнего" rs232 порта на "нижний" rs485.
2) Организовать маршрутную ретрансляцию пакетов данных Modbus TCP с "верхнего" Ethernet порта на "нижний" rs485.
При маршрутной ретрансляции из «верхней» сети в «нижнюю» пакеты данных имеют структуру, приведенную в таблице 1.
Маршрутный ретранслятор отбрасывает от исходного пакета (П1) свой маршрутный адрес и «верхнюю» контрольную сумму CRCВ (при ее наличии), и получившийся новый пакет (П2) передает в «нижнюю» сеть.
При получении корректного ответа из «нижней» сети (пакет П3) маршрутный ретранслятор добавляет в начале пакета свой маршрутный адрес, а в конце – новую («верхнюю») CRC пакета, и отправляет получившийся пакет (П4) в «верхнюю» сеть.
Маршрутная ретрансляция может иметь несколько уровней вложенности, по количеству маршрутных ретрансляторов на пути данных от ДП до оконечного устройства.
Пример того, как должно быть в приложении. (маршрутный адрес ПЛК ретранслятора 227, адрес оконечного устройства 23)
Поиском ничего на форуме не нашел... прошу помочь... возможно эта тема уже обсуждалась или в какую сторону ковырять.
Вы хотите из ПЛК110 некое подобие гейта Modbus TCP/RTU сделать? А он умеет? И зачем? не проще на нём все данные собирать, раз уж всё равно оконечные устройства к нему подключены?
И какой смысл Вы вкладываете в определение "маршрутный"? Что-то я в Вашем описании даже намёка на маршрутизацию не увидел.
Ничего у Вас не получится, ПМСМ. Тем более что
Маршрутная ретрансляция может иметь несколько уровней вложенности, по количеству маршрутных ретрансляторов на пути данных от ДП до оконечного устройства.
Во всяком случае средствами MODBUS, где даже намёка на маршрутизацию нет.
Может для начала задачу стоит сформулировать?
какую сторону ковырять.
"Здрасьте" SysLibCom и SysLibSockets...:)
Василий Соловьев
29.08.2022, 13:57
Вы хотите из ПЛК110 некое подобие гейта Modbus TCP/RTU сделать? А он умеет? И зачем? не проще на нём все данные собирать, раз уж всё равно оконечные устройства к нему подключены?
И какой смысл Вы вкладываете в определение "маршрутный"? Что-то я в Вашем описании даже намёка на маршрутизацию не увидел.
Ничего у Вас не получится, ПМСМ. Тем более что
Во всяком случае средствами MODBUS, где даже намёка на маршрутизацию нет.
Может для начала задачу стоит сформулировать?
Исправляюсь:
Система действующая и в ней более 3000 ПЛК подключены к АРМ с помощью радиоканалов 160 МГц.
Радиоканал не всегда про,ивает от базы до абонента, поэтому используются ПЛК, которые ретранслируют пакеты данных на промежуточных узлах... На сегодня такой функционал работает на ScadaPACK, ICPDAS,B&R.
Есть 100500+ нефтегазодобывающих скважин со своими станциями управления, которые технологи постоянно меняют, т.к. меняют режимы работы сважин.
У каждой станции управления различаются адреса целевых регистров и типы данных.
На уровне АРМ разработаны шаблоны для каждого типа станции управления, и при замене станции просто меняется шаблон на верхнем уровне и указывается маршрут связи.
Данная тема возникла на фоне отсутствия возможности закупки ПЛК ScadaPACK и желания перейти на работу с отечественным производителем. Сейчас определяется техническая возможность для решения данных задач оборудованием ОВЕН.
Василий Соловьев, оборудование ОВЕН достаточно "гибкое", с возможностью реализации очень большого количества хотелок. И Ваша задача вполне реализуема, я думаю. Но готовых примеров, схожих с Вашим (я, по крайней мере) не встречал на форуме. И если их все таки нет, то придется всю реализацию делать самостоятельно (так же, как когда-то, кто-то делал реализацию Вашей системы на базе оборудования иностранного производителя). Библиотеки для работы с RS и Ethernet (не все, конечно, есть и другие) указаны выше.
Исправляюсь:
Радиоканал не всегда про,ивает от базы до абонента, поэтому используются ПЛК, которые ретранслируют пакеты данных на промежуточных узлах...
Вот в таком изложении понятней. Ретрансляция пакетов для ПЛК не является основной задачей? Чисто побочно, поскольку умеет (ScadaPACK) штатно, если я правильно понимаю? А вариант снять с ПЛК функцию ретранслятора и переложить на более специализированное устройство рассматривали? Насколько я понимаю, репитеры для радиоканалов 160 МГц существуют.
keysansa
29.08.2022, 16:25
Нафига нагружать контроллер не свойственными ему задачами, если можно это решить существующими сетевыми протоколами, поддерживаемыми всеми более-менее толковыми маршрутизаторами...
ЗЫ. RTU<->TCP - так же решается, либо переделкой программы и конфигурации, либо шлюзами RTU<->TCP
Нафига нагружать контроллер не свойственными ему задачами
Не делайте скоропалительных выводов. Это может быть удобно по неочевидным причинам, которые на поверхности не лежат. А может просто так исторически сложилось. ТС же всей картины не раскрывает.
Добрый день!
Дано:
ПЛК110-30[M02]
OPC-сервер Lectus OPC
Множество разнесенных территориально объектов связанных с диспетчерским пунктом (ДП) по радиоканалу, .
Очень похожую задачу решал лет 7 назад на ПЛК304 (https://owen.ru/product/plk304)
Сейчас, наверно, и не найду. Да и писалось на CDSv3.
Однако, думаю, что и на CDSv2 тоже можно сваять!
Если я не ошибаюсь то в инструкции на Ваш ПЛК110-30, есть такой пункт
62337
Впрочем здесь есть Доска Услуг (https://owen.ru/forum/showthread.php?t=14182)
Василий Соловьев
30.08.2022, 07:29
Вот в таком изложении понятней. Ретрансляция пакетов для ПЛК не является основной задачей? Чисто побочно, поскольку умеет (ScadaPACK) штатно, если я правильно понимаю? А вариант снять с ПЛК функцию ретранслятора и переложить на более специализированное устройство рассматривали? Насколько я понимаю, репитеры для радиоканалов 160 МГц существуют.
ПЛК выполняет функции удаленного ввода-вывода для сбора состояний датчиков и пересылку пакетов из "верхней сети" (мощный модем 160 МГц, связь с ДП) в "нижнюю" (маломощный модем 433 МГц, связь со станциями управления).
Основная задача, в этом случае, это реализовать "вложенную", если так можно выразиться, ретрансляцию пакетов Modbus RTU (и я понимаю что это не возможно cделать стандартными функциями Modbus) из одного порта в другой .
Но не на всех объектах "верхняя" сеть это модемы 160 МГц, где-то используется ШПД (WLAN). Вот для этих случаев уже необходимо сначало преобразование из TCP в RTU, затем отправка пакета RTU в "нижний" порт, а после ответа оконечного устройства обратно преобразование в TCP и отсылка в "верхний" порт.
Изменить конфигурацию оборудования невозможно... проекты реализуются годами. Использовать другую схему передачи данных тоже невозможно.
И да... никто не знает когда и кем эта ретрансляция вообще была придумана... возможно из-за того что ScadaPACK в нефтянке были практически монополистами и там этот базовый функционал из коробки.
Добрый день, Василий.
Давайте определимся, что Вам надо?
Если Вам нужно готовое устройство от ОВЕН - такого устройства нет.
Если Вам нужен пример кода для ПЛК110-30 - Вам бы его уже предложили.
Если Вам нужен ответ на вопрос "можно ли реализовать на базе этого ПЛК ретранслятор" - можно. (ссылки на библиотеки Вам дали)
Если Вам нужна помощь в реализации ПО по вашим задачам - предложите форму сотрудничества.
Примечание:
Ретранслятором в данном случае имеется в виду только ПЛК реализующий инкапсуляцию пакетов "верхний-нижний" и капсуляцию "нижний-верхний".
Запрос капсулируется на верхнем уровне Lectus'ом.
Последний ретранслятор в цепочке на выходе выдает ModbusRTU-запрос для контроллера обслуживающий скважину.
Ответ передается обратно с капсуляцией на каждом ретрансляторе.
Инкапсуляцию ответа производит Lectus.
Если я ТЗ описал верно, то готов взяться за решение.
Без схемы не совсем понятно. Подозреваю, какие бы там ПЛК ни были, это реализация программная, а не заложенная сразу в ПЛК. Так как предусматривать такие вещи производителям ПЛК слишком дорого...
Подозреваю, какие бы там ПЛК ни были, это реализация программная, а не заложенная сразу в ПЛК.
Предположу, что всё же "искаропки". Беглое чтение первого попавшегося документа по ScadaPACK 32 показало, что там в настройках Modbus TCP есть режим Store and Forward и ссылка на некую таблицу маршрутизации, завязанную на этот режим. Возможно, это как раз про то самое. Но, не уверен ;)
zaychenko
30.08.2022, 23:53
ПЛК выполняет функции удаленного ввода-вывода для сбора состояний датчиков и пересылку пакетов из "верхней сети" (мощный модем 160 МГц, связь с ДП) в "нижнюю" (маломощный модем 433 МГц, связь со станциями управления).
Основная задача, в этом случае, это реализовать "вложенную", если так можно выразиться, ретрансляцию пакетов Modbus RTU (и я понимаю что это не возможно cделать стандартными функциями Modbus) из одного порта в другой .
Но не на всех объектах "верхняя" сеть это модемы 160 МГц, где-то используется ШПД (WLAN). Вот для этих случаев уже необходимо сначало преобразование из TCP в RTU, затем отправка пакета RTU в "нижний" порт, а после ответа оконечного устройства обратно преобразование в TCP и отсылка в "верхний" порт.
Изменить конфигурацию оборудования невозможно... проекты реализуются годами. Использовать другую схему передачи данных тоже невозможно.
И да... никто не знает когда и кем эта ретрансляция вообще была придумана... возможно из-за того что ScadaPACK в нефтянке были практически монополистами и там этот базовый функционал из коробки.
Мб подойдет под решение задачи вот это видео: https://www.youtube.com/watch?v=0w8hZK6yLW4&t=1s
Добрый день!
2) Организовать маршрутную ретрансляцию пакетов данных Modbus TCP с "верхнего" Ethernet порта на "нижний" rs485.
Кстати 2-ю задачу может выполнить https://owen.ru/product/mkon/specifications
Он только покеты со Slave ID равным 1 оставляет себе, а все остальное отправляет в RS485, добавляя CRC в конец пакета.
Т.е. Ваш ModbusTCP пакет: 64 97 00 00 00 09 E3 17 03 00 01 00 01 D7 3C
он выдаст в RS485: E3 17 03 00 01 00 01 D7 3C 97 CF
соответственно ретранслятор (0xЕ3) 227 отбросит Е3 и 97 СF
передаст дальше только: 17 03 00 01 00 01 D7 3C - уже корректный ModbusRTU запрос устройству (0x17) 23
keysansa
01.09.2022, 12:28
Не делайте скоропалительных выводов. Это может быть удобно по неочевидным причинам, которые на поверхности не лежат. А может просто так исторически сложилось. ТС же всей картины не раскрывает.
Согласен. Но данный коментарий мне напоминает противостояние Linux и Windows. В первой - каждая утилита заточена под свою задачу, но выполняет ее идеально. Вторая - сумасшедший комбайн, где все перемешано (говорю с точки зрения автоматизации а не пользователя).
keysansa
01.09.2022, 12:42
ПЛК выполняет функции удаленного ввода-вывода для сбора состояний датчиков и пересылку пакетов из "верхней сети" (мощный модем 160 МГц, связь с ДП) в "нижнюю" (маломощный модем 433 МГц, связь со станциями управления).
Контроллер выступает мастером на 160МГц, и по другому порту выступает слейвом (или мастером) на 433 МГц. Тут проблем не видно.
Основная задача, в этом случае, это реализовать "вложенную", если так можно выразиться, ретрансляцию пакетов Modbus RTU (и я понимаю что это не возможно cделать стандартными функциями Modbus) из одного порта в другой .
Зачем ретранслировать пакеты, что сложнее, если можно передавать состояния переменных, что проще? Памяти хватает, скорости тоже. Да, будет лаг во времени на одну посылку. Но с учетом канала связи, данные там не realtime.
Но не на всех объектах "верхняя" сеть это модемы 160 МГц, где-то используется ШПД (WLAN). Вот для этих случаев уже необходимо сначало преобразование из TCP в RTU, затем отправка пакета RTU в "нижний" порт, а после ответа оконечного устройства обратно преобразование в TCP и отсылка в "верхний" порт.
То же самое, опрос - по одному интерфейсу, хранение значения внутри контроллера, отдача - по любому другому. Почитайте про OPC. Они похожую задачу уже реализовали, пройдете большинство "камней".
Изменить конфигурацию оборудования невозможно... проекты реализуются годами. Использовать другую схему передачи данных тоже невозможно.
Если можно добавить новый протокол обмена, значит можно поставить рядом второй контроллер, на время, и выполнить сравнение старой и новой программы, например, в течении месяца-двух.
ЗЫ. Посмотрите еще на устройства Anybus, например. Их логика такая:
* Есть общая память, которая конфигурируется следующим образом...
* Интерфейс 1 записывает все полученные данные в область памяти А и отправляет данные из области Б
* Интерфейс 2 отправляет данные из области А и записывает все полученные данные в область Б.
Это не модбас-tcp
?
Part of Data Package Description Value
64 97 Transaction identifier 0x6497 (25751)
00 00 Protocol identifier 0 = MODBUS protocol
00 09 Length 0x0009 (9)
E3 Unit identifier 0xE3 (227)
17 Function code 0x17 (23)
03 00 01 00 01 D7 3C Data
Василий Соловьев
01.09.2022, 18:08
?
Part of Data Package Description Value
64 97 Transaction identifier 0x6497 (25751)
00 00 Protocol identifier 0 = MODBUS protocol
00 09 Length 0x0009 (9)
E3 0xE3 (227) / Адрес порта ретрансляции в данном случае
17 Unit identifier (23) / Адрес устройства назначения
03 Function code 0x03 (04)
00 01 00 01 (D7 3C - CRC запроса modbus RTU) Data
Это не стандартный запрос, но именно в таком виде реализовано передача данных на объектах.... меняют местами "ретрансляторы"(точнее целиком шкафы)... меняют местами конечные устройства, иногда "вложенность такой вот матрЁшечной ретрансляции" достигает 4 уровней!
Изначально делалось это для ускорения замены шаблонов на АРМ оператора... вообщем, так исторички сложилось))
Абсолютно стандартный Modbus, только не Modicon :)
Валенок просто вы привыкли к древнему Modbus, где только Coils, да Input и Holding Register а стандарт дальше развивался и некоторые производители все-таки начали применять это в приборах. А пЕсатели всяких OPC да прочего так и топчутся на месте на старом "добром" Modbus :) (например тот же Овен со своей Конфигурацией в ПЛК), чуть что, не поможет...
я уже встречал по описаниям приборов где кроме штатных и привычных функций применялись расширенные. А по опыту работы с разными протоколами, Modbus при всей его древности куда лаконичнее и проще, чем другие протоколы....
Валенок кто в другую сторону развил? Modicon насколько понимаю устранился давно от данного протокола, 0х17(23) описана в стандарте Modbus - скачайте уж что ли его.
Кого другого вы имеете ввиду ? на Wiki есть упоминание Modbus-Plus от Шнайдера, так о нем речи нет, это из другой оперы проприоритарный протокол на основе Modbus.
Если расширите вы, то это получится как у Шнайдера, понятно будет только вам. А приведенная команда сугубо из стандарта Modbus и описана в его документации.
Я видел приборы, которые текущие данные отдавали по старинке, а вот архивы как раз таки дополнительными командами протокола, вопрос только поддержки от всяких OPC да Scada систем...
https://modbus.org/docs/Modbus_Application_Protocol_V1_1b3.pdf
Все лежит на Modbus_ogr, ссылки есть в конце страницы из Wiki. Вообще там много документов, вплоть до того, какие контакты необходимо использовать, если применяется разъем RJ45 чтобы не лепили отсебятину.
Валенок мне некогда заниматься предложенными вами экспериментами. Вы уж как-то сами пожалуйста.
Живьем мне к сожалению не попадались приборы, работающие на расширенных функциях, но по документации некоторых видел использование. В основном это было для передачи архивов с приборов.
а так, 64 97 00 00 00 09 E3 17 03 00 01 00 01 D7 3C - функция 0x17 и вот эти байты разберите по документации 03 00 01 00 01 D7 3C
Вам нужен раздел 6.17 страница 38, дальше сами, а то я тут протоколом VRV систем занимаюсь и реально не до разбирательств с Modbus..
Валенок какой шаг на, предполагается что два прибора умеют работать со всеми функциями Modbus. Один спросил, другой ответил...
Валенок ну не делайте мне мозг пожалуйста. Посылка, приведенная автором или кем-то скопированная из скрина, полностью Корректна для Modbus.
Столкнусь живьем, разберусь и сделаю. Не такое вытворяли с чужими протоколами :)
это про "мыши - станьте ежиками" ? )) нет, это написание драйвера для Scada, чтобы сделать программный шлюз, имея на руках лишь это https://codeberg.org/xye/xye
И железки в виде адаптера от Даичи и платы кондея. И оно таки отвечает и управляется... Просто надо дооформить управление, интерфейс для настроек. Короче окультурить осталось, правда тоже времени занимает...
2022-09-02 23:23:00 Сеанс связи с устройством [2] AF-X
Отправка (16): AA C0 0F 0F 80 0F 00 00 00 00 00 00 00 3F 54 55
Приём (32/32): AA C0 80 0F 0F 00 31 10 00 00 FF 94 00 FF 00 00 FF 00 00 00 00 00 00 00 00 00 00 00 00 00 D0 55
OK
Валенок то есть я должен потратить время, чтобы вам разжевать? обратите внимание на дату документа в начале, 2012 год если что. И данная посылка на скрине не единственная. Что есть запрос, что есть ответ опять же, разбираться ВЛОМ, это не моя задача. Но то, что это MODBUS не вызывает сомнений. Если в вашем понимании стандарт это все до 0x15 то можете и далее так считать. Удачи. Автору тоже. На его месте я бы от Овен держался подальше, хотя конечно и на нем можно. Особенно если заглянуть в oscat и порыться там, что они поддерживают в Modbus как для 2.3 так и для 3.5 CodeSys...
ТС простите сам не знает что там и как, так что какие-либо подтверждения без диагноза пока рановаты...
Проснулся, Валенок, вы правы. У ТС не очень удачный пример с 23-м адресом слейва (0x17)
64 97 00 00 00 09 E3 17 03 00 01 00 01 D7 3C - запрос RTU к 23-му
64 97 00 00 00 08 E3 17 03 02 00 6D 30 6A - ответ RTU от 23-его
64 9A 00 00 00 08 E3 17 03 02 00 6C F1 AA - аналогичный ответ только под новым номером транзакции
64 98 00 00 00 09 E3 17 03 00 03 00 02 36 FD
64 98 00 00 00 0A E3 17 03 04 00 6E 26 F6 76 09
64 9B 00 00 00 0A E3 17 03 04 00 6E 26 FB B7 CC
64 99 00 00 00 09 E3 17 03 00 06 00 01 66 FD
64 99 00 00 00 08 E3 17 03 02 27 01 2B B7
64 9C 00 00 00 08 E3 17 03 02 27 0A 6A 70
Com over TCP так выглядит? в принципе есть ПР200, могу проверить...
Хотя вроде Com over TCP просто заворачивается в TCP пакет, а не притворяется, что он Modbus TCP. Есть подозрение, что это для идентификации для промышленных коммутаторов с системами защиты. У наших производителей тоже такое есть (VipNet IG например)
Валенок мне больше кажется, что это извращение придумано для работы в защищенных сетях, где оборудование может контролировать пакеты Modbus, но могу ошибаться.
1. Используется Transaction ID для контроля.
2. по сути две контрольные суммы, TCP пакета и встроенного внутрь Modbus TCP запроса обычного RTU запроса
Интересно, у ТС есть слейвы RS например с 5-м адресом, 28-м, 57-м ???
Иначе на кой прикидываться Modbus TCP запросом вообще ?
от TC хотелось бы увидеть пример RS232 "верхний" и RS485 "нижний" но чтобы у нижнего адрес бы отличный от номера команд самого Modbus...
ScadaPACK - учитывая, что это Шнайдер, то вероятно там и есть этот пресловутый Modbus_Plus, который упоминается на Wiki
Проприоритарный протокол от этой компашки... И судя по табличке просто один пакет Modbus встраивают в другой как есть.
Если по схеме в качестве ретрансляторов используются только эти контроллеры, тогда становится понятным ситуация... Пролоббированная фигня в свое время.
Валенок не, я про то, что в Modbus TCP вообще на хвосте нет CRC, собственно табличка у ТС об этом и говорит. Как бы CRC в данном случае занимается TCP стек.
Предположим это фишка Шнайдера, типа их ноухауЛЯ.... Как тогда он понимает, что это вложенный пакет скажем при условии обмена "верх" 232 - "низ" - 485 и адрес нижнего совпадает с номером функции ?
То есть мы со Scada спрашиваем через адрес 5 адрес 3, будет же 05 03 Func Номер регистра ну и так далее.... Может же произойти какое-то совпадение, которое приведет к ошибке
Хочу закрыть этот вопрос окончательно.
У OPC Lectus есть возможность добавлять узлы работающие через такие вот ретрансляторы:
62705
А так как он является OPC-сервером, то интегрируется с любой Scada.
Будет полезно новичкам, как пример использования библиотеки UNM.lib и как возможность организации доступа нескольких мастеров в одну RS485-сеть.
Видео испытания кода (https://drive.google.com/file/d/1OMjpWlnEBTIDNPjogA-0xp9F127kG8NQ/view?usp=sharing)
62704
PROGRAM PLC_PRG
VAR
Port: DWORD := 255;
State: INT := 0; (* Состояние ретранслятора *)
Addr: BYTE := 1; (* Адрес ретранслятора - задается перед заливкой в ПЛК *)
CRC: WORD; (* Контрольная сумма пакетов *)
Timeout: TIME := T#50ms; (* Таймаут ожидания ответного пакета из нижней сети - задается перед заливкой в ПЛК *)
pBuf: POINTER TO STRING;
pByte: POINTER TO BYTE;
IN: POINTER TO RBDATA; (* Принятый байт *)
TMR: TON; (* Таймер отсчета таймаутов *)
HeadTCP: ARRAY[1..4] OF BYTE; (* Заголовок ModbusTCP *)
Buf: ARRAY [1..128] OF BYTE; (* Буфер *)
Item: INT;
Count: WORD;
END_VAR
CASE State OF
0: (* Выполняем захват всех UNM-устройств *)
IF LockDevice(0) = 1 AND LockDevice(1) = 1 AND LockDevice(2) = 1 THEN
Count := 0; State := 1;
END_IF
1: (* Прием пакета с верхней сети *)
IF Port = 255 THEN (* Пока ждем кто начнет первым *)
IN := GetByte(0); (* Слушаем TCP *)
IF IN > 0 THEN
Port := 0; Count := 1; Buf[Count] := IN^.data; (* Итак TCP был первым *)
ELSE
IN := GetByte(1); (* Слушаем RS232 *)
IF IN > 0 THEN
Port := 1; Count := 1; Buf[Count] := IN^.data; (* Итак RS-232 был первым *)
END_IF
END_IF
ELSE (* Здесь кто был первым уже известно *)
IN := GetByte(Port); (* Принимаем очередной байт *)
IF IN > 0 THEN
TMR(IN:=FALSE); Count := Count + 1; Buf[Count] := IN^.data; (* И сохраняем в буфер *)
ELSE
IF Count > 0 THEN
TMR(IN := TRUE, PT := T#1ms); (* Здесь желательно установить PT:= 3.5/(Baudrate*10) *)
IF TMR.Q THEN (* Прем пакета завершен *)
TMR(IN:=FALSE);
IF Count >= 5 THEN (* Длина пакета достаточна для анализа *)
CASE Port OF
0: (* Обработка ModbusTCP-пакета *)
FOR CRC := 1 TO 4 DO (* Сохраним заголовок ModbusTCP-пакета *)
HeadTCP[CRC] := Buf[CRC];
END_FOR
pByte := ADR(Buf) + 6; CRC := CalcCRC(pByte, Count - 6); (* Вычислим CRC *)
pByte := ADR(Buf) + Count; pByte^ := WORD_TO_BYTE(CRC MOD 256); (* Добавляем младший байт CRC *)
pByte := pByte + 1; pByte^ := WORD_TO_BYTE(CRC / 256); (* Добавляем старший байт CRC *)
pBuf := ADR(Buf) + 6; SetByte(2, pBuf^, Count - 4); (* Отправляем в порт RS485-1 *)
Count := 0; State := 2; (* Переходим к ожиданию ответа *)
1: (* Обработка ModbusRTU-пакета *)
pByte := ADR(Buf); CRC := CalcCRC(pByte, Count - 2); (* Вычисляем CRC *)
pByte := ADR(Buf) + Count - 2;
IF pByte^ = (CRC MOD 256) THEN (* Проверяем младший байт CRC *)
pBYte := ADR(Buf) + Count - 1;
IF pByte^ = (CRC / 256) THEN (* Проверяем старший байт CRC *)
pByte := ADR(Buf);
IF pByte^ = Addr THEN (* Проверяем адрес ретранслятора *)
pBuf := ADR(Buf) + 1; SetByte(2, pBuf^, Count - 3); (* Отправляем в RS485 встроенный пакет *)
Count := 0; State := 2; (* Переходим к ожиданию ответа *)
ELSE
Count := 0; Port := 255; (* Пакет не нам - ждем следующий *)
END_IF
ELSE
Count :=0; Port := 255; (* Неверный CRC - ждем следующий *)
END_IF
ELSE
Count := 0; Port := 255; (* Неверный CRC - ждем следующий *)
END_IF
END_CASE
ELSE
Count := 0; Port := 255; (* Пакет слишком маленький - ждем следующий *)
END_IF
END_IF (* Ожидаем окончание приема *)
END_IF (* Ожидаем входной пакета *)
END_IF (* Ожидаем очередной байт *)
END_IF (* Ожидаем первый байт для определения первого UNM *)
2: (* Ожидание ответного пакета из нижней сети *)
IN := GetByte(2);
IF IN > 0 THEN
TMR(IN := FALSE); Count := Count + 1; Buf[Count] := IN^.data;
ELSE
IF Count = 0 THEN
TMR(IN := TRUE, PT := Timeout);
IF TMR.Q THEN
TMR(IN:=FALSE); Count := 0; Port := 255; State := 1; (* Нет ответа - начинаем все с начала*)
END_IF
ELSE
TMR(IN := TRUE, PT := T#1ms); (* Контроль окончания приема *)
IF TMR.Q THEN (* Окончание приема *)
TMR(IN:=FALSE);
pByte := ADR(Buf); CRC := CalcCRC(pByte, Count - 2);
pByte := ADR(Buf) + Count - 2;
IF pByte^ = (CRC MOD 256) THEN
pByte := ADR(Buf) + Count - 1;
IF pByte^ = (CRC / 256) THEN
CASE Port OF
0: (* Заворачиваем ModbusTCP *)
FOR Item := Count + 7 TO 7 BY -1 DO (* Сдвинем буфер на 6 байт вправо*)
Buf[Item] := Buf[Item - 6];
END_FOR
FOR Item := 1 TO 4 DO (* Вернем заголовок ModbusTCP *)
Buf[Item] := HeadTCP[Item];
END_FOR
pByte := ADR(Buf) + 4; pByte^ := WORD_TO_BYTE((Count -2) / 256); (* Добавим CRC *)
pByte := ADR(Buf) + 5; pByte^ := WORD_TO_BYTE((Count-2) MOD 256);
pBuf := ADR(Buf); SetByte(0, pBuf^, Count + 4); (* Вернем верхней сети 6(Head) + Count - 2(CRC) *)
Count := 0; Port := 255; State := 1; (* И начнем все с начала *)
1: (* Заворачиваем в ModbusRTU *)
FOR Item := Count + 2 TO 2 BY -1 DO (* Сдвигаем буфер на 1 байт вправо *)
Buf[Item] := Buf[Item-1];
END_FOR
pByte := ADR(Buf); pByte^ := Addr; (* Добавляем адрес ретранслятора *)
CRC := CalcCRC(pByte, Count + 1); (* Рассчитаем CRC нового пакета *)
pByte := ADR(Buf) + Count + 1; pByte^ := WORD_TO_BYTE(CRC MOD 256); (* Добавим младший байт CRC *)
pByte := ADR(Buf) + Count + 2; pByte^ := WORD_TO_BYTE(CRC / 256); (* Добавим старший байт CRC *)
pBuf := ADR(Buf); SetByte(1, pBuf^, Count + 3); (* Вернем верхней сети 1(Addr) + Count + 2(CRC) *)
Count := 0; Port := 255; State := 1; (* И начнем все с начала *)
END_CASE
ELSE
Count :=0; Port := 255; State := 1; (* Неверна CRC - все с начала *)
END_IF
ELSE
Count :=0; Port := 255; State := 1; (* Неверна CRC - все с начала *)
END_IF
END_IF (* Ожидание окончания приема *)
END_IF (* Ожидаем очередной байт *)
END_IF (* Ожидаем входной пакет *)
END_CASE
FUNCTION CalcCRC : WORD
VAR
Cnt: BYTE;
END_VAR
VAR_INPUT
pData: POINTER TO BYTE;
Size: WORD;
END_VAR
(* Вычисление контрольной суммы MODBUS RTU CRC *)
CalcCRC := 16#FFFF;
WHILE Size > 0 DO
CalcCRC := CalcCRC XOR pData^;
FOR Cnt := 0 TO 7 DO
IF CalcCRC.0 = 0 THEN
CalcCRC := SHR(CalcCRC, 1);
ELSE
CalcCRC := SHR(CalcCRC, 1) XOR 16#A001;
END_IF
END_FOR;
pData := pData + 1;
Size := Size - 1;
END_WHILE
Powered by vBulletin® Version 4.2.3 Copyright © 2025 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot