Режим мастера

Для работы порта в режиме мастера необходимо установить соответствующую настройку порта контроллера. После этого на схему можно устанавливать блоки, предназначенные для чтения и записи переменных подчиненных устройств, подключенных к соответствующему каналу связи.

Блок Чтение (Slave)

_images/fbd_modbus_read.png

Описание: Производит чтение значений по протоколу Modbus из подчиненного устройства. Запись выполняется асинхронно, т.е. каждый блок, в зависимости от состояния порта, либо ожидает освобождения порта, либо обрабатывает команду. Порт поочередно передается между блоками. Последовательность передачи порта между блоками не определена, но гарантировано, что активные блоки будут выполняться с приблизительно одинаковой частотой. Обработка команды выполняется за несколько шагов выполнения схемы. Она состоит из следующих этапов (упрощенно, полная диаграмма перехода состояний выполняется согласно “Modbus over serial line”, см. Modbus.org для уточнения):

  1. Ожидание освобождения порта (т.е. из блоков, использующих одинаковый порт, выполнять команды будет только один из них)
  2. Если en = 0 - передача порта другому блоку, возврат на этап 1. Если en = 1 - составление пакета запроса в буфере для передачи в зависимости от значений на входах, начало передачи, выдача 1 на выход sent.
  3. Отправка байтов пакета.
  4. Ожидание начала ответа в течение определенного времени таймаута, если ответ подчиненного устройства не начался в течение таймаута и количество попыток не превышает 3 – вернуться на шаг 2, если количество попыток превышает 3 и en = 1 – перейти на этап 7 с ошибкой 16.
  5. Ожидание продолжения и окончания ответа.
  6. Проверка целостности ответа (CRC), правильности его длины и содержимого. Если en = 0 - передача порта другому блоку и переход на этап 1. Если есть ошибка, при количестве попыток не больше 3 – переход на шаг 2, иначе – переход на шаг 6 с соотв. ошибкой. Если ошибок нет – успешное завершение обработки: выдача 1 на выход rdy, 0 на выход err, обнуление счетчика ошибок, передача порта для использования другому блоку.
  7. Выдача 0 на выход rdy, кода ошибки - на выход err, обнуление счетчика ошибок, передача порта для использования другому блоку.

Этапы 2 и 6 выполняются за 1 шаг выполнения схемы. Этапы 1, 3-5 могут длиться продолжительное время, в это время значения всех входов игнорируются, значения всех выходов, за исключением выходов valX, равны 0. Этап 7 всегда выполняется в одном шаге вместе с предыдущим этапом.

Вход port - номер порта контроллера, через который будет производится запрос. На этом входе должна быть установлена константа. Этот вход может быть подключен к какому-либо выходу, но при условии, что значение этого выхода должно быть неизменным, что определяется при оптимизации схемы во время программирования устройства или начала симуляции. Тип данных - беззнаковое однобайтовое целое. Нумерация портов начинается с нуля.

Вход en задает активность блока: если установлено 1, команда будет выполняться, иначе – порт будет передан другому блоку на ближайшем шаге 2 или 6. Если свойство блока Удерживать en не установлено, вход должен удерживаться в 1 в течение многих шагов выполнения схемы, чтобы было достаточно времени для выполнения всех этапов, т.е. до появления 1 на rdy или ненулевого err. Для ускорения срабатывания активных блоков рекомендуется устанавливать 0 на входы en блоков, которые выполнять не требуется.

Вход dev – адрес подчиненного устройства, в которое будет производиться запись.

Вход reg указывает адрес регистра или дискретного входа, начиная с которого будет производиться чтение.

Количество считываемых значений задается свойством блока «Количество выходов» (по умолчанию 1).

Т.к. обработка блока выполняется в течение нескольких шагов выполнения схемы, на этапе 6 блок не имеет данных, которые были на входах на этапе 1. Поэтому значения входов рекомендуется удерживать в неизменном виде. Выход sent устанавливается в 1 в момент составления запроса на этапе 1. Он позволяет определить, какие именно данные, в случае их изменения во времени, были отправлены. Если между выдачей 1 на выходе sent и выдачей 1 на rdy значения входов были изменены, прочитаны будут данные, соответствующие входам в момент, когда sent = 1.

