Сети‎ > ‎Modbus‎ > ‎

MODBUS: протокол прикладного уровня

Что такое MODBUS?
MODBUS - это промышленные сети в нескольких реализациях:
1) MODBUS RTU и MODBUS ASCII, также называемые MODBUS over Serial Line
2) MODBUS + (звучит как MODBUS Plus)
3) MODBUS/TCP, также называемые MODBUS TCP/IP
MODBUS - это также протокол прикладного уровня, тоесть правила общения между программами (также называемыми Процессами), изветен как MODBUS Application Protocol (MBAP)
Далее под MODBUS я буду подразумевать все реализации в общем, тоесть сети MODBUS, а протокол прикладного уровня буду называть MBAP.  
MODBUS разработан еще в конце 1970-х (MODICON Gould), но в современном мире он до сих пор занимает лидирующие позиции по популярности и количеству реализаций. Поддерживается и развивается  www.MODBUS.org, все стандарты открыты.    
 
Зачем нужен MODBUS?
Если Вы заглянули сюда, значит догадываетсь, что MODBUS дает возможность доступиться к данным или другим сервисам различных устройств.
К таким устройствам относятся: промышленные контроллеры, регуляторы, модули ввода/вывода, преобразователи частоты (ПЧ), различного типа вторичные приборы, пускатели, операторские панели (ОП) и многие другие устройства промышленной автоматизации. 
В свою очередь, эти данные нужны компьютерам со специальным ПО, операторским панелям, другим контроллерам и регуляторам. 
 
Какие возможности дает MODBUS?
 С помощью MODBUS, как и с помощью большинства промышленных коммуникаций (синонимы - промышленная сеть, полевая шина, fieldbus) можно провести следующие операции (доступные сервисы):
- доступиться к данным (переменным) устройства для чтения и/или записи;
- управлять состоянием устройств: запускать на выполнение программу, останавливать, инициализировать и т.д.;
- диагностировать состояние устройства (работает, в ошибке, прочитать буфер ошибок)
- и ещё много вкусностей.
НО: доступные функции и особенности их реализации сильно зависят от устройства. 
ПО-ЭТОМУ: мы будем рассматривать только самые популярные функции - это доступ к переменным для чтения и записи.
 
К каким данным (перемненым) можно доступиться с помощью MODBUS? 
 MBAP определяет вобщем 4-ре зоны (области) данных (переменных):
- Discrete Inputs (начиная с 10001), или область дискретных входов (входных битов)
- Coils (начиная с 00001), или область дискретных выходов (выходных битов) 
- Input Registers (начиная с 30001), или область входных регистров (аналоговых входов)
- Holding Registers (начиная с 40001), или область выходных регистров (аналоговых выходов)
 Таким образом, согласно MODBUS можно прочитать значение входных регистров и битов, прочитать или записать значение выходных регистров и битов.  Следует отметить, что эти зоны памяти были доступны в ранних контроллерах MODICON, для которых и был разработан протокол. В этих контроллерах непривязаные к физическим выходам выходные перемнные (Coils и Holding Registers)  можно было использовать как внутренние.
 НО: в разных реализациях MODBUS, эти зоны могут интерпритироваться по разному, это не запрещается стандартами MODBUS.ORG
 ПО-ЭТОМУ: для каждого конкретного устройства в документации определено отображение областей переменных MODBUS на его область данных.
Иными словами стандарт не определяет, к каким именно данным в конкретном устройстве вы будете доступаться, обращаясь к одной из зон памяти, это будут определять правила отображения, придуманные ... разработчиком устройства.
 
