Category Archives: CoDeSys. Теория.

Задачи и контроль времени выполнения в CoDeSys

Слово ‘задача’ в CoDeSys служит исключительно для организации планирования вычислительного процесса. На практике мы имеем дело с задачами только в ‘Конфигураторе задач’. Здесь мы создаем задачи, назначаем им имена и настраиваем их параметры. Для выполнения полезной работы с каждой задачей связывается как минимум одна программа (POU типа PROGRAM). Когда мы создаем новый проект в CoDeSys, то в нем неявно организуется одна задача, содержащая вызов одной программы PLC_PRG.

Данная задача всегда выполняется циклически. В зависимости от типа ПЛК могут быть два способа ее вызова. Обычно она запускается так часто как это только можно. Как только программа отрабатывает один цикл вызова, система исполнения выполняет обслуживание входов/выходов и снова запускает прикладную задачу. Очевидно, период вызова такой задачи не стабилен и может плавать в зависимости от того, по какой ветви работает программа в данный момент. Обслуживание системой исполнения аппаратных устройств, коммуникационных каналов, работа отладчика также могут влиять на периодичность такой задачи. В окне ‘Конфигурация ПЛК’ задача такого типа называется ‘свободная’ (freewheeling). Второй способ состоит в поддержке стабильного интервала выполнения единственной задачи. Даже если программа пуста, то она не будет вызываться чаще, чем задано. В окне ‘Конфигурация ПЛК’ такая задача называется ‘циклическая’.

Например, в ПЛК-150 компании Овен по умолчанию единственная задача вызывается циклически с интервалом 1 мс. Время рабочего цикла можно изменять от 0 до 50 мс (параметр MinCycleLength в конфигурации ПЛК). При задании нулевого времени контроль отключается и задача превращается в ‘свободную’. Такой встроенный механизм настройки ПЛК достаточно удобен для начинающих пользователей.

Для любых типов ПЛК мы можем открыть в CoDeSys диалоговое окно ‘Конфигурация ПЛК’, создать новую задачу и настроить ее параметры так, как нам нужно. Обратите внимание на то, что если мы беремся за самостоятельное определение задач в CoDeSys и создаем в конфигураторе хотя бы одну задачу, то действовавший по умолчанию вызов PLC_PRG отключается. Нам нужно будет вручную добавить вызов этой программы в одну из задач, даже если она всего одна. См. рис. 1.

Рис 1. Настройка циклической задачи с вызовом программы PLC_PRG

 

При задании интервала циклической задачи нужно быть реалистом и не задавать физически недостижимых величин. Так, если используемая вами модель ПЛК имеет системный таймер, который ‘тикает’ раз в 10 мс, то установка интервала не кратного 10 мс не имеет смысла. Если в конфигурации ПЛК Овен вы задали время рабочего цикла 50мс, то чтобы вы не задали в конфигураторе задач, никакая задача не будет вызываться чаще.

При малых значениях интервала задачи весьма вероятно написать программу с настолько большим числом вычислений в одном цикле ее вызова, что она не будет ‘помещаться’ в заданный интервал. При этом интервал вызова программы будет нестабилен, что может быть нежелательно. Но как это проверить при отладке?

В ПЛК компании Овен для этой цели реализован встроенный механизм контроля времени рабочего цикла. В конфигурацию ПЛК необходимо добавить модуль статистики, который включает вход Cycle time. Здесь вы получите число, содержащее измеренное время цикла в сотнях миллисекунд.

Рис 2. Измерение длительности цикла в ПЛК 150 Овен

 

Универсальным способом измерения коротких интервалов является использование точного таймера из системной библиотеки SysLibTime.lib. Библиотека содержит функциональный блок CurTime, который дает время системного таймера в микросекундах. Естественно, практически нельзя рассчитывать, что системный таймер любого ПЛК ‘тикает’ каждую микросекунду. Поэтому прежде чем полагаться на результаты этого способа измерения, уточните частоту его работы. Данная библиотека является не обязательной и может неподдерживаться для определенных типов ПЛК. На рисунке 2 показан результат прогона на ПЛК-150 Овен простой программы, которая измеряет интервал своего вызова в мкс, при установленном рабочем цикле 10мс. Для контроля приведены результаты измерений с использованием модуля статистики. С учетом дискретности таймера 100мкс мы получаем одинаковые результаты для обоих способов измерения.

Диалоговое окно ‘Конфигурация задач’ CoDeSys имеет свой встроенный диагностический инструмент. Для его работы необходимо включить в проект библиотеки SysLibTime и SysTaskInfo. Учтите что, они поддержаны не для всех типов ПЛК. На рисунке 3 показана информация о работе одной циклической задачи (5 мс), включающей программу, выполняющую сто тысяч операций с переменной типа REAL в CoDeSys SP RTE. На диаграмме видна заданная длительность цикла (светлая полоса) и реальное время вычислений. Оно занимает до 3.3 мс. Очевидно, что для данной задачи задавать интервал менее 4мс нет смысла.

Рис 3. Конфигурация ПЛК в режиме онлайн.

 

Далеко не в каждом ПЛК удается напрямую измерить длительность выполнения программы. Часто она меньше или сравнима с дискретностью системного таймера.

Конфигурирование ведомого CANopen-устройства (CANopen Slave)

ПЛК, программируемый с помощью CoDeSys, можно использовать как CANopen Slave-устройство в сети. В дальнейшем будем называть CANopen Slave как CanDevice.

Для этого необходимо определить ПЛК конфигурацию и сохранить ее в EDS-файле. Такой EDS-файл можно в дальнейшем использовать при определении конфигурации CANopen мастера.

Требования для создания CanDevice:

1. Библиотеки

a. 3S_CanDrv.lib

b. 3S_CanOpenManeger.lib

c. 3S_CanOpenDevice.lib

должны быть включены в проект. Они необходимы для того, чтобы ПЛК мог работать как устройство CAN.

2. В конфигурационном файле с расширением *.cfg, который описывает конфигурацию ПЛК, должны быть сделаны соответствующие настройки. Только в этом случае в PLC Configuration появится дополнительный подэлемент “CanDevice”. Этот объект настраивается в дополнительном диалоге с 3 вкладками: Base settings, CAN settings, Default PDO mapping.

Базовые настройки CanDevice

Диалог Base settings

Bus identifier: пока не используется

Name of updatetask: название задачи, из которой будет вызываться CanDevice. В выпадающем списке вы можете выбрать необходимую задачу.

EDS file generation: включите эту опцию, если хотите чтобы текущие настройки были сохранены в EDS-файле, который потом можно использовать для настройки любого CAN-устройства. В поле Name of EDS file введите имя и путь к файлу. Вы можете вручную создать шаблон для EDS и указать к нему путь в поле Template of EDS file. Например, создайте текстовый файл, содержащий элементы EDS- файла, сохраните его как EDS_template.txt и укажите к нему путь в поле Template of EDS file. Теперь, если вы создаете EDS-файл “device_xy.eds” для текущего проекта, то настройки, сделанные в проекте, будут объединены с настройками из шаблона и сохранены в файле “device_xy.eds” (расширение шаблона не должно быть “.eds”). Если настройки текущего проекта уже определены в шаблоне, то они не будут перезаписаны.

