OpenSCADAWiki: Doc/ Programming Environment ...

Home | Index | Changes | Comments | Users | Registration | Login  Password:  
 
English (1 Кб) English
Ukrainian (1 Кб) Українська?

Проект среды программирования системы OpenSCADA.

Автор: Роман Савоченко


Contents

1 Введение

Открытая SCADA система OpenSCADA принадлежит к классу SCADA(Supervisory Control and Data Aquisition) систем. Системы данного класса используются как элемент систем автоматизации технологических процессов(АСУ-ТП).


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


Для организации пользовательских вычислений в среде промышленных контроллеров и SCADA систем используются различные языки программирования. В случае с контроллерами в качестве таких языков чаще всего используются языки низкого уровня (ассемблеры), однако в последнее время всё чаще используются языки высокого уровня (C, Pascal и другие), а также формальные языки (блочные схемы, релейные схемы, логические схемы и другие). В случае с SCADA системами вычисления чаще обеспечиваются языками программирования высокого уровня и формальными языками.


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


Данный проект предназначен для разработки среды программирования системы OpenSCADA.


2 Назначение

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


3 Требования

3.1 Архитектурные требования к среде программирования

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


С такой целью среду программирования архитектурно можно разделить на три части:


Объекты функций должны содержать только структуру параметров функций и алгоритм вычисления. Реальные значения объектам функций должны передаваться в виде кадра значений различными вычислительными контролерам и узлами.


Декларирующие объекты должны содержаться в ядре системы OpenSCADA для предоставления доступа всем компонентам среды программирования.


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


3.2 Общие требования

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


Ядро системы OpenSCADA должно обеспечить:


В рамках проекта нужно реализовать следующие библиотеки функций и вычислительные контролеры:


Модуль(и) статических библиотек функций должны обеспечить:


Модуль вычислителя на языке программирования высокого уровня и модуль библиотек функций на этом языке по совместительству должны обеспечить:


Модуль вычислителя на языке блоков должен обеспечить:


3.3 Требования к разрабатываемому языку программирования высокого уровня

Для реализации модуля вычислителя на языке программирования высокого уровня и модуля библиотек функций на этом же языке нужно использовать грамматику одного из известных языков программирования высокого уровня.
Программа на выбранном языке должна компилироваться в код внутренней виртуальной машины. Главными требованиями к виртуальной машине являются: высокая надёжность и производительность. Для удовлетворения требований высокой надёжности виртуальная машина должна содержать механизмы учёта и ограничения времени обсчёта.


В обязательном порядке нужно реализовать следующие возможности языка программирования:


3.4 Требования к разрабатываемому языку блочного программирования

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

Связи должны поддерживать их "горячую", в процессе вычисления, установку.


4 Проектирование

4.1 Постановка задачи

Любой сложный программный комплекс должен содержать среду программирования. Наличие такой среды значительно расширяет гибкость системы и, как следствие, сферу её применения. Среда программирования, которая используется в таких программных комплексах, может основываться на различных языках программирования. Однако чаще всего используются языки, наделённые высоким уровнем формализма, например, языки блоков (блочные схемы, логичные схемы, релейные схемы и другие). Однако, на уровне с ними часто используются языки высокого уровня типа С и С++ в своей упрощённой реинкарнации: Java и JavaScript. Не в последнюю очередь также используются языки логического вывода: Prolog и Lisp.


Система OpenSCADA разрабатывается как гибкая и высоко-масштабируемая SCADA система, поэтому создание собственной среды программирования является важной задачей. Главной целью создания среды пользовательского программирования является предоставление в систему OpenSCADA гибкого и мощного механизма программирования.


Кроме того, среда программирования предназначена для предоставления возможности создания:


4.2 Объект функции, как ключевой элемент среды программирования

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


То есть, имеем элементарный модуль рис.1.


Функция (3 Кб)
Рис. 1. Функция

Где:

X – множество входов;
Y – множество выходов;
A – алгоритм обработки входов.

Как видно, такой модуль не содержит состояний, потому как не хранит значений ни входов ни выходов. Добавление состояния, как текущий контекст, модуль получает в так называемых вычислителях. Такая схема позволяет один модуль функции использовать в разных модулях вычислителей (рис. 2).


Основа среды программирования системы OpenSCADA (71 Кб)
Рис. 2. Основа среды программирования системы OpenSCADA

4.3 Выбор языка высокого уровня для реализации вычислителя на этом языке

Для реализации языка программирования высокого уровня нужно определиться с языком, который будет взят за основу. Исходя из принципа, что язык должен быть достаточно известным и, по возможности, использоваться другими проектами в качестве внутреннего языка вычислений, остановимся на следующих языках: С, Java, JavaScript и Phyton. Поскольку языки С, Java и JavaScript практически вышли из языка C, то ограничим круг до языков Java и JavaScript. Язык C++ является несколько сложным, поскольку содержит механизмы работы с адресами и указателями. Эти возможности являются избыточными для задач среды пользовательского программирования.