К каким данным конкретного устройства можно доступиться через MODBUS?
Для того, чтоб об этом узнать, прийдется читать документацию :-) . Тем не менее, можно выделить несколько моделей отображения.
1. Все 4-ре зоны независимые одна от другой.
2. Все зоны накладываются на одно адресное пространство. Так например, записывая значение 2 в переменную (ячейку) 4x0001 вы одновременно меняете 3x0001=2 и 0x0002=TRUE и 1x0002=TRUE. 
3. Две независимые зоны: область регистров совпадает и область битов совпадает; 
4. Две независммые зоны: область входных ресгитров и битов совпадают, область выходных регистров и битов совпадают.
 
 
В любом случае, данные на устройстве, к которым идет обращение через MODBUS могут быть и не привязаны к физическим входам/выходам устройства.
Следует также отемтить, что согласно адресации MODBUS все переменные начинаются с 1, тогда как в большинстве устройств адресация начинается с 0.   
 
Как функционирует MODBUS?
На первое время будем считать, что общаются не устройства между собой, а их программы (далее по тексту Процессы).  
Под Процессом будем понимать некоторую программную сущность (реже аппаратную), реализующую протокол MBAP. Это может быть программа, или набор функций в библиотеке, или постоянно-работающий код в операционной системе. 
 
Таким образом протокол MBAP - это язык (семантика) обмена между Процессами. Процесс, который доступается к данным (или сервисам) другого Процесса называется Клиентом (Client), а который предоставляет доступ - Сервером (Server). Если операторская панель или программа на ПК доступается к данным контроллера, то ОП/ПК в этой связи выступает в качестве Клиента а контроллер- Сервера. 
Для того, чтоб Клиент объяснил Серверу, чего он от него хочет, он должен послать сообщение-запрос (Request). Получив сообщение-запрос, Сервер его обрабатывает и возвращает сообщение-ответ (Responce). MBAP определяет правило построения сообщений запроса и ответа.
 
В общем случае сообщение (также называемое MODBUS PDU) состоит из двух частей: функция и данные
С помощью функции, занимающей в сообщении 1 байт, Клиент сообщает Серверу, какими свервисами он хочет воспользоваться. Для того чтобы полностью описать запрашиваемый сервис, одного байта не хватает. По этому Клиент размещает в части данных дополнительную информацию.
Сервер, при удачной обработке сообщения-запроса, возвращает сообщение-ответ, в котором поле функции повторяется, а в поле данных будет дополнительная информация о результатах обработки вызываемого сервиса. 
При неудачном выполнении или невозможности выполнения сервиса, Сервер сообщает об ошибке, путем размещения в сообщении номера функции с модифицированым старшим битом в 1-ке. В поле данных Сервер размещает код ошибки (один байт). 
Следует отметить, что согласно протоколу MBAP ряд функций не требуют возвращения сообщения-ответа.      
 
Какие функции MODBUS нужно использовать для чтения данных?  
С помощью функций чтения можно прочитать значение доступных ячеек с любой  зоны (области) данных. Все функции чтения групповые, тоесть предназначены для чтения нескольких ячеек (переменных). Доступны такие функции:
01 - чтение Coils (дискретных выходов);
02 - чтение Discrete Inputs (дискретных выходов);
03 - чтение Holding Registers (аналоговых выходов, выходных регистров);
04 - чтение Input Registers (аналоговых входов, входных регистров).
 
