После установки сервера ModbusTCP у нас уже есть настроенный конфигурационный файл, которым заранее удобно пользоваться. Все адреса десятеричные и все это можно позднее переделать под себя в том же конфигурационном файле. Пока же воспользуемся параметрами заданными по умолчанию в конфигурационном файле. Сетевой порт TCP = 502, полезная справочная документация = Mapping between Modbus and ADS.
Работа со стандартными массивами
Немецкие инженеры о нас позаботились — четыре заранее сформированные массива открывают доступ к данным Modbus. Причем открывают без какой-либо головоломки с расчетом индексов, упаковкой битов в слова и других отвлекающих преобразований.
После установки на ПЛК сервера ModbusTCP, последний автоматически ищет четыре глобальные переменные с заранее заданными именами.
Эти имена (или пара индекс-смещения) задаются в конфигурационном файле в разделах <VarName> или парой <IndexGroup> // <IndexOffset>.Еще раз: в самой ПЛК-программе, вам ничего добавлять не нужно: сервер сам попытается найти эти имена среди глобальных переменных, и если найдет — автоматически начнет трансляцию данных по шине Modbus. Включать в проект дополнительные библиотеки не требуется, просто добавляем в глобальные переменные четыре массива:
.mb_Input_Coils [0..255] OF BOOL .mb_Output_Coils [0..255] OF BOOL .mb_Input_Registers [0..255] OF WORD .mb_Output_Registers [0..255] OF WORD
С точки зрения ModbusTCP массивы получают адреса начиная с 3276810 (или 0x800016). Расчет полного адреса ведется с учетом индекса в массиве:
.mb_Input_Coils [0..255] OF BOOL .mb_Output_Coils [0..255] OF BOOL Адрес Modbus = 32768 + индекс в массиве (0..255)
Одна катушка или дискретный порт ввода-вывода соответствует одной ячейке массива типа BOOL. Это очень удобно, так как не требуется упаковка битов в "слово". Аналогично с регистрами:
.mb_Input_Registers [0..255] OF WORD .mb_Output_Registers [0..255] OF WORD Адрес Modbus = 32768 + индекс в массиве (0..255)
В каждом массиве всего 256 элементов, поэтому адресация этих массивов заканчивается для Modbus на числе 33023. Полный диапазон 32768..33023.
Для клиента .mb_Input-Coils/Registers массивы доступны только для чтения (функции модбас #2, #4). .mb_Output-Coils/Registers доступны и для чтения (функции #1 #3), и для записи (функции #5, #6).
Переменные ввода/вывода
Дополнительно к массивам, автоматически транслируется область переменных ввода-вывода, то есть также одновременно транслируются те переменные, которые связаны с физическими входами/выходами или, иначе говоря, переменные, которые обозначены как AT %I* и AT %Q*. Простые правила помогут запомнить что-с-чем ассоциируется:
- Катушки (coils) можно намагничивать и размагничивать — поэтому они могут менять свое значение и поэтому они связаны с AT %Q*. Аналогичное правило для регистров хранения (holding registers): в них тоже можно сохранять и читать.
- Inputs — это входа и они только для ввода данных, поэтому записывать нельзя — AT %I*.
Чтение с помощью функций модбаса:
- Катушки %QX — функция #1, Read Coils.
- Регистры хранения %QB, %QW,... — #3, Read Holding Registers.
- Дискретные входа %IX — функция #2, Read Discrete Inputs.
- Дискретные регистры ввода %IB, %IW,... — #4, Read Input Registers.
Запись доступна только для катушек и регистров хранения, по одному за раз, но вообще можно и несколько за раз (функции 15 и 16):
- Катушки %QX — функция #5, Write/Force Single Coil.
- Регистры хранения %QB, %QW,... — #6, Write/Preset Single Register.
В итоге выстраивается стройная система — с точки зрения Modbus, мы номером функции выбираем тип переменных (чтение/запись, катушки/регистры), а затем адресом уточняем какую именно переменную мы хотим.
Адрес Modbus для переменных ввода данных (AT %I) лежит в диапазоне 0..32767. Для переменных ввода/вывода (AT %Q, катушки и регистры хранения) верхняя граница занижена 0..12287, иначе они будут пересекаться с меркерной памятью (читай ниже).
Расчет адресов идет по единому принципу и для тех, и для других. Так как дискретные или битовые входа/выхода упаковываются в байты — значения адресов Modbus придется немного повычислять, :
Адрес Modbus для переменных ввода данных (AT %I) лежит в диапазоне 0..32767. Для переменных ввода/вывода (AT %Q, катушки и регистры хранения) верхняя граница занижена 0..12287, иначе они будут пересекаться с меркерной памятью (читай ниже).
Расчет адресов идет по единому принципу и для тех, и для других. Так как дискретные или битовые входа/выхода упаковываются в байты — значения адресов Modbus придется немного повычислять, :
%IX#.@ (где # — номер байта, @ — номер бита в байте) %QX#.@ Адрес Modbus = # / 2 * 16 + @ = # * 8 + @
Пример:
bSomeVar AT %IX6.2 : BOOL; Адрес Modbus = 6 * 8 + 2 = 50
Для байтовых входов/выходов важно учитывать, что чтение с шины Modbus идет 16-разрядными словами. Чтобы прочитать байт, нужно прочитать слово целиком, а затем выделить из слова байт. Важно знать порядок следования байтов в слове — он не определен!
%IB# (где # — номер байта) %QB# Адрес Modbus = # / 2
Modbus 0 = %IB1 : %IB0
Modbus 1 = %IB3 : %IB2
Modbus 2 = %IB5 : %IB4
%IB123 → 123 / 2 = 61.5 ≈ 61 → Modbus 61 = %IB123 : %IB122
...
"Слова" состоят из двух байт, поэтому идут с шагом два. Например, для %IW и %QW:
iSomeVar0 AT %QW0 : WORD; iSomeVar1 AT %QW2 : WORD; iSomeVar2 AT %QW4 : WORD; [...] iSomeVarN AT %QW# : WORD; Адрес Modbus = # / 2
Меркерная память
Для шины Modbus эта область памяти (AT %M*) лежит в диапазоне адресов 12288..24575. Адреса строятся аналогично переменным ввода/вывода из предыдущего пункта.
Обратите внимание, что адреса Modbus для меркерной памяти пересекаются с адресами переменных ввода/вывода %Q и в то же время не пересекаются с адресами переменных ввода %I. Это происходит по причине доступности переменных %M как на чтение, так и на запись, аналогично переменным ввода/вывода %Q. Именно поэтому M- и Q-области памяти выглядят одинаково с точки зрения Modbus, а значит и доступны с помощью одних и тех же функций Modbus.
Порядок слов
Modbus как таковой ничего о типах данных не знает и перегоняет битовые единицы упакованными в "слово", а регистры просто как "слова" (WORD). При этом протокол ничего не знает ни о знаке числа (для него все числа целые), ни о плавающей запятой, ни о порядке байт в слове.
Например, я сейчас включил ПЛК и при использовании типа WORD получил следующую картину:
%MB0 — младший байт
%MB1 — старший байт
%MW0 — 12288 (%MB1 : %MB0)
%MW2 — 12289 (%MB3 : %MB2)
%MW4 — 12290 (%MB5 : %MB4)
...а мой сосед включил сервоусилитель какой-то другой фирмы и получил обратный порядок байт, что смешало бы значения параметров в кашу. Проверяйте!
Загадочные области памяти
На самом деле — нет, но начиная с 24576 идет область данных, где хранятся значения переменных ПЛК-программы. Отсюда можно вытащить значения обычных локальных и глобальных переменных ПЛК-программы. Правда порядок их следования не гарантирован, поэтому использовать не рекомендуется.
Обновлено: 12 ноября 2017 г.
Не могли бы вы сделать пошаговый обзор использования ПЛК Beckhoff совместно с OpenHub?
ReplyDeleteОчень полезная статья! Нашел у себя ошибки с вашей помощью. Благодарю!
ReplyDelete