Остановимся на языках Java и JavaScript, грамматика которых упрощена. Сначала реализуем общую грамматику для языков Java и JavaScript с последующим уклоном к языку JavaScript, поскольку он часто используется внутри других проектов (Web-браузеры, KDE).


4.4 Проектирование грамматики синтаксического анализатора. Выбор инструмента для создания синтаксического и лексического анализаторов

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


Лексический анализатор строится достаточно просто.


Синтаксический анализатор основывается на таком понятии, как формальные грамматики и его создание - задание нетривиальное. Поэтому существуют готовые инструменты для построения синтаксических анализаторов по указанной грамматике. Из них можно отметить генератор синтаксических анализаторов Yacc (AT&T и Berkeley). На основе этого известного генератора синтаксических анализаторов создано множество других, например Bison и Zubr. Все они совместимы и могут заменять один другого.


Для разработки языка программирования был выбран генератор синтаксических анализаторов Bison, поскольку он свободно распространяется практически со всеми современными дистрибутивами ОС Linux, развивается и является многоплатформенным.


Любую формальную грамматику можно записать в виде:
G = <A, N, г, P>
где :

A – терминальный алфавит;
N – нетерминальный алфавит;
г - аксиома;
P – правило грамматики.

Запишем терминальный и нетерминальный алфавиты:
A = {ERR, IF, ELSE, =, ADDEQ, SUBEQ, MULEQ, DIVEQ, FUNC, B_FUNC, B_FUNC1, B_FUNC2, VAR, CONST, ?, :, OR, AND, |, &, ^, >, <, GE, LE, EQ, NE, +, -, *, /, %, UN_MINUS, !, , ',', (, ), '{', '}', ; }
N = {root, solver, solve,assign, expr, prmlst, if, if_expr, end }


Описание терминального алфавита приведено в таблице 1. Описание нетерминального алфавита приведено в таблице 2. Правила P грамматики приведены в таблице 3. В качестве аксиомы грамматики определено: г = root;


Таблица 1: Терминальный алфавит Java-подобного языка (A)

ТерминалОписание
ERRОшибка. Вставляется лексическим анализатором в случае ошибки в нём.
errorОшибка. Прерывает работу синтаксического анализатора.
IFКлючевое слово условия - “if”.
ELSEКлючевое слово условия - “else”.
=Операция – присвоить.
ADDEQОперация - “+=”
SUBEQОперация - “-=”
MULEQОперация - “*=”
DIVEQОперация - “/=”
FUNCВнешняя функция.
B_FUNCВстроенная функция без параметров.
B_FUNC1Встроенная функция с одним параметром.
B_FUNC2Встроенная функция с двумя параметрами.
VARПеременная, автоматическая переменная, атрибут системного параметра или параметр функции.
CONSTКонстанта.
?Первый символ операции “?:”
:Второй символ операции “?:”
ORЛогическая операция - “||”
ANDЛогическая операция - “&&”
|Операция – побитовое “ИЛИ”
&Операция – побитовое “И”
^Операция – исключающее “ИЛИ”
>Операция – больше.
<Операция – меньше.
GEОперация – больше или равно.
LEОперация – меньше или равно.
EQОперация – эквивалентно.
NEОперация – неэквивалентно.
+Операция – сложение.
-Операция – вычитание.
*Операция – умножение.
/Операция – деление.
%Операция – остаток от целочисленного деления.
UN_MINUSОперация – унарный минус.
!Операция – инверсия.
~Операция – побитовая инверсия.
,Разделитель (отделяет параметры в функциях).
(Выделение приоритета в выражениях и параметров в функциях.
)Выделение приоритета в выражениях и параметров в функциях.
{Выделение блока выражений.
}Выделение блока выражений.
;Завершение выражения.


Таблица 2: Нетерминальный алфавит Java-подобного языка (N)

НетерминалОписание
rootКорень. Все выражения должны сворачиваться в него.
solverРешение.
solveЕлемент решения.
assignПрисвоение.
exprВыражение.
prmlstСписок параметров функции.
ifУсловие.
if_exprВыражение условия.
endКонец условия или программы.


Таблица 3: Грамматика Java-подобного языка