Рассмотрим на примере формат сообщений запроса от Клиента и ответа от Сервера для наиболее популярной функции 03 (чтение Holding Registers). Допустим, нужно прочитать выходные регистры с 108-го по 110-й (40108, 40109, 40110).
Перед тем как составить запрос, следует отметить один важный момент - регистры (и другие ячейки) в модели MBAP нумеруются с 1-го, а в запросе с 0-го. Это одна из самых запутанных историй, из за которых "танцуют с бубнами" не только новички :-)
Благо, что в большинстве моделей отображения зоны проецируются на ячейки с номерами от нуля, и все становится на свои места. Допустим в контроллерах Modicon М340 или Premium, зоны Input Registers и Holding Registers  проецируются на внутренние переменные %MW начиная с нуля. То-есть ячейки 40108, 40109, 40110 (так же как и 30108, 30109, 30110)  на самом деле будут находиться в переменных  %MW107, %MW108, %MW109. Таким образом 108-й регистр в запросе указывается под номером 107 (6В hex, где hex - это 16-тиричное представление).
Формат запроса и положительного ответа показан на рисунке 
Разберём сообщение-запрос по байтам. Первый байт = 03 - номер функции, то есть чтение Holding Registers. Любой клиентский запрос MBAP начинается с однобайтного поля функции. Дальше идет уточнение: нужно прочитать регистры начиная с 107-го (6B hex), 3 штуки. Обратите внимание указывается не с "какой" по "какую", а с "какой" и "сколько". Причем для адреса начального регистра и их количества в запросе всегда выделяются 2 байта: сначала передается старший (HI) а потом - младший (LO). Учитывая, что 6B занимает один байт, старший байт заполняется нулями. Итак, сообщение-запрос можно озвучить так:
            прочитать Holding Registers, начиная с 006B hex, 0003 штуки     
 
Сервер, при положительном результате обработки, ответит сообщением, в котором первый байт будет повторять код функции, в данном случае =03. Следующий байт указывает на количество байт с данными, идущие в сообщении после него (счетчик байт). Учитывая, что регистры являются 16-разрядными, значение каждого из них будет передаваться 2-мя байтами: 3 регистра * 2 = 6 байт. Значение каждого регистра передается в таком порядке - сначала старший байт (HI) потом младший (LO). Таким образом, сообщение-ответ можно озвучить так:
            ответ на чтение Holding Registers, содержит 6 байт, с такими значениями: CD6B hex, 0005 hex, 0064 hex
 
HI и LO, что это такое, зачем мне это понимать?
Следует отметить, что регистры в устройствах также могут иметь разное представление. Кроме того, что они могут быть не только 16-ти разрядными, но и 32 или даже 64 разрядными, они ещё и по разному хранятся и интерпритируются. Для лучшего понимания вопроса советую почитать Википедию с определением "Порядок байтов". Тут же приведу абсолютно бесполезную в данном случае, но интересную цитату из той же Википедии:
Термины big-endian и little-endian первоначально не имели отношения к информатике. В сатирическом произведении Джонатана Свифта «Путешествия Гулливера» описываются вымышленные государства Лилипутия и Блефуску, в течение многих лет ведущие между собой войны из-за разногласия по поводу того, с какого конца следует разбивать варёные яйца. Тех, кто считает, что их нужно разбивать с тупого конца, в произведении называют «Big-endians» («тупоконечники»). Споры между сторонниками big-endian и little-endian в информатике также часто носят характер т. н. «религиозных войн»
То-есть, возможно вам придется позаботиться о том, чтобы после получения ответа, переставить местами байты, чтобы их правильно итерпритировал контроллер или SCADA. Когда-то услышал из уст одного из слушателей фразу: "это Вы о проблеме больших и малых индейцев?" :-) 
   
Какие функции MODBUS нужно использовать для записи данных?
Запись возможна только в область Coils и Holding Registers. Но, в отличии от чтения, запись можно производить как группой переменных, так и по одной. Доступны такие функции для записи:
05 - запись одного дискретного выхода (Coil)
15 (0F hex) - запись нескольких дискретных выходов (Coils) 
06 - запись одного выходного регистра (Register)
16 (10 hex) - запись нескольких регистров (Registers)
Рассмотрим формат наиболее популярной функции - 16 (10 hex). В этом примере будем писать значение все тех же 3-х переменных (40108, 40109, 40110).
 
 
Не будем тут останавливаться на особенностях адресации. Я думаю, что если с функцией 03 все понятно, то тут особых проблем с пониманием не возникнет. Вначале указывается функция, потом адрес и количество тех регистров, куда будет производиться запись. Затем следует счетчик байт, которые непосредственно передаются за эти полем. Поскольку это функция записи, то за полем счетчика идут данные. Вобщем, диалог Клиента и Сервера можно озвучить так:
Клиент делает запрос:
    записать Holding Registers, начиная с 006B hex, 0003 штуки, данные содержат 6 байт со значениями CD6B, 0005, 0064