Выход rdy устанавливается в 1 в случае успешного выполнения операции записи. В случае сбоя записи на выходе err выставляется код ошибки. Значения на выходах rdy и err устанавливаются только на один шаг программы (одиночное значение), поэтому для их фиксации необходимо использовать локальные переменные. В большинстве шагов выходы rdy и err равны 0 – это значит, что либо порт устройства занят другим блоком или порт находится находится в процессе выполнения запроса (на этапе 1-4). Считанные значения выдаются на выходы valX. Тип данных устанавливается для каждого выхода индивидуально. Они действительны только, если выход rdy равен 1. В других случаях, в зависимости от реализации устройства, они могут принимать либо значение 0, либо случайное значение.

Свойство блока Порядок байтов в регистре управляет следованием байтов в регистре. Протокол Modbus рекомендует, чтобы устройства должны передавать сначала старший байт, затем младший: при отображении числа в буфере приема-передачи оно удобно для чтения человеком, число 0x1234 передается как 0x12, затем 0x34. Но некоторые устройства передают числа так, как они хранятся в памяти устройства. Если устройство хранит числа в формате «little endian» (младший адрес ячейки хранит младший байт), в буфере приема-передачи также байты могут быть в порядке от младшего к старшему: число 0x1234 передается как 0x34, затем 0x12.

Свойство блока Порядок регистров управляет следованием регистров при передаче 4-байтовых величин. Смысл свойства аналогичен свойству Порядок байт в регистре, однако для этого свойства в спецификации протокола Modbus нет рекомендаций, каждое устройство либо настраивается на определенный порядок, либо имеет строго определенный порядок.

На выходы valX (где X указывает на номер величины, нумерация с 0) блок выдает считанные значения на этапе 6, одновременно с rdy = 1. Если свойство блока Фиксировать значения выключено, когда rdy = 0, значения этих выходов также равны 0, что позволяет экономить память и ускорять работу блока. Но в таком случае схема обычно должна содержать переменные и блоки для сохранения считанных значений. Если свойство блока Фиксировать значения включено (по умолчанию для новых блоков) - эти выходы сохраняют значения до следующего этапа 6, для чего блок дополнительно использует внутренние переменные. Тип данных для каждого выхода valX может быть настроен произвольно и независимо от других выходов. Однако, в связи с особенностями протокола Modbus, дискретный (логический) тип данных имеет отдельные коды команд чтения-записи и отдельную адресацию, поэтому все выходы одного блока должны иметь либо логический тип, либо любые другие. Код функции Modbus выбирается автоматически, в зависимости от установленного типа данных выхода val. Остальные выходы должны иметь соответствующий тип данных, иначе при проверке схемы блок выдаст ошибку.

Список возможных кодов ошибок, выдаваемых на выход err:

  • 1 – устройство ответило, что запрашиваемая функция не поддерживается;
  • 2 – устройство ответило, что отсутствует запрашиваемый адрес регистра;
  • 3 – устройство ответило, что неправильный пакет запроса: ошибочная длина пакета, ошибочное значение или другая проблема, специфичная для устройства;
  • 4-15 – устройство ответило указанным кодом ошибки;
  • 16 – нет ответа от устройства в течение установленного таймаута;
  • 17 – неправильная контрольная сумма ответа;
  • 18 – адрес устройства в ответе не соответствует запросу;
  • 19 – код функции в ответе не соответствует запросу;
  • 20 – неправильная длина ответа.

Пример 1 использования блока:

_images/Modbus4.png

Простая схема реализации чтения одной переменной представлена на рисунке. Для работы схемы нужно создать две переменные. Переменная enable – логическая, значение по умолчанию 1. Переменная Var имеет тот же тип данных, что и блок. В неё производится сохранение считанного значения. В начальный момент времени на входе en блока установлена 1, следовательно, производится операция чтения. В случае успешного чтения на выходе rdy устанавливается логическая единица. При этом происходит запись значения с выхода val в переменную Var и запись нуля в переменную enable. Так как переменная enable устанавливается в 0, чтение прекращается. Таким образом, указанная схема позволяет производить однократное чтение данных из подчиненного устройства, выполняя эту команду после включения питания устройства до первого успешного выполнения.

Пример 2 использования блока:

_images/Modbus5.png

Другой вариант схемы использует RS-триггер, что позволяет производить чтение регистра произвольное число раз. Для начала чтения необходимо подать 1 на вход S RS-триггера. При этом триггер переключится в единичное состояние и установит значение переменной enable в единицу, чем активирует процесс чтения. В случае успешного чтения выход rdy установится в единицу, что приведет к записи значения с выхода в переменную Var и сбросу триггера в нулевое состояние. При этом переменная enable станет равна нулю и чтение прекратится. Для следующего цикла чтения необходимо изменить переменную “read” с 0 в 1.