ПравилоОписание
root: solver end
| error
разрешение и окончание программы;
ошибка.
solver: /*empty*/
| solver solve
пустое решение;
рекурсия решения.
solve: assign ';'
| IF '(' expr ')' if solve end
| IF '(' expr ')' if solve end ELSE solve end
| FUNC '(' prmlst ')' ';'
| '{' solver '}'
присвоение;
глобальное короткое условие;
глобальное полное условие;
процедурный вызов внешней функции;
блоки кода в скобках “{“ “}”.
assign: VAR '=' expr
| VAR ADDEQ expr
| VAR SUBEQ expr
| VAR MULEQ expr
| VAR DIVEQ expr
простое присвоение;
присвоение с добавлением;
присвоение с вычитанием;
присвоение с умножением;
присвоение с делением.
expr: CONST
| VAR
| VAR '=' expr
| B_FUNC '(' ')'
| B_FUNC1 '(' expr ')'
| B_FUNC2 '(' expr ',' expr ')'
| FUNC '(' prmlst ')'
| expr '+' expr
| expr '-' expr
| expr '*' expr
| expr '/' expr
| expr '%' expr
| expr '|' expr
| expr '&' expr
| expr '^' expr
| '(' expr ')'
| expr OR expr
| expr AND expr
| expr '<' expr
| expr '>' expr
| expr GE expr
| expr LE expr
| expr EQ expr
| expr NE expr
| '!' expr
| '~' expr
| '-' expr
| expr if_expr expr end ':' expr end
константа;
переменная;
присвоение переменной внутри выражения;
встроенная функция без параметров;
встроенная функция с одним параметром;
встроенная функция с двумя параметрами;
внешняя функция;
добавление;
вычитание;
умножение;
деление;
остаток от целочисленного деления;
побитовое “ИЛИ”;
побитовое “И”;
побитовое исключающее “ИЛИ”;
скобки в выражении;
логическое “ИЛИ”;
логическое “И”;
меньше;
больше;
больше и равно;
меньше и равно;
равно;
не равно;
логическое отрицание;
побитовая инверсия;
унарный минус;
условие внутри выражения;
prmlst: /*empty*/
| expr
| prmlst ',' prmlst
пустой список параметров;
выражение как параметр;
перечень параметров через “,”.
if: /*empty*/Старт условия (для создания кода условия).
if_expr: '?'Старт условия внутри выражения.
end: /*empty*/Конец программы или условия.


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


Реализуем лексический анализатор, который должен выполнять следующие функции:


Для упрощения языка будем использовать неявное определение локальных переменных, которое предполагает определение новых переменных во время присвоения ей первого значения. Кроме того, тип локальной переменной должен устанавливаться в соответствии с типом значения, которое впервые было ей присвоено. Например, выражение <Qr=Q0*Pi+0.01;> должно определить переменную Qr типом переменной Q0.


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


Для комментирования участков кода предусмотрим символы «//». Всё, что идёт после данных символов до конца строки, должно игнорироваться компилятором (лексическим анализатором).


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


Под оптимизацией по константам подразумевается выполнение вычислений над двумя константами в процессе построения кода и последующая вставка результата в код. Например, выражение <y=pi*10;> должно свернуться к простому присваиванию <y=31.4159;>.


Под приведением типов констант к необходимому типу подразумевается формирование в коде константы, которая исключает приведение типа в процессе исполнения. Например, выражение <y=x*10> в случае вещественного типа переменной <x>, должно преобразоваться в <y=x*10.0>.

4.4.1 Элементы языка

В результате разработки реализуем следующие элементы языка программирования:
Ключевые слова: if, else, true, false.
Постоянные:

Типы переменных:

Встроенные константы: pi = 3.14159265, e = 2.71828182.
Атрибуты параметров системы OpenSCADA.
Функции объектной модели системы OpenSCADA.

4.4.2 Операции

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


Таблица 4. Операции Java-подобного языка

СимволОписание
()Вызов функции.
{}Программные блоки.
-Унарный минус.
!Логическое отрицание.
~Побитовое отрицание.
*Умножение.
/Деление.
%Остаток от целочисленного деления.
+Сложение
-Вычитание
>Больше
>=Больше или равно
<Меньше
<=Меньше или равно
==Равно
!=Неравно
|Поразрядное «ИЛИ»
&Поразрядное «И»
^Поразрядное «Исключающее ИЛИ»
&&Логический «И»
||Логический «ИЛИ»
?:Условная операция (i=(i<0)?0:i;)
=Присваивание.
+=Присваивание с сложением.
-=Присваивание с вычитанием.
*=Присваивание с умножением.
/=Присваивание с делением.

4.4.3 Встроенные функции языка

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

4.4.4 Операторы языка

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


Условный оператор для использования внутри выражения строится на операциях «?» и «:». В качестве примера можно записать следующее практическое выражение <st_open=(pos>=100)?true:false;>, что читается, как «Если переменная <pos> больше или равна 100, то переменной <st_open> присваивается значение "true", иначе "false".


Глобальное условие строится на основе ключевых слов "if" и "else". В качестве примера можно привести то же выражение, но другим способом <if(pos>100) st_open=true; else st_open=false;>. Как видно, выражение записано по-другому, но читается также.

4.4.5 Примеры программы на Java-подобном языке

Приведём несколько примеров программ на разработанном Java-подобном языке:


//Модель хода исполнительного механизма шарового крана
if( !(st_close && !com) && !(st_open && com) )
{
  tmp_up=(pos>0&&pos<100)?0:(tmp_up>0&&lst_com==com)?tmp_up-1./frq:t_up;
  pos+=(tmp_up>0)?0:(100.*(com?1.:-1.))/(t_full*frq);
  pos=(pos>100)?100:(pos<0)?0:pos;
  st_open=(pos>=100)?true:false;
  st_close=(pos<=0)?true:false;
  lst_com=com;
}


//Модель клапана
Qr=Q0+Q0*Kpr*(Pi-1)+0.01;
Sr=(S_kl1*l_kl1+S_kl2*l_kl2)/100.;
Ftmp=(Pi>2.*Po)?Pi*pow(Q0*0.75/Ti,0.5):(Po>2.*Pi)?Po*pow(Q0*0.75/To,0.5):pow(abs(Q0*(pow(Pi,2)-pow(Po,2))/Ti),0.5);
Fi-=(Fi-7260.*Sr*sign(Pi-Po)*Ftmp)/(0.01*lo*frq);
Po+=0.27*(Fi-Fo)/(So*lo*Q0*frq);
Po=(Po<0)?0:(Po>100)?100:Po;
To+=(abs(Fi)*(Ti*pow(Po/Pi,0.02)-To)+(Fwind+1)*(Twind-To)/Riz)/(Ct*So*lo*Qr*frq);


4.5 Разработка внутренней виртуальной машины

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


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


Виртуальная машина позволяет реализовывать высоко производительные вычисления за счёт оптимизации кода и исключения лишнего анализа лексического и синтаксического анализаторов, однако требует значительных усилий на её разработку.


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


Существует множество способов построения виртуальной машины, из них можно отметить:


Стековые машины являются удобным способом построения виртуальной машины. Особенностью стековой виртуальной машины является:


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


Другим классом виртуальных машин являются виртуальные машины, основанные на так называемых четверках. Суть четвёрок состоит в том, что команда состоит из: <код> <результат> <операнд1> <операнд2>


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


Все даные нашей виртуальной машины будем размещать в регистрах. Регистр виртуальной машины должен представлять структуру, которая может сохранять следующие данные:


Команды построенной виртуальной машины приведено в приложении A. Механизм работы виртуальной машины будет следующим:
Синтаксический анализатор выделяет команды и генерирует код в семантических процедурах Bison. Во время генерации кода виртуальной машины формируется перечень регистров. Регистры, которые содержат ссылки на параметры данной функции, атрибуты параметров подсистемы "DAQ" и внутренние переменные, будут инициализироваться во время генерации кода и больше не использоваться на другие цели. Другие регистры (динамические даные промежуточных вычислений) должны резервироваться и использоваться на временные цели. Такие регистры инициируются конкретными значениями во время выполнения программы в виртуальной машине. Полученная конфигурация регистров (структура памяти) и код программы виртуальной машины используются в режиме вычисления виртуальной машины. При этом конфигурация регистров не меняется, что позволяет использовать быстрые механизмы для доступа к регистрам и первичной инициализации кадра регистров.


Для адресации регистров использован один байт, что обеспечивает поддержку до 255 параметров функции (в сумме с внутренними переменными).


4.6 Разработка языка блочного программирования

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


С формальной точки зрения блок - это элемент, который имеет входы, выходы и алгоритм вычисления. Исходя из концепции среды программирования и его основы (рис. 2), блок - это кадр значений параметров, ассоциированный с объектом функции.


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


Условно соединения блоков можно изобразить как связи между блоками в целом (рис. 3) или детализация связей (рис. 4). В процессе связывания параметров блоков не будем придерживаться строгого соответствия типам параметров. Это означает, что параметры разных типов смогут легко связываться один с другим. Причем в процессе вычисления будет выполняться автоматическое приведение типов.


Поскольку блочный вычислитель основан на объектах функций объектной модели системы OpenSCADA, то и типы параметров блоков будут такими же, то есть: целое, вещественное, логичное и строка.


Общие связи между блоками блочной схемы (15 Кб)
Рис. 3. Общие связи между блоками блочной схемы

Детализированные связи между блоками (14 Кб)
Рис. 4. Детализированные связи между блоками

4.7 Проектирование архитектуры

Исходя из модульной архитектуры системы OpenSCADA и размышлений, приведенных в разделах выше, была разработана архитектура среды программирования (рис.5).


Структура среды программирования (39 Кб)
Рис. 5. Общая структура среды программирования

Как можно видеть, архитектура среды программирования состоит из трёх частей:


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


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


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


Статическая диаграмма классов среды программирования (17 Кб)
Рис. 6. Статическая диаграмма классов среды программирования

Таблица 5. Классы среды программирования