Для указания пути к файлам используйте стандартный диалог, который открывается при нажатии кнопки Browse…

CAN-параметры CanDevice

Диалог CAN settings

В этом диалоге вы можете определить Node id и Baud rate. Node id – это идентификатор узла, который используется для адресации к устройству по сети CANopen.

Так же можно настроить Nodeguarding и Emergency Telegram (описание этих механизмов приведено выше). Heartbeat не поддерживается.

Стандартное PDO отображение для CanDevice

Диалог Default PDO mapping

В этом диалоге элементы локального Менеджера параметров могут быть сопоставлены с PDO, которые отправляются и принимаются этим CanDevice. Полученное PDO-отображение будет доступно в любом конфигураторе, в который CanDevice интегрируется. Параметры, описанные в Менеджере параметров, присоединяются к переменным проекта с помощью системы индексов/подиндексов.

List of mappable objects: Здесь вы можете выбрать список параметров, элементы которого будут отображаться в PDO данного CanDevice. В зависимости от целевой платформы, можно создать список параметров типа “Mapping”, который специально предназначен для отображения в PDO CanDevice. В этом случае для настройки отображения PDO будет доступен только этот список параметров. В противном случае будут доступны все списки параметров типа “Variables” и “Instance”.

Элементы выбранного списка появляются в списке Objects. В списке PDO’s настраивается конфигурация PDO. Добавить в список принимаемые и передаваемые PDO можно с помощью кнопок Insert receive PDO и Insert send PDO. Для того чтобы отобразить объект в PDO, выберите объект в левом окне, PDO в правом и нажмите кнопку >>. Параметры PDO настраиваются с помощью диалога, который появляется при нажатии кнопки Properties.

С помощью кнопки Delete выбранное PDO можно удалить из списка.

Пример:

Цель: В первое принимаемое PDO(COB-Id = 512+NodeId) нужно отобразить переменную PLC_PRG.a Для этого в менеджере параметров нужно создать параметр с определенным индексом/подиндексом и связать его с переменной PLC_PRG.a. Менеджер параметров подключается на вкладке “Network functionality” в настройках целевой платформы. Там же определятся диапазоны индексов и подиндексов.

Теперь в диалоге “Default PDO-Mapping” можно отобразить этот параметр в принимаемое PDO.

Конфигурирование CANopen-модулей в CoDesys 2.3 (часть1)

CoDeSys поддерживает настройку оборудования в соответствии со спецификацией CANopen Draft Standart 301. Конфигурирование контроллера производиться практически так же, как описано выше для обычного аппаратно-зависимого конфигурирования ПЛК.

Все файлы электронной спецификации EDS (Electronic Data Sheet) и DCF (Device Configuration File), которые находятся в директории конфигурационных файлов (обычно PLCCONF), интегрируются в CoDeSys. Их содержание можно просмотреть и изменить с помощью ПЛК конфигурации. В EDS описываются параметры CAN-модуля, которые можно настраивать. Если вы добавите модуль, описанный с помощью DCF, можно будет настраивать только МЭК-адреса, а все остальные параметры модуля будут зафиксированы.

Модули CAN настраиваются удаленно с помощью обмена сетевыми сообщениями. Необходимые значения параметров задаются в диалоге ‘CAN параметры’ (CAN Parameters). Затем прием и передача данных модулей происходит через PDO (Process Data Objects), что определяется в диалогах ‘Отобр. принимаемый PDO’ (Receive PDO) и ‘Отобр. перед. PDO’ (Send PDO-Mapping). Значения доступных SDO (Service Data Objects) задаются в диалоге Service Data Objects. Дополнительные параметры CAN модулей, определенные в файлах описания устройств, настраиваются в диалоге ‘Параметры модуля’ (Module parameters). Если программируемый в CoDeSys контрроллер должен быть включен в сеть CANopen как ведомый (“CAN device”), то он настраивается с помощью конфигуратора ПЛК. Его конфигурация записывается в EDS-файл, который может затем может быть использован с любым CANopen мастером.

Ниже описан процесс конфигурирования устройств CANopen.

Базовые параметры CAN-мастера

Настройка таких параметров, как Идент. модуля (Module-Id), Адреса входов/выходов (input/output addresses), Адрес диагностики (Diagnostic address), описана в разделе 0.

Параметры сети CAN можно настраивать сразу после добавления модуля либо после вызова команды “Дополнения” “Свойства” (“Extras” “Properties”).

CAN-параметры CAN-мастера

Выберите скорость передачи данных из списка ‘Скорость’ (Baud rate).

PDO (Process Data Object) может передаваться в синхронном и асинхронном режимах. Синхронизирующее сообщение, имеющее уникальный идентификатор ‘Синхр. COB-ID’ (Sync. COB-ID) (Communication Object Identifier), передается с периодом, указанным в поле ‘Общее время цикла’ (Communication Cycle Period). Для передачи PDO выделяется временной интервал ‘Ширина окна синхронизации’ (Sync. Window Length) сразу после передачи синхронизирующего сообщения. Величина этого интервала указывается в микросекундах. Синхронизирующее сообщение не посылается, если ‘Общее время цикла’ (Communication Cycle Period) и ‘Ширина окна визуализации’ (Sync. Window Length) равны 0. Флажок ‘Активация’ (activate): разрешает передачу синхронизирующего сообщения.

‘Идент. узла’ (Node-Id): уникальный идентификатор CAN-устройства (узла). Принимает значения от 1 до 127. Это значение должно быть уникальным для каждого устройства в сети и задается в десятичном виде. (Не путайте поля Node-Id и Node number.)

Сеть CAN будет автоматически инициализироваться и включаться в работу сразу после загрузки программы, если активна опция ‘Автостарт’ (Automatic startup). Если эта опция не активна, то сеть нужно запускать непосредственно из программы.

Если активна опция ‘Поддержка DSP301, V3.01 и DSP306’ (Support DSP301, V3.01 and DSP306), то будут поддерживаться модульные CAN-Slave устройства, а также еще некоторые возможности, описанные в стандарте DSP301, V3.01 и DSP306, в том числе и сердцебиение. В этом случае CAN устройство будет передавать специальные сообщения, сообщающие о том, что оно работает, с периодом, указанном в поле ‘Сердцебиение’ (Heartbeat Master[ms]). Такой механизм называется сердцебиение (Heartbeat) и является альтернативой механизма Защита узла (Node guarding), но отличается тем, что может работать как на Master, так и на Slave-устройствах. Обычно этот механизм запускается на CAN-мастере.

Параметры модуля CAN-мастера

Диалог настройки параметров модуля CAN мастера такой же, как и для других модулей (см. 0). Дополнительные параметры CAN-мастера, описанные в конфигурационном файле, также доступны пользователю, и их можно редактировать.

Базовые CAN параметры

МЭК-адреса для обращения к PDO из проекта, вводятся в полях ‘Адрес выходов’ (output address) и ‘Адрес входов’ (input address) в зависимости от направления передачи данных, которая осуществляется PDO. В поле ‘Адрес диагностики’ (diagnostic address) нужно ввести МЭК-адрес маркированной памяти (M). По этому адресу будет размещена диагностическая информация о модуле.