Блок чтения использует следующие функции Modbus:

  • 1 (0х01) – Чтение койлов (Read Coil)
  • 2 (0х02) – Чтение дискретных входов (Read Discrete Inputs)
  • 3 (0х03) – Чтение хранимых регистров (Read Holding Registers)
  • 4 (0х04) – Чтение входных регистров (Read Input Registers)

Выбор функции осуществляется в зависимости от свойства блока Тип функции и типа данных выхода val:

Тип данных /Тип функции Чтение памяти Чтение входов
Логический 1 2
Числовой 3 4

Тип функции Чтение станд. регистров является служебным и используется только в спец. проектах.

В FBD-программах подчиненных устройств оба типа функций работают одинаково, т.е. функции 1 и 2 выдают одни и те же значения, как и функции 3 и 4.

При чтении нескольких регистров необходимо учитывать, что адреса зависят от разрядности выбранного типа данных. Для типов данных, разрядность которых не превышает 2 байтов, адресация будет увеличиваться на единицу для каждой следующей величины. Для типов данных, умещающихся в 4 байта (4-байтовые целые и дробные), адресация будет увеличиваться на 2. Например, если на входе reg установлено значение 10, количество выходов установлено 5, а тип данных всех выходов 4-байтовое целое, то у подчиненного устройства будут запрашиваться 10 регистров - с адреса 10 по 19.

Блок Чтение переменных

Описание: Блок выполняет команду чтения, полностью аналогично блоку Чтение (slave). Отличие заключается в том, что для удобства использования состав считываемых величин (выходов) и их свойства определяются автоматически, исходя из имеющейся в проекте программы подчиненного устройства. Это автоматическое определение выполняется так:

  • в свойстве блока Программа подчиненного указывается ссылка на программу подчиненного устройства.
  • в свойстве блока Начальная переменная* указывается ссылка на переменную подчиненного устройства, начиная с которой будет выполняться чтение.
  • в свойстве блока Кол-во переменных указывается количество переменных в команде.

После изменения свойств блока или после изменения программы подчиненного устройства нужно обновить блок, чтобы выходы блока автоматически настроились. Блок будет выполнять чтение указанного количества переменных, расположенных последовательно по адресам, непосредственно после начальной переменной. Если таких переменных нет, или нет указанного количества, количество выходов блока будет меньше указанного в свойстве Кол-во переменных. Названия выходов, вместо valX, будут соответствовать названиям переменных подчиненного устройства.

Вход reg, в отличие от блока Чтение (slave), не требуется подключать. Если он не подключен, используется неизменное значение адреса начальной переменной. Поэтому подключать константу ко входу reg не имеет смысла. Подключение входа reg рекомендуется использовать для динамического переключения между одинаковыми по структуре группами переменных.

Блок Запись (Slave)

_images/fbd_modbus_save.png

Описание: Производит запись величин, поданных на входы valX, в подчиненное устройство. Запись выполняется асинхронно, т.е. этот блок, в зависимости от состояния порта либо ожидает освобождения порта, либо обрабатывает команду. Обработка команды выполняется за несколько шагов выполнения схемы. Обработка выполняется последовательно, аналогично блоку Чтение (slave). Логика работы выходов и входов, кроме входов значений valX, также аналогична блоку Чтение (slave).

Вход en задает активность блока: если установлено 1, команда будет выполняться, иначе – порт будет передан другому блоку на ближайшем шаге 2 или 6. Если свойство блока Удерживать en установлено, на вход en можно подавать кратковременные (или одинарные) импульсы, блок будет устанавливать внутренний признак en по такому импульсу и снимать его одновременно с выдачей 1 на rdy или ненулевого err.

Если свойство блока Удерживать en не установлено, вход должен удерживаться в 1 в течение многих шагов выполнения схемы, чтобы было достаточно времени для выполнения всех этапов, т.е. до появления 1 на rdy или ненулевого err.

Вход dev – адрес подчиненного устройства, в которое будет производиться запись. Вход reg указывает начальный адрес регистра или дискретного входа, в который будет производиться запись. Количество записываемых параметров задается свойством блока Количество входов (по умолчанию 1). Значения для записи подаются на входы val , val1 , val2 и т.д. Тип данных можно указать для каждого блока в отдельности. Нельзя использовать совместно логический тип данных с другими, так как для записи лог. данных используются другие функции.