КлассОтветственностьСвязи
TFunctionКласс функции. Содержит описание параметров (IO). В предке должен содержать реализацию алгоритма функции.Используется вычислителями для связывания с кадром значений. Является абстрактным, наследуется компонентами, которые предоставляют собственные библиотеки функций.
TValFuncКласс значений функции. Содержит значения функции в соответствии с составом параметров (IO) класса TFunction.Агрегируется с объектом функции TFunction для совместных вычислений. Может наследоваться классами вычислителя. Экземпляр класса TValFunc передаётся классу TFunction во время вычисления для выполнения алгоритма в TFunction над значениями в TValFunc.
IOКласс параметра функции. Содержит описание параметра, его тип и атрибуты.Используется классом значений TValFunc для определения значений параметров.
UserLibКласс библиотеки пользователя.Может предоставлять инструмент создания функций пользователя.
UserFuncКласс функции пользователя. Предоставляет параметры функции и алгоритм вычисления.Наследует класс функции TFunction.
BlockПользовательский класс вычислителя. Содержит ассоциированный с функцией TFunction кадр значений TValFunc. Вызывает процесс вычисленияНаследует класс кадра значений.

4.7.1 Архитектура вычислителя на Java-подобном языке

Исходя из структуры среды программирования (рис.5) и её диаграммы классов (рис.6), создадим классы вычислителя на Java-подобном языке (рис.7). Описание классов приведено в таблице 6.


Статическая диаграмма классов модуля \
Рис. 7. Статическая диаграмма классов модуля "JavaLikeCalc"

Таблица 6. Классы модуля JavaLikeCalc

КлассОтветственностьСвязи
TipContrКоренной класс модуля, главным назначением которого является точка входа в модуль.

Наследует класс интерфейса модулей подсистемы «Источников данных» TTypeDAQ для интеграции в систему OpenSCADA. Содержит:

  • библиотеки функций предоставляемые этим модулем;
  • объекты классов (Bfunc) встроенных в язык функций;
  • объекты классов (NConst) именованных констант языка.
ContrКласс реализации контроллера. Содержит механизм периодических вычислений над алгоритмом функции этого модуля.Наследует класс интерфейса контроллера TController. Наследует класс кадра значений функции вычисления TValFunc.
PrmКласс реализации параметра. Содержит механизм отображения таблицы данных контроллера на структуру параметра системы OpenSCADA.Наследует класс интерфейса параметра TParamСontr. Содержит ссылки на таблицу данных контроллера.
LibКласс библиотеки функций данного модуля. Содержит механизм создания функций на Java-подобном языке.Содержит функции Func данной библиотеки.
FuncКласс реализации функции. Содержит механизм создания параметров функции и программы вычисления. Также содержит механизм вычисления в виде виртуальной машины и компилятор для построения программы виртуальной машины.

Наследует класс интерфейса функции TFunction. Содержит:

  • рабочие регистры;
  • регистры вычисления;
  • ссылки на использованные внешние функции.
BFuncКласс встроенной функции. Содержит описание и количество параметров функции.Содержится в классе TTipContr. Используется компилятором и виртуальной машиной в TFunc.
NConstКласс именованной константы. Содержит описание и значение константы.Содержиться в классе TTipContr. Используется компилятором и виртуальной машиной в TFunc.
RegКласс регистра виртуальной машины. Содержит информацию про тип регистра, его содержимое и другую информацию, необходимую для построения программы виртуальной машины.Содержится в классе функции Func. Используется компилятором и виртуальной машиной.
RegWКласс рабочего регистра виртуальной машины. Содержит только данные про тип и значение регистра, которых достаточно для работы виртуальной машины.Содержится в классе функции Func. Используется виртуальной машиной во время вычисления.
UFuncКласс внешней функции, который используется программой виртуальной машины.Содержится в классе функции Func. Используется виртуальной машиной во время вычисления.

Для непосредственного вычисления нужно обеспечить создание и связывание контроллера с функцией этого же модуля. Для связывания с функцией в контроллере создаётся кадр значений TValFunc, над которым и производятся периодические вычисления.


Для экспорта полученных значений из контроллера в систему OpenSCADA и для импорта значений из системы в контроллер нужно использовать параметры контроллера подсистемы "DAQ". Параметры контроллера связываются с параметром вычислительной функции (полем таблицы данных) и должны выполнять отражение значений.

4.7.2 Архитектура вычислителя на языке блоков

Исходя из структуры среды программирования (рис.5) и её диаграммы классов (рис.6), создадим классы вычислителя на языке блоков (рис.8). Описание классов приведено в таблице 7.


Статическая диаграмма классов модуля BlockCalc (47 Кб)
Рис. 8. Статическая диаграмма классов модуля "BlockCalc"

Таблица 6. Классы модуля BlockCalc