CAN-параметры CAN-модуля

Диалог CAN параметров CAN-модуля

Раздел General ID узла (Node-Id): идентификатор CAN-устройства (узла). Принимает значения от 1 до 127. Это значение должно быть уникальным для каждого устройства в сети и задается в десятичном виде. Если активна опция ‘Записать DCF’ (Write DCF), то при компиляции проекта создается файл с расширением DCF, имя которого состоит из имени соответствующего EDS файла и идентификатора узла, для которого создавался этот файл. Если активна опция ‘Создавать все SDO’ (Create All SDO’s), то SDO создаются для всех объектов, а не только для тех, которые изменены. Если активна опция ‘Сброс узла’ (Reset node) (ее наличие зависит от содержимого файла описания устройства), то ведомое устройство сбрасывается перед загрузкой конфигурации. Опция ‘Опц. устройство’ (Optional device) (ее наличие зависит от специфики целевой платформы) приводит к тому, что мастер будет выполнять только одну попытку чтения из данного узла. Отсутствие ответа игнорируется, то есть мастер продолжит нормальное функционирование. Опция ‘Без иниц.’ (No initialization) указывает мастеру немедленно активировать данный узел без посылки конфигурационного SDO. (Данные SDO будут созданы и сохранены в контроллере в любом случае.) Если поддерживается целевой системой, то создание SDO может быть ограничено по трем уровням. Это может потребоваться при недостаточной памяти:

  • CreateCommSDOs: SDO коммуникационных параметров
  • CreateMappingSDOs: конфигурационные SDO
  • CreateBasicSDOs: SDO базовых параметров (Nodeguarding, Sync и др.)

Будут создаваться только SDO разрешенного типа. Вышеописанная опция ‘Создавать все SDO’ (Create All SDO’s) влияет только на активированные здесь типы. Раздел охрана узла (Node guard альтернатива механизму Сердцебиение — Heartbeat). Если активна опция ‘Защита узла’ (NodeGuarding), то модулю посылается сообщение с периодом (Guard Time) (указывается в миллисекундах). В ответ модуль должен послать сообщение с идентификатором “Защитный COB-ID” (Guard COB-ID) (Communication Object Identifier). Если этого не происходит, то он получает статус “timeout”. Если модуль не отвечает на ‘Фактор работоспособности’ (Life Time Factor) сообщений, то он получает статус “not OK”. Статус модуля можно определить, обратившись по диагностическому адресу. Контроль состояния модуля не производится, если переменные ‘Период’ (Guard Time) и ‘Фактор работоспособности’ (Life Time Factor) равны 0.

Раздел сердцебиение (Heartbeat Settings альтернатива механизму Защита узла — Node

guarding): если опция ‘Активировать генерацию сердцебиения’ (Activate Heartbeat generation) активна, то модуль посылает специальные сообщения сердцебиения с периодом ‘Время потребителя’ (Heartbeat Consumer Time) (указывается в миллисекундах). Если активна опция ‘Активация потребителя’ (Activate Heartbeat Consumer), то модуль слушает сообщения сердцебиения, посылаемые мастером. Если эти сообщения до него не доходят, то модуль выключает свои входы/выходы.

Язык ST для C программиста (часть 2)

WHILE и REPEAT

Цикл WHILE совершенно аналогичен циклу while в C. REPEAT UNTIL соответствует do while. Тонкое, отличие состоит в том, что REPEAT выполнятся до тех пор, пока условие не примет значение TRUE.

FOR

Цикл FOR применяется для выполнения группы выражений заранее известное число раз. Цикл включает установку начального значения, конечное значение, опционально шаг (по умолчанию 1) и тело цикла. Пример:

FOR I := 1 TO 100 BY 10 DO x := x*y; END_FOR

На С этому соответствует:

for (I = 1; I <= 100; I += 10) x = x*y;

Бесконечный цикл в ST обычно записывается как WHILE TRUE DO.

Оператору break в циклах ST соответствует оператор EXIT. Оператор continue в CoDeSys V2.3 отсутствует.

main и PLC_PRG

Прекращение выполнения и возврат управления операционной системе был бы для контроллерной программы полным крахом. Поэтому любая контроллерная программа имеет цикл:

while(1)

{ReadInputs();

PLC_PRG();

WriteOutputs();

}

На самом деле в CoDeSys мы видим только PLC_PRG. Сам главный цикл спрятан в системе исполнения. Это наиболее тонкий момент, который нужно очень четко себе представлять. В многозадачных проектах система исполнения создает независимый главный цикл для каждой задачи. Любая ваша программа выполняется в цикле, если вы не предприняли специальных мер. Принимайте это как факт. Сложности в этом нет, устойчивые навыки приобретаются за несколько часов.

Многозадачность.

Многозадачность в CoDeSys доступна даже для ПЛК, выполненных на 8 разрядных микропроцессорах без ОС. В простейшем случае, вместо вызова единственной PLC_PRG, система попеременно подставляет вызовы разных пользовательских программ. Конечно, с учетом их приоритетов и времен циклов выполнения. Так реализуется не вытесняющая многозадачность. В многозадачных проектах необходимо сопоставить программы задачам с помощью менеджера задач в CoDeSys (См. рис. 2). Если этого не сделать, то проект будет однозадачным, с единственной главной функцией PLC_PRG.

Помимо циклических задач в CoDeSys можно создавать задачи, вызываемые по событиям. В контроллерах имеющих ОС, CoDeSys умеет обеспечивать вытесняющую многозадачность. Например, так работает CoDeSys SP RTE [3]. Минимальное время цикла задач и список активирующих событий необходимо уточнить в документации на контроллер.

Рис. 2. Настройка задачи, вызываемой по фронту входной переменной.

Функции

Для возврата значения функции в C используется return(). Часто для подготовки возвращаемого значения приходится объявлять вспомогательную переменную. В МЭК каждая функция имеет неявно объявленную переменную для возврата значения. Ее наименование совпадает с именем функции. То есть int GetX(int x) { … return(x); } на ST будет выглядеть так:

GetX := x; RETURN;

Как и в языке C передавать параметры, при вызове функции, можно перечисляя их в скобках через запятую: GetX(2). Либо путем присваивания значений: GetX(x := 2). Второй способ применяется и для функциональных блоков.

Память для переменных функции выделяется в стеке. Естественно, значения внутренних переменных не сохраняются между вызовами. Объявления локальных static переменных в функциях не предусмотрено. Для функций и функциональных блоков допускается передача параметров по ссылке (VAR_IN_OUT).

Функции МЭК могут иметь переменное число параметров. Типичный пример – это функция MUX, приведенная в таблице 1. Она может работать с переменным числом параметров, причем любого типа. В CoDeSys V2.3 это реализовано только для стандартных функций. Перегрузки стандартных операций нет. Впрочем, этого нет и в языке C.

Типа void в CoDeSys V2.3 нет. Любая функция должна иметь хотя бы один параметр и возвращать значение. Используйте тип BOOL, он обеспечивает минимальные издержки. Как и в С, вызовы функции можно включать в выражения.

Функциональные блоки.

