Переменные MODBUS ================= Элемент **Переменные modbus** в шаблоне контроллера, работающего в режиме главного устройства, позволяет упрощенно обращаться к переменным подчиненного контроллера. Для каждого экземпляра подчиненного контроллера нужно добавить отдельный пункт **Переменные modbus**: .. figure:: image/modbus_vars1.png :align: center Редактирование списка переменных доступно вручную. Возможен импорт переменных из файла с расширением **mbm**. Этот файл можно получить, экспортируя сетевые переменные из любого шаблона программы. Кроме того, при перетаскивании мышью шаблона подчиненного устройства в окно списка в список добавляются все сетевые переменные подчиненного устройства. Предполагается, что для каждого подчиненного контроллера в главном будет создаваться отдельно один или несколько списков переменных, поэтому настройки адреса подчиненного и другие его опции относятся к списку в целом. Список переменных MODBUS: .. figure:: image/modbus_vars2.png :align: center Переменные, содержащиеся в списке, могут использоваться в FBD-программе так же, как и глобальные переменные. Отличие заключается в том, что переменные modbus автоматически синхронизируются с подчиненным устройством. Кроме основных свойств, аналогичных глобальным переменным, у переменных Modbus есть параметр **Период**. Этот параметр задается в миллисекундах и определяет частоту, с которой будет опрашиваться переменная. Синхронизация выполняется 3 возможными способами, в зависимости от настройки **Режим работы**: #. **Только запись** - переменная никогда не читается из подчиненного, первоначально и при изменении значения подчиненному отправляется команда записи. При отсутствии изменений команды записи быстро прекращаются, настройка **Период** игнорируется. #. **Только чтение** - переменная читается из подчиненного, первоначально и далее с указанным периодом, запись в подчиненного не выполняется. Для уменьшения вероятности ошибок проектирования запрещено создавать блоки записи для переменных с этим режимом. #. **Чтение, синхронизация изменений** - переменная читается из подчиненного, так же, как в режиме "только чтение". Однако, если переменная изменяется по любой причине, кроме чтения из подчиненного, включается команда записи. Во время записи команды чтения не выполняются. В случае повторного изменения переменной, даже в процессе выполнения первоначальной записи, выполняется повторная запись, поэтому переменная может меняться с произвольной частотой. Следует понимать, что нет гарантии того, что все изменения будут успешно синхронизированы - даже при идеальном качестве связи могут встречаться противоречивые команды изменения переменной из различных программ! Если требуется хранение переменной при выключенном питании, то для режимов 2 и 3 это должен реализовать подчиненный контроллер, а для 1 режима - главный. Для включения/выключения и повтора команд чтения-записи в программе скрыто создаются соответствующие логические переменные, управляющие состоянием синхронизации. Собственно команды чтения-записи создаются как блоки **Чтение (slave)** и **Запись (slave)**, с соответствующими логическими блоками, связанными между собой. В случае ошибок связи с подчиненным контроллером все состояния синхронизации сбрасываются в исходное состояние - в 1 режиме включается запись, иначе включается чтение. Как следствие, при восстановлении связи переменные с 3 режимом получат значения из подчиненного, т.е. последние не записанные изменения будут потеряны. **!!!Внимание** Если все переменные имеют 1 режим и меняются редко, возможна ситуация, когда в подчиненный контроллер долгое время никакие команды не отправляются. В результате, если подчиненный будет внезапно перезагружен, его переменные будут иметь ошибочные значения. Поэтому для проверки наличия связи с подчиненным рекомендуется иметь как минимум одну читаемую переменную, даже если ее значение не нужно. Тогда при ошибке чтения все переменные в режиме **Только запись** будут повторно записываться. Переменные при создании команд чтения-записи автоматически группируются при наличии такой возможности при совпадении кодов команд и при последовательном расположении регистров/коилов. При группировке учитывается максимальный размер буфера приема-передачи в главном и подчиненном устройствах. Таким образом, при последовательном расположении регистров и небольшом количестве переменных может быть единственная команда чтения и единственная команда записи. В текущей версии такую группировку полностью отменить невозможно, а можно только разделить один элемент **Переменные modbus** на несколько, при этом объединение переменных выполняется отдельно в каждом списке. Функции modbus в командах чтения выбираются в соответствии с настройкой "Тип функции чтения" и типа данных переменной. При настройке **Чтение памяти**, выбираются функции modbus 1 и 3, иначе 2 и 4, для логического и прочих типов данных, соответственно. Для записи используются функции 5, 6, 15, 16, в зависимости от типа данных и количества записываемых регистров/коилов. Для доступа к переменным из FBD-программы необходимо выделить элемент **Переменные modbus**, а затем перетащить переменную из панели **Навигатор** в окно FBD-программы. При этом появится блок, аналогичный показанному на рисунке ниже, позволяющий читать или записывать переменную, полностью аналогично блокам чтения-записи локальных и глобальных переменных. При перетаскивании мышью элемента **Переменные Modbus** в FBD-программу появляется блок c таким же названием, предоставляющий доступ к управлению синхронизацией. Этот блок не обязателен, он позволяет дополнительно управлять синхронизацией при необходимости, и просматривать ее состояние. .. figure:: image/modbus_vars3.png :align: center Входы блока управления: * **dev** - адрес подчиненного устройства. Если не подключен - используется константа **Адрес устройства**, указанная в настройках; * **en_read** - признак разрешения команд чтения, для временного запрета команд. Если не подключен - используется 1; * **en_write** - признак разрешения команд записи, для временного запрета команд. Если не подключен - используется 1; * **start_read** - команда принудительного начала чтения всех читаемых переменных из подчиненного, дополнительно к указанным выше условиям; * **start_write** - команда принудительного начала записи всех записываемых переменных из подчиненного, дополнительно к указанным выше условиям; Выходы блока управления: * **reading** - признак необходимости выполнения в данный момент чтения какой-либо переменной; * **writing** - признак необходимости выполнения в данный момент записи какой-либо переменной; * **is_err** - признак получения ошибки связи в подчиненным в данном такте; * **err** - код ошибки, полученный в данном такте;