КлассОтветственностьСвязи
TipContrКоренной класс модуля, главным назначением которого является точка входа в модуль.
Наследует класс интерфейса модулей подсистемы «Источников данных» TTypeDAQ для интеграции в систему OpenSCADA.
ContrКласс реализации контроллера. Содержит механизм периодических вычислений над алгоритмом блочной схемы.Наследует класс интерфейса контроллера TController. Содержит блоки блочной схемы.
PrmКласс реализации параметра подсистемы "DAQ". Содержит механизм отражения параметров блоков блочной схемы на структуру параметра подсистемы "DAQ" системы OpenSCADA.Наследует класс интерфейса параметра TParamСontr. Содержит ссылки на параметр блока блочной схемы.
BlockКласс блока. Содержит кадр значений в соответствии с ассоциированной функцией. Содержит механизм связей.Наследует класс интерфейса кадра значений TValFunc. На него ссылается объект класса параметра (Prm). Экземпляры класса этого типа могут содержать связи один на другого.

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


Сами блоки при этом не содержат структуры входов/выходов(IO), а только содержат значения, исходя из структуры параметров связанной функции. Для соединения с блоком могут использоваться любые функции объектной модели (ОМ) системы OpenSCADA.


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

4.7.3 Стандартная архитектура библиотек статических функций

Исходя из структуры среды программирования (рис.5) и её диаграммы классов (рис.6), создадим архитектуру классов для библиотек статических функций (рис.9). Описание классов приведено в таблице 8.


Статическая диаграмма классов статических библиотек функций (34 Кб)
рис. 9. Статическая диаграмма классов статических библиотек функций

Таблица 7. Классы статической библиотеки функций

КлассОтветственностьСвязи
LibКоренной класс модуля, главным назначением которого является точка доступа в модуль. Выполняет функцию библиотеки, а значит содержит объекты статических функций.Наследует класс интерфейса модулей подсистемы «Специальные» TSpecial для интеграции в систему OpenSCADA. Содержит объекты функций.
FuncКласc функции. Содержит структуру параметров и алгоритм их вычисления.Наследует класс интерфейса функции TFunction.

На основе данной архитектуры построены следующие статические библиотеки функций:


Таблица 8. Функции библиотеки Complex1