Помимо функции, в МЭК существует понятие функционального блока. По сути, это структура, к которой добавлен управляющий код. При объявлении данных выделяются входные, выходные и внутренние переменные. На основе объявления функционального блока можно объявить один или несколько его экземпляров. Объявление экземпляра приводит к выделению памяти данных, совершенно аналогично созданию переменных типа структура.

Естественно код при этом не увеличивается. В отличие от функции, значения переменных экземпляра функционального блока сохраняются между его вызовами. Это означает, что к переменным экземпляра можно обращаться в любое время, вне зависимости от его вызова.

В объявлении экземпляра можно выполнять дополнительную инициализацию переменных. При трансляции с ST в C, для каждого функционального блока приходится писать функцию инициализации.

Дополнительно CoDeSys V2.3 позволяет добавлять действия в функциональные блоки. Это аналогично методам класса в ООП.

Библиотеки.

CoDeSys поддерживает 2 вида библиотек. Первый вид это внутренние библиотеки. Любой проект можно сохранить как библиотеку. Внутренние библиотеки пишутся и хранятся на языках МЭК. Они компилируются вместе с проектом. Вы можете запретить редактирование и просмотр текстов внутренних библиотек пользователем. Специальный менеджер библиотек позволяет защитить вашу библиотеку лицензией и сделать ее платной. Именно так реализованы библиотеки CANopen и SoftMotion в CoDeSys (язык ST).

Второй тип – это внешние библиотеки. Их код откомпилирован внешними средствами и включен в систему исполнения (например, системные библиотеки) или размещен в obj файлы. Внешние библиотеки могут иметь еще и ‘внутреннюю’ реализацию (на языках МЭК). Это позволяет написать заглушки системных функций, работающие в режиме эмуляции контроллера в среде программирования CoDeSys.

Системные библиотеки.

Указателей на функции в CoDeSys нет. Есть оператор INDEXOF(name), возвращающий внутренний индекс программного компонента (POU). Он используется там, где нужно программно указать POU. Например, это используется в системных библиотеках, выполняющих установку обработчиков аппаратных прерываний, управление задачами и некоторых других.

В CoDeSys можно создать множество задач и программно управлять (разрешать и останавливать) их работой (по событиям или ‘в лоб’ с помощью специальной системной библиотеки). Это является аналогом идеи массива указателей на функции.

Динамическое распределение памяти в МЭК не предусмотрено. В CoDeSys это делается с помощью функций специализированной библиотеки. Аналогично поддерживается работа с файлами, потоками, сокетами TCP/IP, точная синхронизация задач, управление работой контроллера и многое другое. Всего в CoDeSys V2.3 существует 24 системные библиотеки.

На самом деле, в CoDeSys видны лишь интерфейсы системных библиотек. Их код реализован в системе исполнения изготовителем. Он решает, что можно отдавать пользователю и что лучше запретить. В итоге, состав системных библиотек может быть разным для разных типов ПЛК. Общий обзор дан в документе SysLyb_Overview_RU в дистрибутиве CoDeSys. Безусловно, использовать системные библиотеки можно порекомендовать только опытным пользователям.

Обработка ошибок.

CoDeSys имеет специальный набор функции с фиксированными именами, позволяющими организовать обработку критических ошибок (деление на ноль, выход за границы массива, диапазоны значений, ошибочные указатели и др.) в пользовательской программе. Например:

Checkbounds, CheckPointer, CheckRangeSigned, CheckRangeUnsigned, CheckDivByte, CheckDivWord, CheckDivDWord и CheckDivReal и др. Если соответствующая функция отсутствует в проекте, то используется обработчик по умолчанию, имеющийся в системе исполнения.

Средства управления проектом.

Все что входит в рабочий проект, CoDeSys сохраняет в единственном файле. Это достаточно удобно для архивации. В случае аварии питания компьютера, CoDeSys полностью восстанавливает проект. В контроллеры, имеющие достаточный объем памяти, можно загрузить файл проекта вместе с исполняемым кодом.

