Актуальность наличия технологий решения задач моделирования, мониторинга и управления сложными технологическими объектами не вызывает сомнений. Сегодня у научных и инженерно-технических работников в наличии имеется большое количество программных продуктов в основном зарубежного производства. Полноценное их использование в силу не полной документированности или дороговизны отдельных составляющих модулей (библиотек) затруднительно. Поэтому наличие возможности самостоятельного расширения пакетов конечным пользователем всегда представляет особый интерес. "MathConnex" в пакете "Mathcad 2000", и "VisSim" - возможно наиболее известные моделирующие программы, имеющие интерфейсы для расширений.
Существуют несколько технологий расширений. Первая - внедрение ActiveX объектов других программных продуктов (см. "MathConnex"). Вторая - динамический обмен данными между программами посредством DDE или OPC серверов / клиентов. Третья - создание библиотечных модулей с новыми для пакетов процедурами и функциями. Пакет VisSim имеет все три механизма. Первые два интуитивно понятны и хорошо описаны в документации. Методика подключения внешних, динамически загружаемых библиотек - dll документирована не полностью, поэтому вызывает затруднения у пользователей, хотя способна существенно расширить возможности пакета. Пользователь сможет, используя известный ему язык программирования С, С++, Pascal (Delphi), Basic, Fortran создавать новые линейные, нелинейные, дискретные, частотно зависимые элементы, расширяя библиотеку стандартных; разрабатывать собственные процедуры и функции измерений, анализа, работы с базами данных; подключать как собственные, так и стандартные платы сбора данных (DAQ-board) или OPC сервера для исследования, мониторинга, управления внешним объектом.
Постановка задачи. Необходимо создать "dll-модель" (согласно меню VisSim-а "userFunction") (см. Рисунок 1), которая имеет два выхода и выполняет две операции: интегрирование и синтез синусоидальной функции. Модель должна иметь: вход для интегратора, вход для временного сигнала, и вход для передачи значения шага моделирования.
Демонстрация результатов моделирования с использованием пользовательской функции "myF", подключенной с помощью блока "userFunction" из библиотеки Project2.dll, написанной с использованием зыка программирования Pascal (Delphi)
Рисунок 1
Модель должна иметь следующие начальные условия и параметры: 1) начальное значение, присваиваемое интегратору в начале моделирования, 2) амплитудное значение, 3) частоту и 4) фазу синтезируемого синусоидального сигнала. Т.е. при нажатии правой клавиши мыши на блоке "Project2.dll.myF", должно появится диалоговое окно - см. Рисунок 2.
Рисунок 2
Все, что требуется - это написать библиотечную программу на языке Pascal в соответствии с определенными правилами, скомпилировать в файл Project2.dll (имя библиотеки значения не имеет) и подключить его к рабочему файлу пакета VisSim с помощью блока "userFunction". Для создания dll-библиотеки выбран язык Pascal (Delphi), поскольку в примерах пакета есть исходные файлы для языка С. Приведем распечатку файла Project2.dpr.
Файл: Project2.dpr |
library Project2; type InVector = array [0..9] of Double; { тип входной переменной: входов - 10 } OutVector = array [0..9] of Double; { тип выходной переменной: выходов - 10 } Global = record { запись параметров, и координат "dll"-модели } Uo : double; { Начальное условие для интегратора ID1 } Am : double; { Амплитуда синусоиды } freq : double; { частота синусоиды } faza : double; { фаза синусоиды } end; var ID1 : double; { вспомогательные переменные "dll"-модели } {/************ Это базовая процедура в DLL ****************************/} {/************ Вызывается VisSim-ом на каждом шаге моделирования ******/} procedure myF(var P:Global; var inV:InVector; var outV:OutVector); export; stdcall; begin { Расчеты, выполняемые на каждом шаге моделирования } ID1:=ID1+inV[0]*inV[2]/2; outV[0]:=ID1; { интегрирование } outV[1]:=P.Am*sin(2*Pi*inV[1]*P.freq+P.faza); { синтез синусоидального сигнала } end; {/************ Функция размещения параметров **************************/} {/************ Вызывается VisSim-ом при создании блока ****************/} function myFPA( var pCount:integer):Longint; export; stdcall; begin pCount := 4; { число первых по списку параметров записываемых в файл *.vsm } myFPA := sizeof(Global); { размер памяти необходимый под параметры } end; {/************ Процедура инициализации параметров *********************/} {/************ Вызывается VisSim-ом после PA функции ******************/} procedure myFPI( var P:Global ); export; stdcall; begin { Инициализация параметров (координат) модели. значения постоянных времени, напряжений, токов ...} P.Uo:=0; P.Am:=10; P.freq:=2; P.faza:=0; end; {/************ Функция изменения параметров ***************************/} {/************ Вызывается VisSim-ом при нажатии правой клавиши мыши ***/} function myFPC( var P:Global ):Pchar; export; stdcall; begin { Изменение параметров модели: соответствующий очередности список названий параметров } myFPC :='Начальное условие;Am;freq;faza';{ названия могут быть любые } end; {/************ Процедура Simulation Start *****************************/} {/************ Вызывается VisSim-ом на первом шаге моделирования ******/} procedure myFSS( var P:Global; var runCount:longint); export; stdcall; begin { присвоение начальных условий интеграторам: напряжений на конденсаторах, токов в индуктивностях ...} ID1:=P.Uo; end; {/************ Процедура Simulation End *******************************/} {/************ Вызывается VisSim-ом на последнем шаге моделирования ***/} procedure myFSE( var P:Global; var runCount:longint); export; stdcall; begin { сохранение значений интеграторов для повторного запуска при многоэтапном моделировании: напряжений на конденсаторах, токов в индуктивностях ...} end; exports myF index 1,{ Имя базовой процедуры в DLL Его нужно будет указать в блоке userFunction } myFPA index 2,{ Список вспомогательных процедур и функций для экспорта. Они будут } myFPI index 3,{ вызываться Vissim-ом по окончаниям PA,PI,PC,SS,SE для базового имени. } myFPC index 4, myFSS index 5, myFSE index 6; begin end. |
По тексту программы видно, что для базовой функции (процедуры) с именем "myF" пользователь должен написать минимум еще пять процедур и функций, назначение которых ясно из комментариев. Следует отметить, что откомпилированная, тридцатидвухразрядная библиотека подключается ко всем версиям пакета VisSim начиная со 2-ой (текущая 4.5 Beta).
К сожалению VisSim не создает экземпляров dll-библиотек, поэтому повторное использование dll-библиотеки требует размножения файла *.dll (*.dll, *1.dll, *2.dll, ...). Этот прием демонстрирует модель сигма-дельта аналогово-цифрового преобразователя (см. в архиве (files) дискуссионной e-группы). Цифровой фильтр модели состоит из трех одинаковых звеньев. Одно звено это одна dll-библиотека.
Любой из частотных анализов неприменим для dll-библиотек. Поскольку VisSim не производит виртуальных измерений, а анализирует модели используя передаточные функции.
При написании dll-библиотек пользователю предоставляется еще две, интересные возможности. Первая заключена в использовании глобальных переменных и процедур непосредственно файла Vissim32.exe, что избавляет от необходимости передавать в и из "dll-модели" пользователя переменные и сигналы "шаг моделирования", "время моделирования", "остановить моделирование", "ошибка в dll-модели". Вторая заключена в направлении потока событий (Event) в "dll-модель", что позволяет пользовательской модели реагировать как на события стандартных устройств ввода / вывода: клавиатуры, мыши, так и на события пакета VisSim: "получить имя модели", "получить описание параметров", "установить локальный временной шаг моделирования", "выполнить пред-моделирование", "выполнить пост-моделирование", и т.д.
Вечная жизнь в играх своими руками тут25.08.2000