IdИмяОписание функции. Формулы вычислений функций
alarm Сигнал
Сигнал по шкале параметра:
out = if(val>max || val<min) then true; else false;
cond <Условие '<'
Условие '<' по формуле:
out=if(in1<(in2_1*in2_2*in2_3*in2_4)) 
then in3_1*in3_2*in3_3*in3_4;
else in4_1*in4_2*in4_3*in4_4;
cond >Условие '>'
Условие '>' по формуле:
out=if(in1>(in2_1*in2_2*in2_3*in2_4)) 
then in3_1*in3_2*in3_3*in3_4;
else in4_1*in4_2*in4_3*in4_4;
cond_fullПолное условие
Полное условие по формуле:
out = if(in1<(in2_1*in2_2*in2_3*in2_4))
then in3_1*in3_2*in3_3*in3_4;
else if( in1>(in4_1*in4_2*in4_3*in4_4) 
  then in5_1*in5_2*in5_3*in5_4;
  else in6_1*in6_2*in6_3*in6_4;
digitBlockДискретный блокСборка дискретных сигналов.
divДелитель
Делитель по формуле:
out = (in1_1*in1_2*in1_3*in1_4*in1_5 + in2_1*in2_2*in2_3*in2_4*in2_5 + in3) /
(in4_1*in4_2*in4_3*in4_4*in4_5 + in5_1*in5_2*in5_3*in5_4*in5_5 + in6);
expЭкспонента
Экспонента по формуле:
out=exp (in1_1*in1_2*in1_3*in1_4*in1_5 + (in2_1*in2_2*in2_3*in2_4*in2_5+in3) /
(in4_1*in4_2*in4_3*in4_4*in4_5+in
flowРасход
Расчёт расхода по формуле:
f = K1*((K3+K4*x)^K2);
incrementИтератор
Итератор по формуле:
out = if( in1 > in2 ) then in2 + in3*(in1-in2); 
else in2 - in4*(in2-in1);
lagЗадержка
Задержка по формуле:
y = y - Klag*( y - x );
multПростое умножение
Простое умножение по формуле:
out=(in1_1*in1_2*in1_3*in1_4*in1_5*in1_6)/
(in2_1*in2_2*in2_3*in2_4);
multDivУмножение+деление
Умножение+деление по формуле:
out=in1_1*in1_2*in1_3*in1_4*in1_5*
(in2_1*in2_2*in2_3*in2_4*in2_5+(in3_1*in3_2*in3_3*in3_4*in3_5)/
(in4_1*in4_2*in4_3*in4_4*in4_5));
pidПИД регуляторПИД регулятор
powСтепень
Степень по формуле:
out=(in1_1*in1_2*in1_3*in1_4*in1_5)^
(in2_1*in2_2*in2_3*in2_4*in2_5 + (in3_1*in3_2*in3_3*in3_4*in3_5)/
(in4_1*in4_2*in4_3*in4_4*in4_5));
selectВыбор
Вибор по формуле:
out = if( sel = 1 ) then in1_1*in1_2*in1_3*in1_4;
if( sel = 2 ) then in2_1*in2_2*in2_3*in2_4;
if( sel = 3 ) then in3_1*in3_2*in3_3*in3_4;
if( sel = 4 ) then in4_1*in4_2*in4_3*in4_4;
sumПростой сумматор
Простой сумматор по формуле:
out=in1_1*in1_2+in2_1*in2_2+in3_1*in3_2+in4_1*in4_2
+ in5_1*in5_2+in6_1*in6_2+in7_1*in7_2+in8_1*in8_2;
sum_divСумма с делением
Сумма с делением по формуле:
out = in1_1*in1_2*(in1_3+in1_4/in1_5) + 
in2_1*in2_2*(in2_3+in2_4/in2_5) +
in4_1*in4_2*(in4_3+in4_4/in4_5) + 
in5_1*in5_2*(in5_3+in5_4/in5_5);
sum_multСумма с умножением
Сумма с умножением по формуле:
out = in1_1*in1_2*(in1_3*in1_4+in1_5) + 
in2_1*in2_2*(in2_3*in2_4+in2_5) +
in4_1*in4_2*(in4_3*in4_4+in4_5) + 
in5_1*in5_2*(in5_3*in5_4+in5_5);

Таблица 9. Стандартные математические функции

IdИмяОписание
absМодульМат. функция - модуль от числа.
acosАрккосинусМат. функция - арккосинус.
asinАрксинусМат. функция - арксинус.
atanАрктангенсМат. функция - арктангенс.
ceilОкругл. до большегоМат. функция - округления до большего целого.
cosКосинусМат. функция - косинус.
coshКосинус гиперболическийМат. функция - косинус гиперболический.
expЭкспонентаМат. функция - экспонента.
floorОкругл. до меньшегоМат. функция - округления до меньшего целого
ifУсловие ЕслиФункция - условие "Если".
lgДесятичный логарифмМат. функция - десятичный логарифм.
lnНатуральный логарифмМат. функция - натуральный лагорифм.
powСтепеньМат. функция - возведение в степень.
randСлуч. числоМат. функция - генератор случайных чисел.
sinСинусМат. функция - синус.
sinhСинус гиперболическийМат. функция - синус гипербалический.
sqrtКорень квадратныйМат. функция - корень квадратный.
tanТангенсМат. функция - тангенс.
tanhТангенс гиперболическийМат. функция - тангенс гиперболический.

Таблица 10. Функции времени

IdИмяОписание
dateПолная датаВозвращает полную дату в составе: секунда, минута, час, день месяца, месяц, год, день недели, день в году.
timeПолное время (с 01.01.1970)Возвращает полное время в виде числа секунд от начала эпохи
ctimeПолное время в виде строкиВозвращает строку полного времени вида "Wed Jun 30 21:49:08 1993".

5. Реализация

Начальную реализацию среды программирования в коде было выполнено с помощью полученной UML-модели путём генерации C++ кода в программе Umbrello. В результате был разработан интерфейс объектной модели (API) и компоненты в виде модулей к системе OpenSCADA:

Общую структуру всех этих компонентов и API приведено на рис.10.


Общая структура компонентов среды программирования (78 Кб)
рис. 10. Общая структура компонентов среды программирования

ПРИЛОЖЕНИЕ A. Команды внутренней виртуальной машины

Таблица. Команды внутренней виртуальной машины модуля “JavaLikeCalc”

КомандаКодОписание
End01Окончание программы или условной команды.
MviB02 R VЗагрузка логического признака [V] в регистр [R]. Производится инициализация регистра.
MviI03 R V V V VЗагрузка целого числа [V V V V] в регистр [R]. Производится инициализация регистра.
MviR04 R V V V V V VЗагрузка вещественного числа [V V V V V V] в регистр [R]. Производится инициализация регистра.
MviS05 R N S . . Загрузка строки [S . .] длиной [N] в регистр [R]. Производится инициализация регистра.
AssB06 R0 R1Присвоение логического признака из регистра [R1] регистру [R0].
AssI07 R0 R1Присвоение целого из регистра [R1] регистру [R0].
AssR08 R0 R1Присвоение вещественного из регистра [R1] регистру [R0].
AssS09 R0 R1Присвоение строки из регистра [R1] регистру [R0].
MovB0A R0 R1Перемещение логического признака из регистра [R1] в регистр [R0]. Производится инициализация регистра.
MovI0B R0 R1Перемещение целого из регистра [R1] в регистр [R0]. Производится инициализация регистра.
MovR0C R0 R1Перемещение вещественного из регистра [R1] в регистр [R0]. Производится инициализация регистра.
MovS0D R0 R1Перемещение строки из регистра [R1] в регистр [R0]. Производится инициализация регистра.
AddIOE R0 R1 R2Сложение целых: R0 = R1 + R2.
AddROF R0 R1 R2Сложение вещественных: R0 = R1 + R2.
AddS1O R0 R1 R2Сложение строк: R0 = R1 + R2.
SubI11 R0 R1 R2Вычитание целых: R0 = R1 - R2.
SubR12 R0 R1 R2Вычитание вещественных: R0 = R1 - R2.
MultI13 R0 R1 R2Перемножение целых: R0 = R1 * R2.
MultR14 R0 R1 R2Перемножение вещественных: R0 = R1 * R2.
DivI15 R0 R1 R2Деление целых: R0 = R1 / R2.
DivR16 R0 R1 R2Деление вещественных: R0 = R1 / R2.
RstI17 R0 R1 R2Остаток от целочисленного деления: R0 = R1 % R2.
BitOr18 R0 R1 R2Побитовое “ИЛИ”: R0 = R1 | R2.
BitAnd19 R0 R1 R2Побитовое “И”: R0 = R1 & R2.
BitXor1A R0 R1 R2Побитовое исключающее “ИЛИ”: R0 = R1 ^ R2.
LOr1B R0 R1 R2Логическое “ИЛИ”: R0 = R1 || R2.
LAnd1C R0 R1 R2Логическое “И”: R0 = R1 && R2.
LTI1D R0 R1 R2Целое меньше: R0 = R1 < R2.
LTR1E R0 R1 R2Вещественое меньше: R0 = R1 < R2.
GTI1F R0 R1 R2Целое больше: R0 = R1 > R2.
GTR20 R0 R1 R2Вещественное больше: R0 = R1 > R2.
LEI21 R0 R1 R2Целое меньше или равно: R0 = R1 <= R2.
LER22 R0 R1 R2Вещественное меньше или равно: R0 = R1 <= R2.
GEI23 R0 R1 R2Целое больше или равно: R0 = R1 >= R2.
GER24 R0 R1 R2Вещественное больше или равно: R0 = R1 >= R2.
EQI25 R0 R1 R2Целое равно: R0 = R1 == R2.
EQR26 R0 R1 R2Вещественное равно: R0 = R1 == R2.
EQS27 R0 R1 R2Строка равно: R0 = R1 == R2.
NEI28 R0 R1 R2Целое не равно: R0 = R1 != R2.
NER29 R0 R1 R2Вещественное не равно: R0 = R1 != R2.
NES2A R0 R1 R2Строка не рано: R0 = R1 != R2.
Not2B R0 R1Отрицание: R0 = !R1.
BitNot2С R0 R1Побитовая инверсия: R0 = ~R1.
NegI2D R0 R1Инверсия целого: R0 = -R1.
NegR2E R0 R1Инверсия вещественного: R0 = -R1.
If2F R E E N NУсловие, если [R] действительно, то исполняются команды после этой операции и по завершению выполняется переход по относительному адресу [N N]; иначе выполняются команды по относительному адресу [EE] и по завершению выполняется переход по относительному адресу [N N].
FSin30 R0 R1Функция синус: R0 = sin(R1).
FCos31 R0 R1Функция косинус: R0 = cos(R1).
FTan32 R0 R1Функция тангенс: R0 = tan(R1).
FSinh33 R0 R1Функция гиперболический синус: R0 = sinh(R1).
FCosh34 R0 R1Функция гиперболический косинус: R0 = cosh(R1).
FTanh35 R0 R1Функция гиперболический тангенс: R0 = tanh(R1).
FAsin36 R0 R1Функция арксинус: R0 = asin(R1).
FAcos37 R0 R1Функция арккосинус: R0 = acos(R1).
FAtan38 R0 R1Функция арктангенс: R0 = atan(R1).
FRand39 R0 R1Случайное число: R0 = rand(R1).
FLg3A R0 R1Десятичный логарифм: R0 = lg(R1).
FLn3B R0 R1Натуральный логарифм: R0 = ln(R1).
FExp3С R0 R1Экспонента: R0 = exp(R1).
FPow3D R0 R1 R2Возведение в степень: R0 = pow(R1,R2).
FSqrt3E R0 R1Корень квадратный: R0 = sqrt(R1).
FAbs3F R0 R1Абсолютное значение: R0 = |R1|.
FSign40 R0 R1Знак: R0 = sign(R1).
FCeil41 R0 R1Округление до большего: R0 = ceil(R1).
FFloor42 R0 R1Округление до меньшего: R0 = floor(R1).
CProc43 F N R P P . .Процедурный вызов внешней функции [F], с параметрами [P P . .], в количестве [N]. [R] - не используется.
CFunc44 F N R P P . .Вызов внешней функции [F], с параметрами [P P . .], в количестве [N]. Результат функции помещается в [R].

Ссылки

Referring pages: Doc
Doc/LogicLevParam
Doc/VCA/part6/part1
HomePageUk/Doc
Works/ChangeLog/part2006


 
There are 20 files on this page.[Display files/form]
There is no comment on this page. [Display comments/form]