Средств условной трансляции (#ifdef) в CoDeSys V2.3 нет. Однако есть возможность в менеджере проекта выделить определенные POU и запретить их включение в процесс компиляции. В CoDeSys можно установить дополнительный продукт 3S, так называемый инжиниринговый сервер (ENI). С его помощью реализуется полноценная возможность сетевой многопользовательской работы с проектом и управление версиями программных компонентов пользователей.

Заключение.

По числу типов данных ST превосходит C. Применение стандартных и специализированных операций не вызывает у C программистов ни каких сложностей. Редактор ST в CoDeSys поддерживает синтаксическое цветовое выделение и имеет средства быстрого ввода. Как правило, трансляция C программ в ST проще, чем обратная операция. Может вызвать сложность цикличность вызова главной программы, но это дело привычки. Вы наверняка заметили, что в определенных местах, где речь шла об ограничениях ST в сравнении с C, было написано ‘CoDeSys V2.3’. Все эти моменты доработаны в новой версии CoDeSys V3.0. Безусловно, это радикальный шаг 3S по расширению МЭК. Он сделан под давлением пользователей, являющихся профессиональными программистами. Пожалуй, самое интересное в 3.0 – это оснащение МЭК языков полноценными средствами ООП.

Мой блог находят по следующим фразам

Язык ST для C программиста (часть 1)

Принято считать, что языки программирования ПЛК стандарта МЭК 61131-3 (далее для краткости МЭК) предназначены для применения неспециалистами в области информатики. Но возможности ПЛК растут, соответственно растут и требования, предъявляемые к прикладному программному обеспечению (ПО). Все чаше мы встречаем системы на ПЛК, включающие сложнейший математический аппарат. В ПЛК используют web-технологии, нечеткие регуляторы, многомерные интерполяторы систем управления движением (SoftMotion) и т.д.

Такие технологии требуют специальных знаний. Несмотря на все прогнозы и рассуждения, на сегодняшний день более половины ПО для ПЛК создается профессиональными программистами, имеющими высшее образование. С каждым годом их доля возрастает. Не смотря на это, подавляющее большинство изготовителей МЭК систем упорно продолжают создать простые инструменты «для чайников». Чаще всего это некий редактор FBD и интерпретирующая система исполнения, опирающаяся на вызов заранее откомпилированных модулей. Для расширения состава блоков их пишут на языке C внешними средствами. Если профессиональный программист сталкивается с такой средой, то часто результатом становится МЭК программа, состоящая из одного большого функционального блока, полностью написанного на C.

Стандарт МЭК включает высокоуровневый язык ST, по выразительной мощности не уступающий языкам C и Паскаль. К сожалению, в большинстве систем МЭК программирования он не реализован вовсе либо имеет массу ограничений. Как правило, это ограничение числа поддерживаемых типов данных, упрощенный интерпретирующий транслятор или промежуточный код, ограничения на доступ к аппаратным ресурсам, невозможность обрабатывать прерывания, выполнять динамическое распределение памяти, управлять процессами и др. На самом деле, это не ограничения языка ST. Это именно ограничения среды программирования.

Некоторым особняком в ряду комплексов МЭК стоит CoDeSys производства 3S-Smart Software Solution GmbH. Его уникальность состоит в том, что он изначально задумывался как инструмент для профессионалов. Исходя из собственных соображений, при адаптации CoDeSys для конкретного ПЛК, изготовитель может наложить ряд ограничений на возможности пользователя. Но изначально их нет.

Безусловно, в CoDeSys можно использовать внешние библиотеки, реализованные на C, но необходимость в этом возникает крайне редко. Практически все, что можно написать на C, в CoDeSys можно написать на ST, без изменения методологии проектирования. CoDeSys имеет встроенный компилятор и генераторы машинного кода для всех популярных семейств микропроцессоров. Внешний C компилятор не даст выигрыша по быстродействию, но значительно усложнит разработку.

Очень существенная тонкость стандарта МЭК состоит в том, что он включает только требование однозначности выполнения описанных в нем конструкций. Многие воспринимают это как возможность называть МЭК системой программирования среду, поддерживающую только часть стандарта. Однако справедлив и обратный подход: МЭК система может включать все, что описано в стандарте, плюс дополнительные возможности.

Практика показывает что, профессиональные программисты, работая с CoDeSys, чаше всего выбирают язык ST. Практически все они в совершенстве владеют языком C. Данная статья имеет целью быстро очертить C программистам границы возможностей языка ST в CoDeSys и подсказать типовые методы преодоления затруднений.

Типы данных.

В CoDeSys реализованы все стандартные типы данных МЭК 61131-3. Все типы данных доступны во всех 6 поддерживаемых языках. Специальных расширений для ST нет. Целочисленные типы таковы: SINT (char), USINT (unsigned char), INT (short int), UINT (unsigned int), DINT (long), UDINT (unsigned long), LINT (64 бит целое), ULINT (64 бит целое без знака).

Действительные типы: REAL (float), LREAL (double).

Специальные типы BYTE, WORD, DWORD, LWORD представляют собой битовые строки длиной 8, 16, 32 и 64 бит соответственно. Битовых полей в ST нет. К битовым строкам можно непосредственно обращаться побитно. Например: a.3 := 1; (* Установить бит 3 переменной a *). В C в подобных целях используются целые без знака и битовые логические операции. В CoDeSys к битовым стокам можно применять операции, доступные для целых без знака. Логический тип BOOL. Может иметь значение TRUE или FALSE. Физически переменная типа BOOL может соответствовать одному биту. Обычно так и есть, если речь идет о дискретном входе либо выходе ПЛК или прямоадресуемой переменной (см. ниже). В иных случаях CoDeSys выделяет один байт. Это вызвано тем, что большинство микропроцессоров не умеют непосредственно адресоваться к отдельным битам памяти.

Строки STRING. Являются именно строкой, а не массивом. Поэтому (в версии V2.3) нет возможности обращаться к отдельным символам. Зато можно сравнивать и копировать строки стандартными операторами. Например так: strA := strB. В МЭК есть стандартный набор функций для работы со строками. Внутренний формат строк не стандартизован. CoDeSys использует нуль-терминированные строки.

Специальные типы в стандарте МЭК определены для длительности (TIME), времени суток (TOD), календарной даты (DATE) и временного штампа (DT). Работа со временем и интервалами встречается в ПЛК программах повсеместно.

Применение структур (STRUCT) не отличается от C. Описание структуры должно предшествовать объявлению переменной данного типа. Допускаются вложенные структуры и массивы.

Массивы (ARRAY) строятся из элементов любых типов, включая структуры и массивы. Из особенностей нужно отметить возможность задания повтора значений при инициализации. Например: bX ARRAY[0..20] OF BOOL := TRUE, 10(FALSE), 9(TRUE); Значение FALSE повторено здесь 10 раз и значение TRUE, соответственно 9 раз. Массивы (и структуры) можно копировать с помощью обычной операции присваивания: bY := bX; Перечисления аналогичны перечислениям C. Пример: TYPE TEMPO: (Adagio := 1, Andante := 2); END_TYPE.

На базе целых можно построить типы, имеющие ограниченный диапазон значений.

Например: TYPE DAC10: INT (0..16#3FF); END_TYPE.

Для любого типа можно создать псевдоним (typedef в C). Например: TYPE DEGR : UINT

END_TYPE.

Константы.

В МЭК используются типизированные константы. Например: 2#10001000 (целое, байт в двоичном формате), INT#40, t#10h14m5s (время дня), D#2006-01-31 (дата). Формат констант описан в документации и не вызывает сложностей.

Символьные константы можно объявлять локально или глобально в специальной секции раздела объявлений: VAR CONSTANT.

Идентификаторы.

Идентификаторы имен переменных могут иметь любую длину. Ограничения числа значимых символов нет. Идентификаторы не чувствительны к регистру (XZ и Xz одно и тоже). Идентификаторы не должны начинаться с цифры (12x). Двойные подчеркивания запрещены(__X).

Инициализация переменных.

По умолчанию, все переменные инициализируются нулем. Иное значение переменной можно указать явно при ее объявлении. Например: str1: STRING := ‘Hello world’. Переменные можно объявить как RETAIN или PERSISTENT. Это означает требование их размещения в энергонезависимой памяти контроллера (если она есть). Их инициализация производится только при первом запуске программы или по специальной команде.

Прямая адресация.

Помимо общей памяти данных в контроллере предусмотрены 3 специальные области памяти. Это область входов, выходов и прямо-адресуемая область. Эти области служат для связи системы исполнения контроллера и пользовательской программы. В простейших ПЛК распределение памяти в области входов/выходов фиксировано изготовителем. Мы можем непосредственно обращаться к нужному адресу из программы (например, %QB5 дает 5-й байт в области выходов) или объявить переменную, расположенную в соответствующем месте. Как правило, изготовители ПЛК снабжают CoDeSys конфигурационными файлами. Встроенный графический конфигуратор позволяет настроить и автоматически объявить переменные для всех входов/выходов и диагностических переменных без программирования, включая распределенные модульные системы (См. рис. 1).

Рис. 1. Конфигурирование переменных входов/выходов в CoDeSys

Преобразование типов.

Неявное преобразование типов запрещено. Любое преобразование нужно делать явно с помощью специальных операторов. Запомнить их легко. Пишем исходный тип, далее _TO_ и нужный тип. Например: iX := REAL_TO_INT(rX); .

Операторы и функции.

Наиболее часто используемые операторы и функции ST приведены в таблице 1. В МЭК определен целый ряд общепринятых и специализированных (для ПЛК программ) функций и функциональных блоков. В их числе таймеры, триггеры, счетчики, регуляторы и многое другое.

Написать ++x; или x += 1; в ST, конечно, нельзя. Единственный вариант – это x := x + 1;. Полное описание стандартных операций, функций и функциональных блоков вы найдете в руководстве программиста CoDeSys.

Sizeof В CoDeSys имеется оператор SIZEOF(in). Смысл его должен быть очевиден для C

программистов.

Sprintf Такого оператора в ST нет. Преобразовать любой переменную любого типа в строку можно с помощью …_TO_STRING.

Указатели.

В МЭК указателей нет, в CoDeSys они есть. Адрес переменной можно получить с помощью оператора ADR, разыменовывание дает ‘^’. Например:

pt : POINTER TO INT;

var_int1:INT;

var_int2:INT;

pt := ADR(var_int1);

var_int2 := pt^;

Объединений в CoDeSys V2.3 нет. При необходимости это удается обойти, разместив несколько переменных разного типа по одному адресу в прямо адресуемой памяти либо посредством указателей. Аналогично можно получить доступ к элементам строки ‘совместив’ ее с массивом.

Точка с запятой.

Не смотря на явное родство ST с языком Паскаль, точка с запятой используется в нем также как в языке C. То есть она служит не разделителем, а признаком конца оператора. Естественно, в одной строке может быть любое число операторов. Кроме того, точка с запятой служит пустым оператором. Текст любого программного компонента (POU) на ST должен включать хотя бы один оператор.

Программные скобки.

В ST нет привычных программных скобок ({} в C или begin и end в Паскале). Вместо этого каждая программная конструкция имеет собственную закрывающую программную скобку. Например: END_FUNCTION или END_IF. Каждому кто имел ‘счастье’ видеть многоэтажные лесенки завершающих скобок в C, такое решение должно быть понятно. Некоторая многословность текста компенсируется средствами быстрого ввода CoDeSys.

IF ELSE

Оператор выбора IF почти эквивалентен соответствующему оператору в C. Условием может служить переменная или выражение только логического типа. В ином случае, необходимо выполнить явное приведение к логическому типу.

Дополнительно в IF можно вложить последовательную цепочку условий ELSIF. Это достаточно удобно при анализе сложных разветвляющихся условий.

CASE

Аналогичен switch в C. Альтернативные ветки не имеют закрывающей программной скобки и не могут выполняться одна за другой. Соответственно оператор break не имеет смысла и отсутствует. При указании значений констант альтернативы можно перечислить их через запятую или указать диапазон. Например:

CASE (x + 2)/3 OF

0:

y := 1;

1,2:

y := 4;

z := 5;

3..50:

y := 7

ELSE

y := 0;

END_CASE

 

Мой блог находят по следующим фразам

Неявные переменные визуализации CodeSys

В программе доступны следующие системные переменные, управляющие визуализацией:

CurrentVisu String[40] Имя текущей визуализации. Если имя изменяется, то проводится изменение визуализации. Строку имени визуализации следует всегда вводить прописными буквами.

В зависимости от целевой системы использование этой переменной может активироваться / деактивироваться в настройках целевых систем.

CurrentCaller String[40] Содержит имя предыдущей визуализации (для ZOOMTOCALLER). Устанавивается и изменяется только в целевой визуализации.

CurrentLanguage String[40] Текущий выбранный язык, заданный в языковом файле. Его нужно указывать прописными буквами. Устанавивается и изменяется только в целевой визуализации.

CurrentUser-Level INT Группа пользователя 0.. 7. Значение должно изменяться только в соответствующем диалоге CoDeSys.

CurrentPasswords[0 .. 7] ARRAY [0..7] OF STRING[20] Пароли, заданные в CoDeSys ‘User Group Passwords…’ . Значение должно изменяться только в соответствующем диалоге CoDeSys.

Неявные переменные CurrentLanguage, CurrentUserLevel и CurrentPasswords[0..7] могут быть объявлены

реманентными для использования их в целевой визуализации. Для этого их необходимо объявить явно в списке глобальных переменных. Они должны быть объявлены в самом верхнем списке папки ‘Global Variables’ на вкладке Resources. При размещении объявлений в ином списке, компилятор даст сообщение об ошибке.

Переменные CurrentUserLevel, CurrentPasswords[…] нужно объявлять в одном разделе (normal, RETAIN, PERSISTENT…)! Если они объявлены реманентными, то нужно объявить дополнительно глобальную переменную «VisuDoExecuteUserlevelInit» типа BOOL RETAIN, инициализировав ее TRUE («VisuDoExecuteUserlevelInit : BOOL := TRUE;»).

Мой блог находят по следующим фразам

Пример Dll для ActiveX Control

Ниже приведен исходный текст примера Dll, использующийся для вызова методов ActiveX элемента в визуализации CoDeSys.

В данном примере dll будет вызывать методы GoBack или GoForward, только если элемент поддерживает интерфейс IWebBrowser.

Метод выбирается параметром pszId.

#include «stdafx.h»

#include <unknwn.h>

#include <exdisp.h>

BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call,

LPVOID lpReserved)

{

return TRUE;

}

extern «C» __declspec (dllexport) void ExecuteActiveXCall(IUnknown* pUnk,

char* pszId, char* pszParam, char* pszReturnBuffer, int nReturnBufferSize,

DWORD* pdwReturnFlag)

{

if (strcmp(pszId, «IWebBrowser|GoBack») == 0)

{

IUnknown* pNewUnk;

IWebBrowser* pwb;

pUnk->QueryInterface(IID_IWebBrowser, (void**) &pNewUnk);

pwb = (IWebBrowser*) pNewUnk;

if (pwb)

{

pwb->GoBack();

pwb->Release();

}

}

else if (strcmp(pszId, «IWebBrowser|GoForward») == 0)

{

IUnknown* pNewUnk;

IWebBrowser* pwb;

pUnk->QueryInterface(IID_IWebBrowser, (void**) &pNewUnk);

pwb = (IWebBrowser*) pNewUnk;

if (pwb)

{

pwb->GoForward();

pwb->Release();

}

Мой блог находят по следующим фразам

Настройка OPC-сервера для работы по протоколу Modbus TCP в режиме Master

Компьютер, на котором установлен «Lectus Modbus OPC/DDE сервер версии 3.8», должен иметь возможность подключения к сети Интернет через один из возможных каналов связи (например, через сеть Ethernet, dialup-модем, ADSL-модем и др.), для определенности будем считать, что компьютер подключен к сети Интернет через Ethernet. Установить соединение с сетью Интернет, средствами Windows.

Для работы LectusOPC по протоколу Modbus TCP, необходимо:

1. Запустить LectusOPC, удалить ранее созданные узлы, после чего сохранить проект под новым именем — тем самым создать новый проект.

2. Добавить к текущим данным новый Modbus-узел (Рис.1.).

Рис.1 Добавление нового узла в LectusOPC

3. В появившемся окне задать параметры modbus-узла (Рис.2). Описание параметров смотрите в справке LectusOPC.

Рис.2 Настройка Modbus узла по TCP/IP.

4. Не закрывая окно «Добавить узел», нажать на кнопку «Настройка..», где указать IP-адрес (Рис.3).

Рис.3 Настройка TCP/IP

 

5. После добавления узла, добавить переменные в Modbus-узел (Рис.4).

Рис.4 Добавление переменной в OPC

6. В появившемся окне задать параметры переменной (Рис.5). Описание параметров смотрите в справке LectusOPC.

Рис.5 Задания адреса переменной

7. После создания узла и добавления в него переменных сохраните проект и запустите встроенный клиент LectusOPC, нажав на кнопку «Запустить опрос». Появится узел, где будут отображены значения переданных из контроллера переменных (Рис.6).

Рис.6 Запуск OPC

8. Впоследствии, именно к этому узлу можно будет подключиться OPC-клиентом (например, SCADA-системой).

9. Через некоторое время OPC-сервер соединиться с ПЛК100 и начнется обмен Modbus-пакетами, для контроля над этим процессом необходимо перейти на вкладку «Лог» (рис.7).

Рис.7 Обмен посылками по ModbusTCP, лог LectusOPC

На вкладке «Лог» видно, как был запущен OPC-сервер, затем произошло соединение с IP-адресом 83.220.242.28 по порту 502 (протокол TCP) и начался обмен Modbus-пакетами. OPC-сервер считывает переменную с ПЛК100, ее значение равно 100dec (64hex).

 

Мой блог находят по следующим фразам

Сетевые переменные в CoDeSys.

Данная операция имеет смысл, когда у Вас на одном объекте стоит несколько контроллеров, и необходимо обмениваться данными между этими контроллерами без создания дополнительного межсетевого обмена.

Необходимо помнить, что данная опция необходима, когда у нас на одном объекте как минимум 2 контроллера.

Обмен переменными может вестись только по интерфейсу Ethernet. (На данном этапе).

Пример создан на базе контроллера ПЛК150-220.И-L

Target 2-02.3

Переходим на вкладку Resources

Выбираем папку «Target settings», вкладку «Network functionality»

В строчке «Name of supported network interfaces» задаем в ручную – UDP

Во вкладке Resources выбираем вкладку «Library Manager» и добавляем библиотеку (правой кнопкой мыши в поле библиотек) – Additional Library.

Необходимо подключить следующие библиотеки:

SysLibCallback.lib

SysLibSockets.lib

NetVarUdp_LIB_V23.lib

Библиотеки вложены в архиве, либо на диске с ПЛК, либо на сайте ОВЕН.

Рекомендуется перед подключением перенести библиотеки в директорию, созданную CoDeSys, по умолчанию: c:Program Files3S SoftwareCoDeSys V2.3Library

Выбираем папку «Global variables»

Выбираем команду Add Object

Всплывает следующее окно.

В строчке «Name of the global list» задаем имя, например PRIMER.

!Важно:

  1. В обоих (нескольких) контроллерах имя данной папки должно быть идентичным.
  2. Регистр (большие или маленькие буквы) важен.

Далее в этом окне нажимаем на кнопку «Add network» — окно видоизменяется следующим образом:

Значение параметра «Network type» — необходимо выставить UDP. Вкладку Settings не редактируем.

Значение параметра  «List identifier (COB-ID)» так же должно быть общим для всех контроллеров, участвующих в обмене. Значение выставляется произвольно. Для примера – 1.

Далее ставим галочку у необходимого параметра.

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

Если выбраны Write – становятся доступными три последующие строчки, которые описывают по какому принципу необходимо передавать значение: «Циклически», «по изменению значения», «по команде».

!Важно: Рекомендуется не ставить галочки чтение и запись для одной и той же группы «PRIMER» в одном контроллере. То есть только в одном контроллере переменные одной папки должны быть Write, в остальных контроллерах типа Read.

Если необходимо, чтобы у каждого контроллера были переменные, которые и опрашиваются, и задаются – необходимо сделать несколько таких папок.

После этого добавляем (объявляем) непосредственно во вновь созданной папке переменные, которые нам необходимы.

И уже в программе работаем с ними, как со стандартными глобальными переменными.

Сложные типы данных CoDeSys

Массивы

Элементарные типы данных могут образовывать одно-, двух-, и трехмерные массивы. Массивы  могут быть объявлены в разделе объявлений POU или в списке глобальных переменных. Путем вложения массивов можно получить многомерные массивы, но не более 9 мерных ( «ARRAY[0..2] OF ARRAY[0..3] OF …» ).

Синтаксис:

<Имя_массива>:ARRAY [<ll1>..<ul1>,<ll2>..<ul2>] OF <базовый тип>.

где ll1, ll2, ll3 указывают нижний предел индексов; ul1, ul2 и ul3 указывают верхние пределы.

Индексы должны быть целого типа. Нельзя использовать отрицательные индексы.

Пример:

Card_game: ARRAY [1..13, 1..4] OF INT;

Пример инициализации простых массивов:

arr1 : ARRAY [1..5] OF INT := 1,2,3,4,5;

arr2 : ARRAY [1..2,3..4] OF INT := 1,3(7); (* сокращение для 1,7,7,7 *)

arr3 : ARRAY [1..2,2..3,3..4] OF INT := 2(0),4(4),2,3;

(* сокращение для 0,0,4,4,4,4,2,3 *)

Пример инициализации массива структур:

TYPE STRUCT1

STRUCT

p1:int;

p2:int;

p3:dword;

END_STRUCT

ARRAY[1..3] OF STRUCT1:= (p1:=1,p2:=10,p3:=4723),(p1:=2,p2:=0,p3:=299),
(p1:=14,p2:=5,p3:=112);

Пример инициализации части массива:

arr1 : ARRAY [1..10] OF INT := 1,2;

Не инициализированные явно элементы массива принимают значения по умолчанию. Так, в данном примере оставшиеся элементы примут значение 0.

Доступ к элементам массива:

Для доступа к элементам двухмерного массива используется следующий синтаксис:

<Имя_массива>[Индекс1,Индекс2]

Пример:

Card_game [9,2]

Функция CheckBounds

Определив в проекте функцию с именем CheckBounds, вы сможете использовать её для контроля за соблюдением границ индексов массивов. Имя функции фиксировано, изменять его нельзя.

Пример функции CheckBounds:

FUNCTION CheckBounds : INT
VAR_INPUT
index, lower, upper: INT;
END_VAR

IF  index < lower THEN
CheckBounds := lower;
ELSIF  index > upper THEN
CheckBounds := upper;
ELSE  CheckBounds := index;
END_IF

В этом примере CheckBounds ограничивает индекс массива заданными границами. Если запрашивается элемент, отсутствующий в массиве, функция  CheckBounds возвращает ближайший элемент.

Проверка работы функции CheckBounds:

PROGRAM PLC_PRG
VAR
a: ARRAY[0..7] OF BOOL;
b: INT:=10;
END_VAR

a[b]:=TRUE;

Указатели

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

Синтаксис:

<Имя_указателя>: POINTER TO <Тип данных/Функциональный блок>;

Указатели применимы для всех базовых типов данных или функциональных блоков, включая  определяемые пользователем.

Адреса переменных и функциональных блоков можно получить во время исполнения программы при помощи оператора ADR. Для обращения через указатель необходимо добавить оператор «^»  (content) после его имени.

Обратите внимание: Указатели инкрементируются побайтно! Для увеличения указателя, как это принято в C-компиляторах, используйте инструкцию p=p+SIZEOF(p^);.

Пример:

pt:POINTER TO INT;

var_int1:INT := 5;

var_int2:INT;

pt := ADR(var_int1);

var_int2:= pt^;  (* var_int2 теперь равна 5 *)

Функция CheckPointer:

Данная функция позволяет контролировать обращение к допустимой области памяти через указатели. Если определена функция CheckPointer, то она будет автоматически вызываться при любом обращении через указатель. Функция должна быть определена в проекте (непосредственно или в библиотеке). Ее имя (CheckPointer) изменять нельзя.  Функция имеет следующие параметры:

Для систем с 32-х битными указателями:

FUNCTION CheckPointer : DWORD

VAR_INPUT

dwAddress : DWORD;

iSize : INT;

bWrite: BOOL;

END_VAR

Для систем с 16-и битными указателями:

FUNCTION CheckPointer : WORD

VAR_INPUT

dwAddress : WORD;

iSize : INT;

bWrite: BOOL;

END_VAR

Функция возвращает адрес, который будет использоваться как указатель. Если все хорошо то, это будет входной параметр — dwAddress.

Перечисление

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

Перечисление доступно в любой части проекта, даже при локальном его объявлении внутри POU. Поэтому наиболее разумно создавать все перечисления на вкладке Типы данных Организатора Объектов. Объявление должно начинаться с ключевого слова TYPE и заканчиваться строкой END_TYPE.

Синтаксис:

TYPE <Имя_перечисления>:(<Элемент_0> ,< Элемент _1>, …< Элемент _n>);END_TYPE

Переменная типа  <Имя_перечисления> может принимать только перечисленные значения. При инициализации переменная получает первое из списка значение. Если числовые значения элементов перечисления не указаны явно, им присваиваются последовательно возрастающие числа, начиная с 0. Фактически элемент перечисления — это число типа INT и работать с ними можно точно так же. Можно напрямую присвоить число переменной типа перечисление.

Пример:

TYPE TRAFFIC_SIGNAL: (Red, Yellow, Green:=10); (*Каждому цвету

соответствует свое значение, для red — это 0, для yellow — 1 и для green — 10 *)

END_TYPE

TRAFFIC_SIGNAL1 : TRAFFIC_SIGNAL;

TRAFFIC_SIGNAL1:=0; (* Переменная получила значение red*)

FOR i:= Red TO Green DO

i := i + 1;

END_FOR;

Элемент, уже включенный в перечисление, нельзя повторно включать в другое перечисление.

Пример:

TRAFFIC_SIGNAL: (red, yellow, green);

COLOR: (blue, white, red);

Ошибка: попытка повторного использования элемента TRAFFIC_SIGNAL red  в COLOR.

Структуры

Структуры создаются на вкладке Типы данных Организатора Объектов. Объявление должно начинаться с ключевых слов TYPE и STRUCT и заканчиваться строками END_STRUCT и END_TYPE.

Синтаксис:

TYPE <Имя _структуры>:

STRUCT

<Объявление переменной 1>

.

.

<Объявление переменной n>

END_STRUCT

END_TYPE

<Имя _структуры> образует новый тип данных, который может быть использован в любой части проекта наряду с базовыми типами.

Вложенные структуры допускаются. Единственное ограничение заключается в запрете размещения элементов структуры по прямым адресам (AT объявления недопустимы!).

Пример объявления структуры по имени Polygonline:

TYPE Polygonline:

STRUCT

Start:ARRAY [1..2] OF INT;

Point1:ARRAY [1..2] OF INT;

Point2:ARRAY [1..2] OF INT;

Point3:ARRAY [1..2] OF INT;

Point4:ARRAY [1..2] OF INT;

End:ARRAY [1..2] OF INT;

END_STRUCT

END_TYPE

Пример инициализации структуры:

Poly_1:polygonline := ( Start:=3,3, Point1 =5,2, Point2:=7,3, Point3:=8,5, Point4:=5,7, End := 3,5);

Для доступа к элементам структуры используется следующий синтаксис:

<Имя_структуры>.<Имя_компонента>

Например, структура «Week» содержит компонент «Monday», обращение к которому будет выглядеть так:

Week.Monday

Псевдонимы типов

Псевдонимы типов нужны для создания альтернативных пользовательских наименований типов данных. Это удобно при работе с большим числом однотипных констант, переменных и функциональных блоков.

Псевдонимы типов определены на вкладке Типы данных Организатора Объектов. Объявление должно начинаться с ключевого слова TYPE и заканчиваться строкой  END_TYPE.

Синтаксис:

TYPE <Имя псевдонима>: <Исходное имя>;
END_TYPE

Пример:

TYPE message:STRING[50];

END_TYPE;

Ограничение диапазона значений

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

Создание нового типа выглядит так:

TYPE < Имя > : < Целый тип > (<от>..<до>) END_TYPE;

<Имя> любой допустимый МЭК идентификатор,
<IЦелый тип> один из типов SINT, USINT, INT, UINT, DINT, UDINT, BYTE, WORD,DWORD (LINT, ULINT, LWORD).
<от> константа, определяющая начало диапазона значений включительно
<до> константа, определяющая конец диапазона значений включительно.

Пример:

TYPE

SubInt : INT (-4095..4095);

END_TYPE

Ограничение диапазона при объявлении переменной:

i : INT (-4095..4095);

ui : UINT (0..10000);

END_VAR

При попытке присвоить переменной с ограниченным диапазоном константы, не попадающей в заданный диапазон (например i := 5000;) CoDeSys даст сообщение об ошибке.

Для контроля значений «ограниченных» переменных в процессе исполнения, применяются функции CheckRangeSigned или CheckRangeUnsigned. Они позволяют обрабатывать ошибки произвольным образом. Например, ограничить присваиваемое значение или сформировать флаги ошибки. Первая функция работает для переменных со знаком, вторая для переменных без знака (unsigned). Изменять идентификаторы этих функций нельзя.

Пример:

Здесь применяется функция CheckRangeSigned, контролирующая переменные со знаком (как, например, объявленная выше i). Функция «обрезает» присваиваемые значения по границам диапазона.

FUNCTION CheckRangeSigned : DINT

VAR_INPUT

value, lower, upper: DINT;

END_VAR

IF (value < lower) THEN

CheckRangeSigned := lower;

ELSIF(value > upper) THEN

CheckRangeSigned := upper;

ELSE

CheckRangeSigned := value;

END_IF

Функция вызывается автоматически при соответствующих операциях присваивания. Она получает три параметра: присваиваемое значение (value) и обе границы диапазона (lower, upper). Фактически присваивается возвращаемое CheckRangeSigned значение.

Например, при присваивании i:=10*y происходит неявный вызов:

i := CheckRangeSigned(10*y, -4095, 4095);

В результате, даже если y > 1000, i не получит значение более 4095.

Аналогично объявляется и функция CheckRangeUnsigned:

FUNCTION CheckRangeUnsigned : UDINT

VAR_INPUT

value, lower, upper: UDINT;

END_VAR

Важно: Если функции CheckRangeSigned или CheckRangeUnsigned не включены в проект, ограничение границ диапазонов во время исполнения работать не будет.

Внимание: Функции CheckRange…, содержащащиеся в библиотеке Check.Lib представляют собой пример реализации. Прежде чем использовать эту библиотеку, убедитесь, что данные функции работает  так, как нужно в вашем случае, либо создайте собственные функции непосредственно в вашем проекте.

Пример. Переменная ui не превысит 10000, и цикл FOR никогда не закончится:
VAR
ui : UINT (0..10000);
END_VAR

FOR ui:=0 TO 10000 DO

END_FOR