Modbus Plus представляет собой сетевой протокол обмена данными, разработанный компанией Modicon (ныне входит в состав Schneider Electric). Структура сообщений Modbus Plus идентична с RTU спецификацией, однако является более надежной и быстродействующей.
Modbus Plus имеет одинаковый с RTU, ASCII и TCP спецификациями прикладной уровень сетевой модели OSI, что позволяет использовать их совместно при обработке данных пользователя.
Modbus Plus использует метод передачи данных либо формата «точка-точка», либо мультимастерный с передачей маркера. Таким образом, сети, построенные на этом протоколе обмена, являются одноранговыми, любое устройство может быть как ведущим, так и ведомым, а так же инициировать обмен данными.
Физический уровень протокола Modbus Plus может быть представлен либо RS-485 интерфейсом, либо оптоволокном.
Именно различие физического уровня и метода передачи данных, не позволяет коммутировать Modbus Plus с другими версиями протокола. Однако, именно это отличие и влияет на повышение скорости передачи данных и надежности системы обмена.
Размер сети построенной на Modbus Plus может достигать 32 или 64 устройств без или с использованием репитеров соответственно. Скорость передачи данных достигает 2 Мбит/с. Протяженность линий связи до 500 м без репитеров/2000 м с репитерами/ более 2000 м с использованием оптоволокна как физического уровня.
Среди дополнительных функций Modbus Plus стоит выделить наличие общей базы транзакций, возможности сканирования сети, чтение и запись отдельных регистров, а так же возможность маршрутизации до 6 сетей.
Tags Modbus
autoworks.com.ua
В предыдущих статьях мы рассмотрели общую структуру протокола ModBus и его разновидности ModBus RTU и ModBus TCP. В этой статье мы подробно рассмотрим наиболее употребимые функции протокола. Структура функций не зависит от конкретной версии протокола (RTU или TCP).
Вспомним, как выглядит общая структура пакета ModBus:
Блоки «Адрес подчинённого устройства» и «Блок контроля подлинности» различаются в зависимости от версии протокола (RTU или TCP), а вот «Номер функции» и «Данные» в любой реализации одинаковы. Эти два блока образуют часть пакета, которую называют PDU (Protocol Data Unit), — именно она и важна при рассмотрении функций ModBus.
Функция для чтения состояния дискретных выходов устройства.
Запрос:
Ответ:
N* — количество запрошенных дискретных выходов/8. Состояния дискретных выходов (coils) передаются в виде 8-битных слов, поэтому параметр N равен ближайшему целому количеству слов, в которые умещается заданное количество coils.
n = N, если N делится на 8 без остатка, в противном случае n=N+1. Параметр n
Например, нужно прочитать 5 выходов. Тогда в ответе N=5/8=n=1. То есть в ответе после кода функции будет идти 1, а потом ещё один байт, в котором младшие 5 бит будут обозначать состояние запрошенных выходов.
Если устройство обнаружило ошибку при выполнении функции, оно отвечает исключением.
Ответ-исключение:
Коды ошибок стандартные. Их описание можно посмотреть в этой статье.
Пример:
Запрос 19 дискретных выходов, начиная с адреса 19:
В ответе 3 полезных байта:
Состояния входов:
1 полезный байт — состояние выходов с адресами 19 -26: 11001101
2 полезный байт — состояние выходов с адресами 27 -34: 01101011
2 полезный байт — состояние выходов с адресами 35 -37: 00000101 (значащие только 3 младших бита, остальные нули)
Функция для чтения состояния дискретных входов устройства.
Запрос:
Ответ:
N* — количество запрошенных дискретных входов/8. Состояния дискретных входов (inputs) передаются в виде 8-битных слов, поэтому параметр N равен ближайшему целому количеству слов, в которые умещается заданное количество входов.
n = N, если N делится на 8 без остатка, в противном случае n=N+1. Параметр n
Например, нужно прочитать 5 входов. Тогда в ответе N=5/8=n=1. То есть в ответе после кода функции будет идти 1, а потом ещё один байт, в котором младшие 5 бит будут обозначать состояние запрошенных входов.
Если устройство обнаружило ошибку при выполнении функции, оно отвечает исключением.
Ответ-исключение:
Коды ошибок стандартные. Их описание можно посмотреть в этой статье.
Пример:
Запрос 22 дискретных входа, начиная с адреса 196:
В ответе 3 полезных байта:
Состояния входов:
1 полезный байт — состояние выходов с адресами 196 -203: 10101100
2 полезный байт — состояние выходов с адресами 204 -211: 11011011
2 полезный байт — состояние выходов с адресами 212 -217: 00110101 (значащие только 6 младших бита, остальные нули)
Функция для чтения регистров общего назначения устройства.
Запрос:
Ответ:
N — количество запрошенных регистров. Каждый регистр состоит из двух байт, поэтому количество полезных байт в ответе равно 2*N.
Если устройство обнаружило ошибку при выполнении функции, оно отвечает исключением.
Ответ-исключение:
Коды ошибок стандартные. Их описание можно посмотреть в этой статье.
Пример:
Запрос на чтение трёх регистров начиная с адреса 107:
В ответе значение 3-х регистров = 6 полезных байта:
Значения регистров (в десятичном виде):
регистр с адресом 107: 555
регистр с адресом 108: 0
регистр с адресом 109: 100
Функция для чтения входных регистров устройства. По своей структуре полностью идентична предыдущей функции, поэтому разбирать её подробно не имеет смысла.
Единственное отличие этой функции от функции 0х03 Read Holding Registers в том, что она обращается к другой области внутри устройства.
Производитель устройства с поддержкой ModBus сам определяет область памяти, в которой будут хранится «Input Registers».
Input Registers — также 16-битные регистры. В классическом представлении ModBus эти регистры предназначены для хранения значений сигнала на аналоговых входах устройства.
Пример:
Запрос двух входных регистров, начиная с адреса 1:
В ответе содержится значения двух регистров = 4 байта данных:
Значения регистров (в десятичном виде):
регистр с адресом 1: 320
регистр с адресом 2: 17
Функция для изменения состояния одного из дискретных выходов (coil) устройства.
Состояние выхода («вкл»/ «выкл») определяется константой, записываемой в регистр, соответствующий данному выходу. Значение константы 0хFF00 — определяет состояние «ВКЛ», а значение 0х0000 — состояние «ВЫКЛ».
Запрос:
Ответ:
При успешном выполнении команды ответ совпадает с запросом.
Ответ-исключение:
Коды ошибок стандартные. Их описание можно посмотреть в этой статье.
Пример:
Запрос на «включение» выхода с адресом 172:
Если команда выполнена без ошибок, то ответ совпадает с запросом:
Функция для записи значения в один из регистров общего назначения (holding registers) устройства.
Состояние выхода («вкл»/ «выкл») определяется константой, записываемой в регистр, соответствующий данному выходу. Значение константы 0хFF00 — определяет состояние «ВКЛ», а значение 0х0000 — состояние «ВЫКЛ».
Запрос:
Ответ:
При успешном выполнении команды ответ совпадает с запросом.
Ответ-исключение:
Коды ошибок стандартные. Их описание можно посмотреть в этой статье.
Пример:
Запись значения «3» в регистр с адресом 1:
Если команда выполнена без ошибок, то ответ совпадает с запросом:
Функция для изменения состояния сразу нескольких дискретных выходов устройства.
Запрос:
Значения выходов которые нужно записать передаются в виде 8-ми битных слов, т.е. каждый байт данных содержит состояние 8-ми выходов. Поэтому количество байт передаваемых данных равно ближайшему целому от деления количества выходов на 8:
N = количество выходов / 8. Если остаток от деления не равен 0, то N = N+1.
Ответ:
Ответ-исключение:
Коды ошибок стандартные. Их описание можно посмотреть в этой статье.
Пример:
Запрос на запись состояния 10 выходов, начиная с выхода с адресом 19 (13 HEX):
Запрос содержит два байта данных, содержащих состояния выходов, которые нужно записать:
(CD 01 hex) (1100 1101 0000 0001 binary). Соответствие битов состояния и выходов устройства определяется следующим образом:
Бит: 1 1 0 0 1 1 0 1 0 0 0 0 0 0 0 1
Выход: 26 25 24 23 22 21 20 19 — — — — — — 28 27
Первый байт данных (CD hex) соответствует выходам 26-19. Младший бит соответствует выходу 19.
Второй байт (01 hex) соответствует выходам 28-27. Младший бит соответствует выходу 27.
Неиспользуемые биты в последнем байте — нули.
В ответе содержится подтверждение успешной записи:
Функция для записи значений в несколько (от 1 до 123) последовательно расположенных регистров общего назначения (holding registers).
Запрос:
N — количество регистров, в которые нужно записать новые значения. Регистры ModBus 16-битные, поэтому на каждый регистр приходится два байта данных.
Ответ:
В ответе содержится подтверждение успешной записи:
Ответ-исключение:
Коды ошибок стандартные. Их описание можно посмотреть в этой статье.
Пример:
Запрос на запись состояния двух регистров, начиная с регистра с адресом 1:
В ответе содержится подтверждение успешной записи:
lazysmart.ru
Ну что же, пора рассмотреть, чем протокол Modbus TCP отличается от протокола Modbus RTU. Так как отличий не очень много, то и статья будет не очень большая.
Итак, в предыдущей стать о функциях Modbus RTU можно узнать, какие есть функции и их бинарный формат. Теперь стоит рассказать что такое Modbus TCP, как он применяется и чем отличается от стандартного Modbus RTU.
Самый простой способ обмена Modbus сообщениями через сеть – просто передавать Modbus RTU пакеты через TCP сокет (соединение). В этом случае формат пакетов такой же, как и для Modbus RTU протокола. В принципе на этом можно и закончить по этому типу протокола.
Для обмена Modbsu сообщениями по сети решили использовать модифицированный протокол. Взяли стандартный Modbus RTU и немного его изменили. Во-первых убрали из него последних 2 байта CRC16. Так как каждый пакет TCP/IP содержит свою контрольную суму, решили что делать проверку еще раз не нужно. Кроме того убрали первый байт Slave ID. В принципе, Как будет видно дальше, Его не убрали, а просто переименовали. Вот эти байты, без Slave ID и CRC16 назвали PDU – Protocol Data Unit.
Например, возьмем запрос Modbus RTU, который читает несколько HOLDING регистров с устройства #17 (Slave ID = 17)
11 03 006B 0003 7687
Теперь убираем первый и последних 2 байта. Получаем PDU!
03 006B 0003
С этим вроде все ясно. Теперь, что бы получить полноценный пакет Modbus TCP нам нужно добавить впереди MBAP Header — Modbus Application Header. Т.е. нам нужно добавить некий заголовок. Этот заголовок включает в себя Transaction ID, Protocol ID, Length и Unit ID.
Transaction ID – 2 байта, которые устанавливаются клиентом, что бы однозначно идентифицировать каждый запрос. Т.е. это просто число от 0 до 65535 уникальное для каждого запроса.
Protocol ID – 2 байта, которые определяют версию протокола. В текущей реализации всегда должны быть равны 0x00 0x00
Length – 2 байта, которые определяют длину пакета (за исключением байтов Protocol ID, Transaction ID и Length)
Unit ID – уникальный адрес устройства, которое опрашивается данной командой. Идентично Slave ID.
Небольшое отступление по поводу адресации. Может показаться что это излишне, так как TCP соединение может быть установлено только на конкретный IP адрес и порт. Т.е. у нас уже есть конкретный адрес сервера, поэтому назначение Unit ID не совсем понятно.
Но на самом деле вполне обычна ситуация, когда есть некий сервер, который просто маршрутизирует Modbus RTU запросы на другие устройства, которые подсоединены к нему по различным каналам (локальная сеть, последовательный порт, CAN интерфейс). Поэтому клиент может использовать Modbus TCP сервер как шлюз (Gateway) для общения с устройствами за ним.
Пример Modbus TCP сервера, который используется как шлюз для перенаправления запросов на Modbus RTU устройства
Вот пример из жизни. Есть некое устройство основанное на Linux. Это устройство выступает Modbus TCP сервером. Любой клиент может подсоединиться к публичному IP адресу на порт 502 и инициировать Modbus TCP соединение. К данному Linux устройству подключены сенсоры, которые использую последовательный порт RS485. Сенсоров много, они очень простые и не могут быть подключены к Internet, у них есть только порт RS485 и они понимают только Modbus RTU. Поэтому клиенты посылают Modbus TCP запросы с Unit ID сенсоров на Modbus TCP Сервер. Сервер декодирует Modbus TCP запрос и преобразует его в Modbus RTU и отправляет в порт RS485. После того как сенсор отвечает ему, он преобразует Modbus RTU ответ в Modbus TCP ответ и отсылает его назад, к Modbus TCP клиенту, который инициировал запрос. Таким образом, имея всего один публичный IP адрес можно опрашивать онлайн сотню сенсоров, которые даже не могут быть подсоединены к Интернету или локальной сети.
А теперь наглядная схема, чем отличается Modbus RTU запрос от Modbus TCP запроса.
Различия Modbus RTU и Modbus TCP запросов
Посмотрим пример байтов для двух запросов:
Modbus RTU: 11 03 006B 0003 7687
Modbus TCP: 0001 0000 0006 11 03 006B 0003
Индекс байта | Значение | Описание |
0-1 | 0001 | Transaction ID. Уникальный идентификатор запроса |
2-3 | 0000 | Protocol ID |
4-5 | 0006 | Длина данных в запросе. 6 байт |
6 | 11 | Unit ID устройства, которое должно обработать запрос |
7 | 03 | Код команды |
8-9 | 006B | Адрес HOLDING регистра, с которого нужно начинать чтение |
10-11 | 0003 | Количество регистров, которые нужно прочитать |
Modbus TCP: 0001 0000 0009 11 03 06 AE41 5652 4340
Modbus RTU: 11 03 06 AE41 5652 4340 49AD
Индекс байта | Значение | Описание |
0-1 | 0001 | Transaction ID. Уникальный идентификатор запроса |
2-3 | 0000 | Protocol ID |
4-5 | 0009 | Длина данных в ответе. 9 байт |
6 | 11 | Unit ID устройства, которое обработало запрос. Должно быть таким же как и в запросе. |
7 | 03 | Код команды |
8 | 06 | Количество байт в ответе, которые хранят значения прочитанных регистров. |
9-14 | Байты данных |
Как видите, конвертировать запросы между Modbus RTU и Modbus TCP очень просто. Хотя реализация Modbus RTU через TCP может показаться самым простым способом для маршрутизации запросов, на самом деле в Modbus TCP есть несколько положительных моментов:
www.siv-blog.com