Сервер отвечает:
    Holding Registers записал, начиная с 006B hex, 0003 штуки
Формат сообщений запросов и ответов для остальных функций без проблем можно найти в Интернете или даже на этом сайте, например тут
 
Почему Клиент получает от Сервера не такой ответ?
До сих пор мы рассматривали только положительные ответы, тоесть когда Сревер смог выполнить сервис(услугу), запрашиваемый Клиентом. Но, как уже отмечалось, бывают ситуации, когда Сервер по каким-то причинам не может выполнить услугу. В таких случаях Сервер отвечает сообщением-ответом с ошибкой. Для того, чтоб Клиент понял, что ответ является сообщением с ошибкой, Сервер  в поле функции вставляет то же значение функции, что и в запросе, но с установленым старшим битом в "1". Допустим, если Сервер не может обработать функцию 03 hex (0000 0011 bin, где bin - это двоичное представление) , он меняет его на 83 hex (1000 0011 bin). 
Но Клиенту кроме самого факта ошибки желательно бы еще и узнать причину  ошибки. Для этого в MBAP предвидено второе поле сообщения-ответа с ошибкой - код ошибки с размером в один байт. 
Допустим, в сообщении-запросе Клиент запросил у Сервера прочитать 1000 Holding Register, которого не существует в его адерсном пространстве. Сервер ответит сообщением, формат которого представлен на рисунке слева - 02="ILLEGAL DATA ADDRESS".
Другой пример, когда Клиент неправильно сформирует сообщение-запрос, например отправит меньшее количество байт, чем ожидается. В этом случае Сервер ответит сообщением с кодом ошибки 03="ILLEGAL DATA VALUE" (на рисунке слева).              
 Остальные коды ошибок можно найти в Интернете или тут
 
Почему Клиент не получает ответа от Сервера?
До сих пор мы говорили о обмене между двумя Процессами, один из которых что-то хотел (Клиент), а другой - от кого чего-то хотели (Сервер). В этом обмене мы не затрагивали вопросов доставки сообщений от одного Процесса к другому и наоборот ,и считали что они как-то "соединены между собой".  На самом деле сообщение-запрос может не дойти до Сервера или сообщение-ответ может не дойти до Клиента. Почему? Это мы рассмотрим при изучении Modbus RTU и Modbus TCP, которые базируются на MBAP. Если эта ситуация имеет место быть - Клиент не дождется ответа.
Что в этом случае делать Клиенту? Как правило, все Клиентские коммуникационные функции (например в контроллере) снабжены тайм-аутом. Тайм-аут - это максимальное время ожидания ответа, после которого Клиент считает, что ответа не будет. Если обмен очень медленный - таймаут стоит увеличивать, если быстрый - увеличение таймаута приводит к ненужному торможению обмена (вместо ожидания ответа, Клиентская программа могла бы опросить другой Сервер).  
 
Клиенты...Серверы... а где же сетевой обмен?
Попробуем представить, что Процессы обмениваются через некие буферы сообщений. Есть входной и выходной буферы как у Клиента так и у Сервера, которые соединены между собой неявными связями. Тоесть, всё что помещается в выходной буфер Клиентского Процесса - автоматически появляется во входном Серверного и наоборот. В этом случае, всё описанное высше достаточно, чтоб обеспечить обмен.
 
Но в реальной жизни Процессы всегда находятся на разных устройствах, и MODBUS то нам нужен, чтоб доставить данные с одного устройства на другое. Доставка сообщений-запросов и сообщений-ответов обеспечивается фнкционированием различных сетевых сервисов, в зависимости от выбраной сети.   
     
 
 
Comments