На входы valX (где X указывает на номер величины, нумерация с 0) подаются значения для записи. Тип данных для каждого входа valX может быть настроен произвольно и независимо от других выходов. Однако, в связи с особенностями протокола Modbus, дискретный (логический) тип данных имеет отдельные коды команд чтения-записи и отдельную адресацию, поэтому все выходы одного блока должны иметь либо логический тип, либо любые другие. Код функции Modbus выбирается автоматически, в зависимости от установленного типа данных выхода val. Остальные выходы должны иметь соответствующий тип данных, иначе при проверке схемы блок выдаст ошибку.

Т.к. обработка блока выполняется в течение нескольких шагов выполнения схемы, на этапе 5 блок не имеет данных, которые были на входах на этапе 1. Выход sent устанавливается в 1 в момент составления запроса на этапе.

Он позволяет определить, какие именно данные, в случае их изменения во времени, были отправлены. Если между выдачей 1 на выходе sent и выдачей 1 на rdy значения входов были изменены, записаны будут значения, которые были на входах в момент 1 на выходе sent . Если схема анализирует необходимость выполнения команды на основе сравнения ранее записанных и новых данных, такое сравнение нужно делать с последними отправленными значениями, когда sent = 1. Например, если отправленные значения нужно сохранить в переменные для последующего сравнения, такое сохранение нужно выполнять с помощью блока условной записи, подключив на его вход en выход sent . Выход rdy устанавливается в 1 в случае успешного выполнения операции записи. В случае сбоя записи на выходе err выставляется код ошибки. Значения на выходах rdy и err устанавливаются только на один такт программы (одиночное значение), поэтому для их фиксации необходимо использовать локальные переменные. В большинстве шагов выходы rdy и err равны 0 – это значит, что либо порт устройства занят другим блоком, либо порт находится находится в процессе выполнения запроса (на этапе 3-6).

Список кодов ошибок см. в блоке чтения. Если адрес подчиненного устройства равен 0 – выполняется «широковещательный запрос», который все подчиненные устройства выполняют без ответа. При широковещательном запросе этапы 4–7 не выполняются, вместо этого через некоторое время «turnaround delay» после передачи последнего байта запроса команда считается выполненной успешно. Хотя результат ее выполнения неизвестен, на выход rdy выдается 1.

Блок записи использует следующие функции Modbus:

  • 05 (0x05) - Запись одного коила (Write Single Coil)
  • 15 (0x0F) - Запись нескольких коилов (Write Multiple Coils)
  • 06 (0x06) - Запись одного регистра (Write Single Register)
  • 16 (0x10) - Запись нескольких регистров (Write Multiple registers)

Выбор функции осуществляется в зависимости от свойств блока:

Тип данных Одиночная запись Групповая запись
Логический 5 15
Числовой 6 16

Тип функции Запись станд. регистров является служебным и используется только в спец. проектах. Тип функции Одиночная запись действует только в том случае, когда количество входов блока равно 1 и разрядность записываемого значения не превышает разрядности 1 регистра (2 байтов). Иначе используется групповая запись. Порядок адресов определяется так же, как в блоке чтения.

Блок Запись переменных

Описание: Блок выполняет команду записи, полностью аналогично блоку Запись (slave). Отличие заключается в том, что для удобства использования состав записываемых величин (входов) и их свойства определяются автоматически, исходя из имеющейся в проекте программы подчиненного устройства. Это автоматическое определение выполняется так:

  • в свойстве блока Программа подчиненного указывается ссылка на FBD-программу подчиненного устройства.
  • в свойстве блока Начальная переменная указывается ссылка на переменную подчиненного устройства, начиная с которой будет выполняться запись.
  • в свойстве блока Кол-во переменных указывается количество переменных в команде.

После изменения свойств блока или после изменения программы подчиненного устройства нужно обновить блок, чтобы входы блока автоматически настроились. Блок будет выполнять запись указанного количества переменных, расположенных последовательно по адресам, непосредственно после начальной переменной. Если таких переменных нет, или нет указанного количества, количество входов блока будет меньше указанного в свойстве Кол-во переменных. Названия входов, вместо valX, будут соответствовать названиям переменных подчиненного устройства.

Вход reg, в отличие от блока Запись (slave), не требуется подключать. Если он не подключен, используется неизменное значение адреса начальной переменной. Поэтому подключать константу ко входу reg не имеет смысла. Подключение входа reg рекомендуется использовать для динамического переключения между одинаковыми по структуре группами переменных.