MATLAB.Exponenta
–Û·Ë͇ Matlab&Toolboxes

Simulink

И.В.Черных. "Simulink: Инструмент моделирования динамических систем"

  В оглавление книги \ К следующему разделу \ К предыдущему разделу

16. Simulink-функции

16.1. Введение

Simulink-функции (S-функции, S-functions) являются описанием блока на одном из языков программирования: MATLAB, C, C++, Ada, или Fortran. Набор стандартных блоков Simulink, достаточно обширен, однако в практике моделирования встречаются ситуации, когда нужного блока нет, либо структурное моделирование делает модель слишком сложной. В этом случае необходимо использовать технологию S-функций для создания нужного блока. С помощью языков программирования пользователь может создать описание сколь угодно сложного блока и подключить его к Simulink-модели, при этом с точки зрения взаимодействия пользователя с моделью, блок на основе S-функции ничем не отличается от стандартного библиотечного блока Simulink. Создаваемые блоки могут быть непрерывными, дискретными или гибридными. S-функции, созданные на C, C++, Ada или Fortran компилируются в исполняемые (*.dll) файлы, за счет чего обеспечивается повышенная скорость выполнения таких блоков. Такие S-функции обладают еще и дополнительными возможностями, которые включают работу с разными типами данных (целыми, действительными и комплексными числами различной степени точности), использование матриц в качестве входных и выходных переменных (MATLAB S-функции могут оперировать только векторами в качестве входных и выходных переменных), а также больший набор внутренних функций (сallback-методов).

Чаще всего S-функции используются при создании новых библиотечных блоков, блоков, обеспечивающих взаимодействие Simulink с аппаратными средствами компьютера, при создании блоков на основе математических уравнений, блоков реализующих анимационные возможности MATLAB, а также при подключении к модели Simulink существующего программного кода языков высокого уровня.

16.1. Блок S-function

S-функция подключается к модели Simulink с помощью библиотечного блока S-function (библиотека Functions&Tables). На рис. 16.1 показано окно модели с блоком S-function и его окно диалога.

Рис. 16.1 Блок S-function и его окно диалога

Параметрами блока являются:

  • S-function name – Имя S-функции. Имя S-функции не должно совпадать с именем модели (mdl-файла).
  • S-function parameters – Параметры S-функции, передаваемые в нее через окно диалога. Параметры записываются в окне диалога в том же порядке, что и в заголовке S-функции.

16.2. Математическое описание S-функции

Simulink-блок однозначно описывается наборами входных переменных u, переменных состояния x и выходных переменных y (рис. 16.2).

Рис. 16.2 Общий вид Simulink-блока

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

16.3. Этапы моделирования

Процесс расчета модели выполняется Simulink в несколько этапов. На первом этапе выполняется инициализация модели: подключение библиотечных блоков к модели, определение размерностей сигналов, типов данных, величин шагов модельного времени, оценка параметров блоков, а также определяется порядок выполнения блоков и выполняется выделение памяти для проведения расчета. Затем Simulink начинает выполнять цикл моделирования. На каждом цикле моделирования (временном шаге) происходит расчет блоков в порядке, определенном на этапе инициализации. Для каждого блока, Simulink вызывает функции, которые вычисляют переменные состояния блока x, производные переменных состояния, и выходы y в течение текущего шага модельного времени. Этот процесс продолжается, пока моделирование не будет завершено. На рис. 16.3 показана диаграмма, иллюстрирующая этот процесс.

Рис. 16.3 Процесс моделирования

16.4. Callback-методы S-функции

Каждая задача при вызове S-функции в процессе моде моделирования решается с помощью специальной внутренней функцией (сallback-метода). В MATLAB S-функции используются следующие методы:

  1. mdlInitializesizes – Инициализация. До начала первого цикла моделирования, Simulink инициализирует S-функцию. В течение этого этапа Simulink:
    • Инициализирует структуру с именем SimStruct, содержащую информацию о S-функции.
    • Устанавливает количество и размерность входных и выходных портов.
    • Устанавливает шаг модельного времени для блока.
    • Выделяет память для хранения переменных и устанавливает размерность массивов.

  2. mdlGetTimeOfNextVarHit – Вычисление времени следующего срабатывания блока (для блоков с дискретным переменным шагом расчета).
  3. mdlOutputs – Вычисление значений выходных сигналов на внешнем шаге моделирования. На этом этапе рассчитанные выходные сигналы блока передаются на его выходные порты.
  4. mdlUpdate – Расчет дискретных переменных состояния на внешнем шаге моделирования. Дискретные переменные состояния сохраняют свое значение до следующего цикла моделирования.
  5. mdlDerivatives – Расчет производных переменных состояния.
  6. mdlTerminate – Завершение работы S-функции.

Если S-функция содержит непрерывные переменные состояния, Simulink вызывает сallback-методы mdlDerivatives и mdlOutputs для расчета производных переменных состояния и выходных переменных на внутренних шагах моделирования.

Вызов каждого из методов Simulink задает с помощью переменной flag, являющейся входным параметром S-функции.

16.5. Основные понятия S-функции

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

  • Direct feedthrough – Прямой проход. Проход входных сигналов на выход. Прямой проход реализуется в S-функций, если в выражениях для выходных переменных присутствуют входные переменные, либо при расчете времени следующего срабатывания блока также используются входные переменные. Установка правильного значения параметра Direct feedthrough очень важна, поскольку именно с помощь него Simulink определяет наличие в модели замкнутых алгебраических контуров.
  • Dynamically sized inputs – Динамическая размерность входов. S-функция может быть написана таким образом, чтобы обеспечить произвольную размерность векторов входных и выходных переменных, а также векторов состояния непрерывной и(или) дискретной части системы. В этом случае фактическая размерность переменных определяется в самом начале процесса моделирования и устанавливается равной размерности входных сигналов. Чтобы задать динамическую размерность какой-либо переменной, нужно задать значение размерности для этой переменной равное -1 (минус один) в соответствующем поле структуры sizes (см. приведенный ниже шаблон S-функции).
  • Setting sample times and offsets - Установка шагов модельного времени и смещений. S-функция может задавать время срабатывания достаточно гибко. Simulink обеспечивает следующие варианты задания шага модельного времени:

  1. Continuous sample time – Непрерывное модельное время. Задается для систем имеющих непрерывные переменные состояния. Для этого типа S-функций выходные переменные вычисляются на внутреннем шаге моделирования.
  2. •Continuous but fixed in minor time step sample time – Непрерывное модельное время с фиксированным шагом во внутреннем цикле. Задается для S-функций, выходные переменные которых должны изменяться только в соответствии с внешним шагом моделирования, но должны быть неизменными на внутреннем.
  3. Discrete sample time – Дискретное модельное время. Задается для дискретной системы (дискретной части системы). Пользователь должен задать шаг модельного времени sample time и смещение (задержку) offset, чтобы определить моменты времени, в которые Simulink должен вызвать на выполнение данный блок. Величина смещения не может превышать величину шага модельного времени. Время срабатывания блока определяется выражением:
  4. TimeHit = (n * sample_time) + offset ,где n – целое число шагов расчета.Если задано дискретное модельное время, то Simulink обращается к методам mdlUpdate и mdlOutputs на каждом внешнем шаге моделирования.
  5. Variable sample time – Дискретный переменный шаг расчета. Модельное время дискретное, но интервалы времени между срабатываниями блока могут быть разными. В начале каждого шага моделирования S-функция должна определить значение времени следующего срабатывания. Для этого используется mdlGetTimeOfNextVarHit метод.
  6. Inherited sample time – Наследуемый шаг расчета. В некоторых случаях работа блока не зависит от выбора варианта задания шага модельного времени. На пример, для блока Gain не имеет значения, какой шаг модельного времени реализован – блок выполняет усиление входного сигнала для любого варианта sample time. В подобных случаях параметр sample time может быть унаследован от предыдущего или последующего блока, либо от блока, имеющего наименьший шаг расчета.

16.6. Создание S-функций на языке MATLAB

Наиболее простой и быстрый путь создать S-функцию – это написать ее на языке MATLAB с использованием файла-шаблона. И хотя создание S-функций на языке MATLAB имеет некоторые ограничения (например, MATLAB S-функция может иметь только по одному входному и выходному порту, а также передаваемые и принимаемые данные через эти порты могут быть только скалярами и векторами типа double), этот способ является наилучшим с точки зрения изучения механизма работы S-функции.

Ниже приводится шаблон S-функции с авторским переводом комментариев. Оригинальный файл шаблона sfuntmpl.m находится в папке ...\toolbox\simulink\blocks .

Шаблон MATLAB S-функции:

function [sys,x0,str,ts] = sfuntmpl(t,x,u,flag)%% SFUNTMPL - Базовый шаблон для создания MATLAB S-функции.%   С помощью MATLAB S-функции пользователь может задать систему%   обыкновенных дифференциальных уравнений (ODE), уравнения дискретной%   системы, и(или) любой алгоритм, описывающий работу Simulink-блока. %%   Базовая форма синтаксиса S-функции выглядит следующим образом:%       [sys,x0,str,ts] = sfunc(t,x,u,flag,p1,...,pn)%%      Параметры S-функции:%%  t    -   Текущее время%  x    -   Вектор переменных состояния системы%  u    -   Вектор входных сигналов%  flag -   Флаг - целое число, определяющее какая функция внутри S-функции %           выполняется при вызове.%  p1,...,pn - Параметры S-функции, задаваемые в окне диалога%              блока "S-function".%%   Результат, возвращаемый (вычисляемый) S-функцией в момент времени t %   зависит от значения переменной flag, значения вектора состояния системы x%   и текущего значения вектора входного сигнала u.%%   Результаты работы S-функции в зависимости от значения переменной flag% приведены в таблице:%  _________________________________________________________________________% |      |           |                        |                             |% | flag | РЕЗУЛЬТАТ |  ВЫПОЛНяЕМАя ФУНКЦИя   |          ОПИСАНИЕ           |% |      |           |   (сallback-метод)     |                             |% |______|___________|________________________|_____________________________|% |  0   | [sizes,x0,| mdlInitializesizes     |  Инициализация:    Расчет   |% |      |  str,ts]  |                        | начальных условий, значений |% |      |           |                        | вектора модельного времени  |% |      |           |                        | времени, размерности матриц.|% |  1   |    dx     | mdlDerivatives         |  Расчет значений производных|% |      |           |                        | вектора x состояния системы.|% |  2   |    ds     | mdlUpdate              |  Расчет  значений  вектора  |% |      |           |                        | состояний   x   дискретной  | % |      |           |                        | системы: sys = x(n+1).      |% |  3   |    y      | mdlOutputs             |  Расчет значений выходного  |% |      |           |                        | вектора sys .               |% |  4   |   tnext   | mdlGetTimeOfNextVarHit |  Расчет значения времени для|% |      |           |                        | следующей  расчетной  точки |% |      |           |                        | дискретной  части  системы. |% |      |           |                        | Используется  при   расчете |% |      |           |                        | дискретной  или  гибридной  |% |      |           |                        | системы с переменным шагом. |% |  5   |           |                        | Зарезервировано для будущего|% |      |           |                        | использования.              |% |  9   |    []     | mdlTerminate           |  Завершение расчета         |% |______|___________|________________________|_____________________________|%       %%   Параметры блока "S-function"  p1,...,pn передаются в S-функцию при любом% значении переменной flag.%%   При вызове S-функции со значением переменной  flag = 0 ею рассчитываются %   следующие величины:%% sys(1) - Число непрерывных переменных состояния.% sys(2) - Число дискретных  переменных состояния.% sys(3) - Число выходных переменных.% sys(4) - Число входных переменных (размерность вектора u).%          Любой из первых четырех элементов в sys может быть задан %          равным -1 (минус один), что означает динамически задаваемую %          размерность соответствующих переменных. Фактическая размерность%          при вызове S-функции с другими значениями переменной flag%          будет равна размерности входного вектора u.%          Например, при sys(3) = -1, размерность выходного вектора будет %          задана равной размерности входного вектора.% sys(5) - Значение зарезервировано для будущего использования. % sys(6) - Значение, равное 1, соответствует прохождению входного сигнала%          на выход. Значение, равное 0, определяет, что входной сигнал не%          используется для вычисления выходного сигнала в функции%          mdlOutputs, вызываемой при значении переменной flag = 3.% sys(7) - Размерность вектора модельного времени (количество строк в%          матрице ts).%%% x0     - Задание вектора начальных значений переменных состояния.%          Если переменных состояния нет - значение параметра задается %          равным [] .%% str    - Зарезервированный параметр. Значение параметра задается%          равным [] .%% ts     - Матрица, размерностью m-на-2, задающая модельное время%          и смещение (period и offset), где m - число строк в матрице ts. %%     Например:%%     ts = [0   0,      % Шаг модельного времени для непрерывной%                       % части системы.%           0   1,      % Фиксированный шаг расчета для непрерывной%                       %  части системы.%        period offset, % Фиксированный шаг модельного времени для%                       % дискретной части системы,%                       % где - period > 0 & offset < PERIOD.%          -2   0];     % Переменный шаг модельного времени для%                         дискретной части системы. При вызове%                         S-функции со значением переменной flag = 4 %                         выполняется расчет следующей точки по времени.%%        Если в матрице ts заданы несколько значений шага модельного времени,%     то его значения должны располагаться в порядке возрастания.%     В том случае, если задано более одного значения шага требуется проверка%     времени срабатывания блока в явном виде:%        abs(round((T-OFFSET)/PERIOD) - (T-OFFSET)/PERIOD)%     Обычно задаваемая погрешность при проверке равна 1e-8. Она зависит от %     величин шага модельного времени и времени окончания расчета.%     Можно также задать, чтобы значение временного шага передавалось в%     блок "S-function" из предшествующего блока модели. Для функций,%     изменяющихся внутри основного временного шага должно быть задано%     sys(7) = 1 и ts = [-1 0] .%        Для функций, не изменяющихся внутри основного временного шага%     должно быть задано sys(7) = 1 и ts = [-1 1] .%%   Copyright 1990-2001 The MathWorks, Inc. %   $Revision: 1.17 $%   Авторский перевод комментариев: Черных И.В.%%   Нижележащие строки показывают базовую структуру S-функции:%switch flag, % В зависимости от значения переменной flag происходит             % вызов того или иного метода::%===============%% Инициализация %%===============%  case 0,    [sys,x0,str,ts]=mdlInitializeSizes;    %====================%% Расчет производных %%====================%  case 1,    sys=mdlDerivatives(t,x,u);    %============================================================%% Расчет значений вектора состояний дискретной части системы %%============================================================%      case 2,    sys=mdlUpdate(t,x,u);    %=====================================================================%% Расчет значений вектора выходных сигналов непрерывной части системы %%=====================================================================%  case 3,    sys=mdlOutputs(t,x,u);%==================================================================%% Расчет значения времени для следующей расчетной точки дискретной %% части системы                                                    %%==================================================================%  case 4,    sys=mdlGetTimeOfNextVarHit(t,x,u);%====================%% Завершение расчета %%====================%  case 9,    sys=mdlTerminate(t,x,u);%======================================%% Неизвестное значение переменной flag %%======================================%  otherwise    error(['Unhandled flag = ',num2str(flag)]);end% Окончание функции sfuntmpl%===============================================================%% mdlInitializeSizes                                            %% Функция инициализации                                         %% Расчет начальных условий, значений вектора модельного времени,%% размерности матриц                                            %%===============================================================%function [sys,x0,str,ts]=mdlInitializeSizes% Приведенные ниже значения параметров даны в качестве примера и не отражают% реально задаваемых значений.sizes = simsizes; % Первый вызов функции simsizes создает структуру sizessizes.NumContStates  = 0; % Число непрерывных переменных состоянияsizes.NumDiscStates  = 0; % Число дискретных  переменных состоянияsizes.NumOutputs     = 0; % Число выходных переменных (размерность выходного                          % вектора)sizes.NumInputs      = 0; % Число входных переменных (размерность вектора u)sizes.DirFeedthrough = 1; % Параметр, задающий проход входного сигнала на                          % выход.                          % Этот параметр нужно задавать равным 1, в том                          % случае, если входной сигнал прямо или                           % опосредованно(например, через логическое                          % выражение или алгебраическую операцию)                          % проходит на выход системы (иными словами: если                          % входной сигнал u, входит в выражения задаваемые в                          % функции mdlOutputs) или используется метод                          % mdlGetTimeOfNextVarHit.                          % При описании системы в уравнениях пространства                          % состояний этот параметр следует задать равным 1,                          % если матрица D (матрица обхода) не пустая и                          % равным нулю, в противном случае.sizes.NumSampleTimes = 1; % Размерность вектора модельного времени.                          % Минимальное значение параметра = 1                          % (одна строка в матрице ts).sys = simsizes(sizes);    % Второй вызов функции simsizes. Данные о                           % размерностях передаются в Simulink.x0  = [];    % Задание вектора начальных значений переменных состояния              % (начальных условий).str = [];    % Задание параметра str, как пустой матрицы. Параметр             % заразервирован для будущего использования.ts  = [0 0]; % Матрица из двух колонок, задающая шаг модельного времени             % и смещение.% Окончание mdlInitializeSizes %========================================================================%% mdlDerivatives                                                         %% Функция для расчета значений производных вектора состояния непрерывной %% части системы                                                          %%========================================================================%function sys=mdlDerivatives(t,x,u)sys = [];% Окончание mdlDerivatives %==========================================================================% % mdlUpdate %% Функция для расчета значений вектора выходных сигналов непрерывной части % % системы %%==========================================================================% function sys=mdlUpdate(t,x,u)sys = [];% Окончание mdlUpdate%===========================================================================%% mdlOutputs                                                                %% Функция для расчета значений вектора выходных сигналов непрерывной части  %% системы                                                                   %%===========================================================================%function sys=mdlOutputs(t,x,u)sys = [];% Окончание mdlOutputs %===========================================================================%% mdlGetTimeOfNextVarHit                                                    %% Расчет значения времени для следующей расчетной точки дискретной части    %% системы.                                                                  %% Функция рассчитывает время (абсолютное значение), по достижении которого  %% значения дискретной части системы передаютсяв Simulink-модель.            %% Функция используется только в случае моделирования дискретной части       %% системы с переменным шагом (variable discrete-time sample time). В этом   %% случае параметр ts функции mdlInitializeSizes должен быть задан как [-2 0]%                          %===========================================================================%function sys=mdlGetTimeOfNextVarHit(t,x,u)sampleTime = 1;  % Пример: время срабатывания блока увеличивается                 % на 1 секунду.sys = t + sampleTime;% Окончание mdlGetTimeOfNextVarHit%=========================================%% mdlTerminate                            %% Функция, выполняющая завершение расчета %%=========================================%function sys=mdlTerminate(t,x,u)sys = [];% Окончание mdlTerminate

[Скачать пример]

16.7. Примеры S-функций языке MATLAB

16.7.1. Простейшая S-функция

Одним из самых простых примеров S-функций поставляемых с пакетом MATLAB является функция timestwo (файл timestwo.m). Данная S-функция выполняет умножение входного сигнала на коэффициент 2. Ниже приведен текст этой S-функции.

function [sys,x0,str,ts] = timestwo(t,x,u,flag)%%   TIMESTWO - Пример S-функции. Выходной сигнал равен входному,%   умноженному на 2:%      y = 2 * u;%%   Шаблон для создания S-функции - файл sfuntmpl.m .%%   Copyright 1990-2001 The MathWorks, Inc.%   $Revision: 1.6 $%   Авторский перевод комментариев: Черных И.В.%switch flag, % В зависимости от значения переменной flag происходит             % вызов того или иного метода:%===============%% Инициализация %%===============%  case 0    [sys,x0,str,ts]=mdlInitializeSizes;%===========================================%% Расчет значений вектора выходных сигналов %%===========================================%  case 3    sys=mdlOutputs(t,x,u);%=========================================%% Неиcпользуемые значения переменной flag %%=========================================%  % В примере не используются методы для завершения работы S-функции,  % нет непрерывных и дискретных переменных состояния,   % поэтому значения переменной flag = 1, 2, 4, 9 не используются.  % Результатом S-функции в этом случае является пустая матрица.  case { 1, 2, 4, 9 }    sys=[];%======================================%% Неизвестное значение переменной flag %%======================================%otherwise    error(['Unhandled flag = ',num2str(flag)]);end% Окончание функции timestwo%===============================================================%% mdlInitializeSizes                                          %% Функция инициализации                                       %% Расчет начальных условий, значений вектора шагов модельного %% времени, размерности матриц                                 %%=============================================================%%function [sys,x0,str,ts] = mdlInitializeSizes()sizes = simsizes;sizes.NumContStates  = 0;   % Число непрерывных переменных состояния.sizes.NumDiscStates  = 0;   % Число дискретных  переменных состояния.sizes.NumOutputs     = -1;  % Число выходных переменных (размерность выходного вектора).                            % Динамическая размерность выходного вектора.sizes.NumInputs      = -1;  % Число входных переменных (размерность входного                            % вектора).                            % Динамическая размерность входного вектора.sizes.DirFeedthrough = 1;   % Прямой проход. Есть проход входного сигнала                            % на выход.sizes.NumSampleTimes = 1;   % Размерность вектора шагов модельного времени.sys = simsizes(sizes);str = [];                   % Параметр заразервирован для будущего                             % использования.x0  = [];                   % Задание вектора начальных значений переменных                            % состояния.                             % Переменных сомтояния нет, поэтому значение                            % параметра - пустая матрица.ts  = [-1 0];               % Матрица из двух колонок, задающая шаг                             % модельного времени и смещение.                            % Шаг наследуется из предшествуюшего блока.% Окончание mdlInitializeSizes %%========================================================%% mdlOutputs                                             %% Функция для расчета значений вектора выходных сигналов %%========================================================%%function sys = mdlOutputs(t,x,u)sys = u * 2; % Выходной сигнал блока есть входной сигнал, умноженный на             % коэффициент 2.% Окончание mdlOutputs 

Пример модели с S-функцией timestwo приведен на рис.16.4.

Рис. 16.4 Модель с S-функцией timestwo

[Скачать пример]

16.7.2. Модель непрерывной системы

Модель непрерывной системы, описываемой уравнениями пространства состояния дана в файле csfunc.m . Данная S-функция моделирует непрерывную систему с двумя входами, двумя выходами и двумя переменными состояния. Параметры модели (значения матриц A,В,С,D) задаются в теле S-функции и передаются в callback-методы через их заголовки в качестве дополнительных параметров.
Ниже приведен текст этой S-функции.

S-функция csfunc:

function [sys,x0,str,ts] = csfunc(t,x,u,flag)%  CSFUNC Пример S-функции. Спомощью уравнений пространства состояния%  моделируется непрерывная система:%%      x' = Ax + Bu%      y  = Cx + Du%%  Значения матриц передаются в callback-методы через их заголовки%  в качестве дополнительных параметров%   %%   Шаблон для создания S-функции - файл sfuntmpl.m .%  %   Copyright 1990-2001 The MathWorks, Inc.%   $Revision: 1.8 $%   Авторский перевод комментариев: Черных И.В.%   Задание матриц:A=[-0.09   -0.01    1         0];     % Mатрица системы. B=[ 1   -7    0   -2];          % Mатрица входа. C=[ 0    2    1   -5];          % Mатрица выхода. D=[-3    0    1    0];          % Mатрица обхода. switch flag,  % В зависимости от значения переменной flag происходит              % вызов того или иного метода:%===============%% Инициализация %%===============%  case 0,    [sys,x0,str,ts]=mdlInitializeSizes(A,B,C,D);%====================%% Расчет производных %%====================%  case 1,    sys=mdlDerivatives(t,x,u,A,B,C,D);%===========================================%% Расчет значений вектора выходных сигналов %%===========================================%  case 3,    sys=mdlOutputs(t,x,u,A,B,C,D);%=========================================%% Неиcпользуемые значения переменной flag %%=========================================%  % В примере не используются методы для завершения работы S-функции,  % нет дискретных переменных состояния,   % поэтому значения переменной flag = 2, 4, 9 не используются.  % Результатом S-функции в этом случае является пустая матрица.  case { 2, 4, 9 }    sys=[];%======================================%% Неизвестное значение переменной flag %%======================================%  otherwise    error(['Unhandled flag = ',num2str(flag)]);end% Окончание csfunc%%===============================================================%% mdlInitializeSizes                                            %% Функция инициализации                                         %% Расчет начальных условий, значений вектора модельного времени,%% размерности матриц                                            %%===============================================================%%function [sys,x0,str,ts]=mdlInitializeSizes(A,B,C,D)sizes = simsizes;sizes.NumContStates  = 2; % Число непрерывных переменных состояния.sizes.NumDiscStates  = 0; % Число дискретных  переменных состояния.sizes.NumOutputs     = 2; % Число выходных переменных (размерность выходного                          % вектора).sizes.NumInputs      = 2; % Число входных переменных (размерность входного                          % вектора).sizes.DirFeedthrough = 1; % Прямой проход. Есть проход входного сигнала                          % на выход.                          % (матрица D не пустая).sizes.NumSampleTimes = 1; % Размерность вектора шагов модельного времени.sys = simsizes(sizes);x0  = zeros(2,1);         % Задание вектора начальных значений переменных                          % состояния. Начальные условия нулевые.str = [];                 % Параметр заразервирован для будущего                          % использования.ts  = [0 0];              % Матрица из двух колонок, задающая шаг модельного                          % времени и смещение.% Окончание mdlInitializeSizes%%========================================================================%% mdlDerivatives                                                         %% Функция для расчета значений производных вектора состояния непрерывной %% части системы                                                          %%========================================================================%%function sys=mdlDerivatives(t,x,u,A,B,C,D)sys = A*x + B*u;% Окончание mdlDerivatives%%========================================================%% mdlOutputs                                             %% Функция для расчета значений вектора выходных сигналов %%========================================================%function sys=mdlOutputs(t,x,u,A,B,C,D)sys = C*x + D*u;% Окончание mdlOutputs

Пример модели с S-функцией csfunc приведен на рис.16.5.

Рис. 16.5 Модель с S-функцией csfunc

[Скачать пример]

16.7.3. Модель дискретнойной системы

Модель дискретной системы, описываемой уравнениями пространства состояния, дана в файле dsfunc.m . Данная S-функция моделирует дискретную систему с двумя входами, двумя выходами и двумя переменными состояния. Параметры модели (значения матриц A, В, С, D) задаются в теле S-функции и передаются в callback-методы через их заголовки в качестве дополнительных параметров.
Ниже приведен текст этой S-функции.

S-функция dsfunc:

function [sys,x0,str,ts] = dsfunc(t,x,u,flag)%  DSFUNC Пример S-функции. С помощью уравнений пространства состояния%  моделируется дискретная система:%      x(n+1) = Ax(n) + Bu(n)%      y(n)   = Cx(n) + Du(n)%%  Значения матриц передаются в callback-методы через их заголовки%  в качестве дополнительных параметров%%   Шаблон для создания S-функции - файл sfuntmpl.m .%  %   Copyright 1990-2001 The MathWorks, Inc.%   $Revision: 1.8 $%   Авторский перевод комментариев: Черных И.В.%   Задание матриц:A = [0.9135 0.1594    -0.7971 0.5947];   % Матрица системы.B = [0.05189 0     0.4782 0];        % Mатрица входа.C = [0 1     1 0];             % Mатрица выхода. D = [0.01  0     0    -0.02];      % Mатрица обхода.switch flag,    % В зависимости от значения переменной flag происходит                % вызов того или иного метода:%===============%% Инициализация %%===============%  case 0,    [sys,x0,str,ts] = mdlInitializeSizes(A,B,C,D);%============================================================%% Расчет значений вектора состояний дискретной части системы %%============================================================%  case 2,     sys = mdlUpdate(t,x,u,A,B,C,D); %=====================================================================%% Расчет значений вектора выходных сигналов непрерывной части системы %%=====================================================================%  case 3,     sys = mdlOutputs(t,x,u,A,C,D);%=========================================%% Неиспользуемые значения переменной flag %%=========================================%  % В примере не используются методы для завершения работы S-функции,  % нет непрерывных переменных состояния,   % поэтому значения переменной flag = 1, 4, 9 не используются.  % Результатом S-функции в этом случае является пустая матрица.  case { 1, 4, 9 }    sys=[];%======================================%% Неизвестное значение переменной flag %%======================================%  otherwise    error(['unhandled flag = ',num2str(flag)]);end% Окончание dsfunc%%===============================================================%% mdlInitializeSizes                                            %% Функция инициализации                                         %% Расчет начальных условий, значений вектора шагов модельного   %% времени, размерности матриц                                   %%===============================================================%%function [sys,x0,str,ts] = mdlInitializeSizes(A,B,C,D)sizes = simsizes;sizes.NumContStates  = 0;         % Число непрерывных переменных состояния.sizes.NumDiscStates  = size(A,1); % Число дискретных  переменных состояния.sizes.NumOutputs     = size(D,1); % Число выходных переменных (размерность                                  % выходного вектора).sizes.NumInputs      = size(D,2); % Число входных переменных (размерность                                  % входного вектора).sizes.DirFeedthrough = 1;         % Прямой проход. Есть проход входного                                  % сигнала на выход (матрица D не пустая).sizes.NumSampleTimes = 1;         % Размерность вектора  шагов модельного                                  % времени.sys = simsizes(sizes);x0  = zeros(sizes.NumDiscStates,1); % Задание вектора начальных значений                                     % переменных состояния.                                    % Начальные условия нулевые str = [];                           % Параметр заразервирован для будущего                                    % использования.ts  = [0.2 0];                      % Матрица из двух колонок, задающая шаг                                    % модельного времени и смещение.% Окончание mdlInitializeSizes%%=========================================================================%% mdlUpdate                                                               %% Функция для расчета значений вектора состояния дискретной части системы %%=========================================================================%%function sys = mdlUpdate(t,x,u,A,B,C,D)sys = A*x+B*u;% Окончание mdlUpdate%========================================================%% mdlOutputs                                             %% Функция для расчета значений вектора выходных сигналов %%========================================================%%function sys = mdlOutputs(t,x,u,A,C,D)sys = C*x+D*u;% Окончание mdlOutputs

Пример модели с S-функцией dsfunc приведен на рис.16.6.

Рис. 16.6 Модель с S-функцией dsfunc

[Скачать пример]

16.7.4. Модель гибридной системы

Модель гибридной системы (комбинации непрерывной и дискретной системы) дана в файле mixedm.m . Рассматриваемая S-функция моделирует систему, состоящую из последовательно включенных интегратора (1/s) и блока задержки (1/z). Особенность S-функции для гибридной системы в том, что вызов callback-методов для расчета дискретной части системы выполняется в те же моменты времени, что и для непрерывной ее части, поэтому пользователь, при написании S-функции, должен предусмотреть проверку правильности вызова callback-методов рассчитывающих дискретную часть системы.
Ниже приведен текст этой S-функции.

S-функция dsfunc:

function [sys,x0,str,ts] = mixedm(t,x,u,flag)% MIXEDM Пример S-функции. S-функция моделирует систему, состоящую из% последовательно включенных интегратора (1/s) и блока задержки (1/z).%%   Шаблон для создания S-функции - файл sfuntmpl.m .%%   Copyright 1990-2001 The MathWorks, Inc.%   $Revision: 1.27 $%   Авторский перевод комментариев: Черных И.В.% Шаг модельного времени и смещение для дискретной части системы: dperiod = 1; doffset = 0;switch flag     % В зависимости от значения переменной flag происходит                % вызов того или иного метода:%===============%% Инициализация %%===============%  case 0             [sys,x0,str,ts]=mdlInitializeSizes(dperiod,doffset);%====================%% Расчет производных %%====================%  case 1    sys=mdlDerivatives(t,x,u);%============================================================%% Расчет значений вектора состояний дискретной части системы %%============================================================%   case 2,    sys=mdlUpdate(t,x,u,dperiod,doffset);  %===========================================%% Расчет значений вектора выходных сигналов %%===========================================%  case 3            sys=mdlOutputs(t,x,u,doffset,dperiod);  %====================%% Завершение расчета %%====================%  case 9    sys = [];%======================================%% Неизвестное значение переменной flag %%======================================%  otherwise    error(['unhandled flag = ',num2str(flag)]);  end% Окончание mixedm%===============================================================%% mdlInitializeSizes                                            %% Функция инициализации                                         %% Расчет начальных условий, значений вектора модельного времени,%% размерности матриц                                            %%===============================================================%function [sys,x0,str,ts]=mdlInitializeSizes(dperiod,doffset)sizes = simsizes;sizes.NumContStates  = 1;  % Число непрерывных переменных состояния.sizes.NumDiscStates  = 1;  % Число дискретных  переменных состояния.sizes.NumOutputs     = 1;  % Число выходных переменных (размерность выходного                           % вектора).sizes.NumInputs      = 1;  % Число входных переменных (размерность входного                           % вектора).sizes.DirFeedthrough = 0;  % Прямой проход. Прохода входного сигнала на выход                           % нет.sizes.NumSampleTimes = 2;  % Размерность вектора  шагов модельного времени.                           % Шаги модельного времени задаются для непрерывной                           % и для дискретной частей системы.sys = simsizes(sizes);x0  = zeros(2,1);          % Задание вектора начальных значений переменных                           % состояния.                           % Начальные условия нулевые  str = [];                  % Параметр заразервирован для будущего                            % использования.ts  = [0 0];               % Шаг модельного времени для непрерывной части                           % системы.       dperiod doffset];   % Шаг модельного времени для дискретной части                           % системы.% Окончание mdlInitializeSizes%%========================================================================%% mdlDerivatives                                                         %% Функция для расчета значений производных вектора состояния непрерывной %% части системы                                                          %%========================================================================%function sys=mdlDerivatives(t,x,u)sys = u; % Окончание mdlDerivatives%=========================================================================%% mdlUpdate                                                               %% Функция для расчета значений вектора состояния дискретной части системы %%=========================================================================%%function sys=mdlUpdate(t,x,u,dperiod,doffset)% Расчет значения переменной состояния дискретной части системы% выполняется в соостветствии с дискретным шагом расчета% (погрешность по времени выбрана равной 1e-15).if abs(round((t - doffset)/dperiod) - (t - doffset)/dperiod) < 1e-15  sys = x(1);else  sys = [];end% Окончание mdlUpdate%%========================================================% % mdlOutputs                                             %% Функция для расчета значений вектора выходных сигналов %%========================================================% %function sys=mdlOutputs(t,x,u,doffset,dperiod)% Расчет значения выходного сигнала системы% выполняется в соостветствии с дискретным шагом расчета% (погрешность по времени выбрана равной 1e-15).% Если условие, заданное оператором if истинно, то выходной сигнал блока% изменяется. В противном случае выходной сигнал остается равным значению% на предыдущем шаге.%if abs(round((t - doffset)/dperiod) - (t - doffset)/dperiod) < 1e-15  sys = x(2);else   sys = [];end% Окончание mdlOutputs

Пример модели с S-функцией mixedm приведен на рис.16.7.

Рис. 16.7 Модель с S-функцией mixedm

[Скачать пример]

16.7.5 Модель дискретной системы с переменным шагом расчета

Модель дискретной системы с переменным шагом расчета дана в файле vsfunc.m. Рассматриваемая S-функция моделирует устройство задержки сигнала. Время задержки определяется величиной входного сигнала. Для вычисления момента времени срабатывания блока используется callback-метод mdlGetTimeOfNextVarHit, вызываемый при значении переменой flag = 4. Поскольку время срабатывания блока зависит от входного сигнала, то параметр DirFeedthrough должен иметь значение равное 1. В целом, любой блок, в котором время срабатывания вычисляется по величине входного сигнала, должен иметь DirFeedthrough = 1.

Ниже приведен текст этой S-функции.

S-функция dsfunc:

function [sys,x0,str,ts] = vsfunc(t,x,u,flag)
% VSFUNC Пример S-функции. S-функциЯ моделирует систему, с переменным шагом
% расчета (устройство задержки сигнала).
% ВремЯ задержки определЯетсЯ величиной сигнала. поступающего на второй вход:
%
%     dt      = u(2)
%     y(t+dt) = u(t)
%
%   Смотри также SFUNTMPL, CSFUNC, DSFUNC.

%   Copyright 1990-2001 The MathWorks, Inc.
%   $Revision: 1.9 $
%   Авторский перевод комментариев: Черных И.В.
%
%
switch flag,    % В зависимости от значениЯ переменной flag происходит
                % вызов того или иного метода:


%===============%
% ИнициализациЯ %
%===============%
  case 0,
    [sys,x0,str,ts]=mdlInitializeSizes;

%============================================================%
% Расчет значений вектора состоЯний дискретной части системы %
%============================================================% 
  case 2,
    sys=mdlUpdate(t,x,u);

%===========================================%
% Расчет значений вектора выходных сигналов %
%===========================================%
  case 3,
    sys=mdlOutputs(t,x,u);

%==================================================================%
% Расчет значениЯ времени длЯ следующей расчетной точки дискретной %
% части системы                                                    %
%==================================================================%
  case 4,
    sys=mdlGetTimeOfNextVarHit(t,x,u);

%====================%
% Завершение расчета %
%====================%
  case 9,
    sys=mdlTerminate(t,x,u);
  
%=========================================%
% Неиcпользуемые значениЯ переменной flag %
%=========================================%

  % В примере нет непрерывных переменных состоЯниЯ, 
  % поэтому значение переменной flag = 1 не используетсЯ.
  % Результатом S-функции в этом случае ЯвлЯетсЯ пустаЯ матрица.
  case 1,
    sys = [];

%======================================%
% Неизвестное значение переменной flag %
%======================================%
  otherwise
    error(['Unhandled flag = ',num2str(flag)]);

end

% Окончание vsfunc

%
%===============================================================%
% mdlInitializeSizes                                            %
% ФункциЯ инициализации                                         %
% Расчет начальных условий, значений вектора шагов модельного   %
% времени, размерности матриц                                   %
%===============================================================%
%
function [sys,x0,str,ts]=mdlInitializeSizes
%
sizes = simsizes;

sizes.NumContStates  = 0;  % Число непрерывных переменных состоЯниЯ.
sizes.NumDiscStates  = 1;  % Число дискретных  переменных состоЯниЯ.
sizes.NumOutputs     = 1;  % Число выходных переменных (размерность выходного
%                            вектора).
sizes.NumInputs      = 2;  % Число входных переменных (размерность входного
                           % вектора).
sizes.DirFeedthrough = 1;  % ПрЯмой проход. Входной сигал используетсЯ
                           % в методе mdlGetTimeOfNextVarHit .
sizes.NumSampleTimes = 1;  % Размерность вектора  шагов модельного времени.

sys = simsizes(sizes);

x0  = [0];                 % Задание вектора начальных значений переменных
                           % состоЯниЯ.
                           % Начальные условиЯ нулевые.
str = [];                  % Параметр заразервирован длЯ будущего
                           % использованиЯ. 

ts  = [-2 0];              % Переменный шаг модельного времени длЯ дискретной
                           % части системы. При вызове S-функции со значением 
                           % переменной flag = 4 выполнЯетсЯ расчет следующей 
                           % точки по времени.

% Окончание mdlInitializeSizes

%
%=========================================================================%
% mdlUpdate                                                               %
% ФункциЯ длЯ расчета значений вектора состоЯниЯ дискретной части системы %
%=========================================================================%
%
function sys=mdlUpdate(t,x,u)

sys = u(1);

% Окончание mdlUpdate

%
%========================================================% 
% mdlOutputs                                             %
% ФункциЯ длЯ расчета значений вектора выходных сигналов %
%========================================================% 
%
function sys=mdlOutputs(t,x,u)

sys = x(1);

% Окончание mdlOutputs

%
%===========================================================================%
% mdlGetTimeOfNextVarHit                                                    %
% Расчет значениЯ времени длЯ следующей расчетной точки дискретной части    %
% системы.                                                                  %
% ФункциЯ рассчитывает времЯ (абсолютное значение), по достижении которого  %
% значениЯ дискретной части системы передаютсЯв Simulink-модель.            %
% ФункциЯ используетсЯ только в случае моделированиЯ дискретной части       %
% системы с переменным шагом (variable discrete-time sample time). В этом   %
% случае параметр ts функции mdlInitializeSizes должен быть задан как [-2 0]%
%===========================================================================%
%
function sys=mdlGetTimeOfNextVarHit(t,x,u)

sys = t + u(2);

% Окончание mdlGetTimeOfNextVarHit

%
%=========================================%
% mdlTerminate                            %
% ФункциЯ, выполнЯющаЯ завершение расчета %
%=========================================%
%
function sys=mdlTerminate(t,x,u)

sys = [];

% Окончание mdlTerminate

Пример модели с S-функцией vsfunc приведен на рис.16.8. В примере время задержки сигнала увеличивается с 0.0005 с до 0.0015 с.


Рис. 16.8 Модель с S-функцией vsfunc

[Скачать пример]

16.7.6 Непрерывная модель электродвигателя постоянного тока независимого возбуждения

В данном параграфе на примере двигателя постоянного тока независимого возбуждения (ДПТ НВ) рассмотрим создание S-функции для модели реального объекта.

16.7.6.1 Математическое описание ДПТ НВ

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

(1)
(2)
(3)
(4)

где

u - напряжение на якорной обмотке двигателя,e - электродвижущая сила (ЭДС) якоря,i - ток якоря,Ф - поток, создаваемый обмоткой возбуждения,M - электромагнитный момент двигателя,MС - момент сопротивления движению,   - скорость вращения вала двигателя,R - активное сопротивление якорной цепи,L - индуктивность якорной цепи,J - суммарный момент инерции якоря и нагрузки,С  - коэффициент связи между скоростью и ЭДС,СМ - коэффициент связи между током якоря и электромагнитным моментом.
Рис. 16.9 Двигатель постоянного тока с независимым возбуждением.

С точки зрения будущей модели, входными воздействиями являются напряжения якоря u и момент сопротивления движению MС , выходными переменными - электромагнитный момент двигателя M и скорость вращения вала двигателя , а переменными состояния - переменные стоящие под знаком производной: ток якоря i и скорость вращения вала двигателя . Остальные переменные, входящие в состав уравнений (1) - (4) являются параметрами, численные значения которых, необходимо будет задавать при проведении расчетов.

Преобразуем дифференциальные уравнения (1) и (2) к явной форме Коши и выполним подстановку. Система уравнений примет вид:

(5)
(6)
(7)
(8)

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

 Введем "машинные" переменные. Входные переменные:   ,  .  .  Выходные переменные:   ,  . ,  Переменные состояния:   ,   . 

Тогда уравнения (5) - (8) примут вид:

(9)
(10)
(11)
(12)

Перепишем систему уравнений в матричной форме:

(13)
(14)

где

, , .

Отметим, что в получившейся системе уравнений входные переменные не участвуют в формировании выходных переменных (матрица обхода D - отсутствует) и, следовательно, параметр sizes.DirFeedthrough, определяемый при инициализации S-функции должен быть задан равным нулю.

16.7.6.2 Пример S-функции для ДПТ НВ

Для создания S-функции для ДПТ НВ за основу взят файл примера модели непрерывной системы csfunc.m . Принципиальные отличия нового файла от образца сводятся к следующему:

  1. Для расчета матриц уравнений пространства состояния A, В и С используются параметры передаваемые в S-функцию через окно диалога блока S-function. Эти параметры (L,R,J,Cm,Cw,Fi) записываются в конце списка параметров в заголовке S-функции :function [sys,x0,str,ts] = dpt_sfunc_1(t,x,u,flag,L,R,J,Cm,Cw,Fi)
  2. Для исключения одинаковых (повторяющихся) вычислений расчет матриц A, В и С выполняется в методе mdlInitializeSizes. Для этого параметры блока (L,R,J,Cm,Cw,Fi) передаются в метод mdlInitializeSizes через его заголовок:[sys,x0,str,ts] = mdlInitializeSizes(L,R,J,Cm,Cw,Fi)Поскольку инициализация модели происходит лишь один раз, то и расчет матриц A, В и С будет выполнен также один раз, что значительно повысит скорость моделирования.
  3. Передача рассчитанных в mdlInitializeSizes матриц выполняется с помощью глобальных переменных. Для этого объявления вида:global A B C;выполнены в теле S-функции, методе mdlInitializeSizes (где выполняется расчет этих матриц), а также методах mdlDerivatives и mdlOutputs (где эти матрицы используются для расчетов).
  4. Поскольку в уравнения пространства-состояния матрица D отсутствует (входные переменные не участвуют в формировании выходных переменных), то параметр sizes.DirFeedthrough в методе mdlInitializeSizes задан равным нулю.

Ниже приводится текст S-функции dpt_sfunc_1 (файл dpt_sfunc_1.m):

function [sys,x0,str,ts] = dpt_sfunc_1(t,x,u,flag,L,R,J,Cm,Cw,Fi)% DPT_SFUNC_1 Пример S-функции для моделирования двигателя постоянного тока% независимого возбуждения.%% В примере выполняется моделирование с помощью уравнений% пространства-состояния:%      x' = Ax + Bu%      y  = Cx + Du%%   Copyright 2002, Chernykh ILya%   $Revision: 1.8%   Автор: Черных И.В.%%      Параметры S-функции, передаваемые через окно диалога блока S-function:%%        L - Индуктивность цепи якоря %        R - Активное сопротивление цепи якоря %        J - Момент инерции%        Cm - Коэффициент связи между моментом и током%        Cw - Коэффициент связи между потоком и скоростью вращения вала%        Fi - Поток, создаваемый обмоткой возбуждения%global A B C;   % Объявление глобальными переменных, необходимых для                % расчетов внутри функций mdlDerivatives и mdlOutputs .                % Сами матрицы расчитываются в методе mdlInitializeSizes .switch flag,    % В зависимости от значения переменной flag происходит                % вызов того или иного метода:%===============%% Инициализация %%===============%  case 0,    [sys,x0,str,ts]=mdlInitializeSizes(L,R,J,Cm,Cw,Fi);%====================%% Расчет производных %%====================%  case 1,    sys=mdlDerivatives(t,x,u);%===========================================%% Расчет значений вектора выходных сигналов %%===========================================%  case 3,    sys=mdlOutputs(t,x,u);%=========================================%% Неиcпользуемые значения переменной flag %%=========================================%  case { 2, 4, 9 },    sys = [];%======================================%% Неизвестное значение переменной flag %%======================================%     otherwise    error(['Unhandled flag = ',num2str(flag)]);end% Окончание dpt_sfunc_1%===============================================================%% mdlInitializeSizes                                            %% Функция инициализации                                         %% Расчет начальных условий, значений вектора шагов модельного   %% времени,размерности матриц                                    %%===============================================================%function [sys,x0,str,ts]=mdlInitializeSizes(L,R,J,Cm,Cw,Fi)sizes = simsizes;sizes.NumContStates = 2;  % Число непрерывных переменных состояния                          % В данном случае этот параметр равен 2                          % (ток якоря и скорость вращения вала).sizes.NumDiscStates = 0;  % Число дискретных  переменных состояния                          % В данном случае этот параметр равен 0,                          % поскольку модель непрерывная.sizes.NumOutputs = 2;     % Число выходных переменных (размерность выходного                          % вектора). В данном случае этот параметр равен 2                          % (скорость вращения и момент на валу).sizes.NumInputs = 2;      % Число входных переменных (размерность входного                          % вектора). В данном случае этот параметр равен 2                          % (напряжение на обмотке якоря и момент                          % сопротивления).sizes.DirFeedthrough = 0; % Прямой проход. Значение параметра равно нулю,                          % поскольку матрица обхода D - отсутствует (входные                          % переменные не участвуют в формировании выходных                          % переменных).sizes.NumSampleTimes = 1; % Размерность вектора модельного времени.sys = simsizes(sizes);x0  = zeros(2,1);         % Задание вектора начальных значений переменных                          % состояния. Начальные условия нулевые.str = [];                 % Зарезервированный параметрts  = [0 0];              % Матрица из двух колонок, задающая шаг модельного                          % времени и смещение.% Далее в функцию mdlInitializeSizes добавлены операторы для% вычисления матриц A, B и C уравнений пространства состояния% модели двигателя постоянного токаglobal A B C;          % Объявление глобальными переменных, необходимых для                       % расчетов внутри функций mdlDerivatives и mdlOutputs.% Расчет матриц А,В и С:%A=[-R/L     -Cw*Fi/L   Cm*Fi/J      0   ];%B=[1/L    0    0   -1/J];%C=[Cm*Fi  0     0    1];% Окончание mdlInitializeSizes %========================================================================%% mdlDerivatives                                                         %% Функция для расчета значений производных вектора состояния непрерывной %% части системы                                                          %%========================================================================%function sys=mdlDerivatives(t,x,u)%global A B;        % Объявление глобальными переменных, необходимых для                   % расчетов внутри метода.sys = A*x + B*u;% Окончание mdlDerivatives %========================================================% % mdlOutputs                                             %% Функция для расчета значений вектора выходных сигналов %%========================================================%function sys=mdlOutputs(t,x,u)global C;        % Объявление глобальными переменных, необходимых для                 % расчетов внутри метода.sys = C*x;% Окончание mdlOutputs

На рис.16.10 показаны модели двигателя постоянного тока на базе S-функции и с использованием стандартных блоков. Результаты расчета для обеих моделей идентичны. Окно диалога блока S-function изображено на рис. 16.11.

Рис. 16.10 Модели ДПТ НВ

Рис. 16.11 Окно диалога блока S-function

[Скачать пример]

16.8. Создание S-функций на языке C с помощью S-Function Builder

Инструментарий Simulink предоставляет пользователю два способа создания S-функций на языке C: с помощью автоматического построителя S-Function Builder и вручную, с использованием шаблона (аналогично созданию S-функций на языке MATLAB). И хотя наибольшими возможностями обладает именно второй способ, первый способ прост и наименее трудоемок, и, поэтому именно с помощью S-Function Builder пользователь может легко и быстро создать нужную ему S-функцию. При этом как во втором, так и в первом случаях S-функция будет создана в виде исполняемого dll-файла, что обеспечивает повышенное быстродействие этой функции.

Создание S-функции рассмотрим на примере двигателя постоянного тока независимого возбуждения. Его математическое описание дано в п. 16.7.6.1. Поскольку в стандарте языка C отсутствуют матричные операции, то уравнения (9) - (12) перепишем в обычной форме:

(15)
(16)
(17)
(18)

Значения элементов матриц даны в п. 16.7.6.1.

S-Function Builder оформлен в виде обычного блока Simulink и находится в библиотеке Function&Tables (функции и таблицы). Пиктограмма блока показана на рис.16.12.


Рис. 16.12 Пиктограмма блока S-Function Builder

Двойной щелчок на пиктограмме открывает окно S-Function Builder. Окно S-Function Builder (см. рис. 16.13) содержит панельпараметров (Parameters),в которой находится графа для ввода имени S-функции (S-function name) и графа для ввода начальныхзначений параметров, передаваемых через окно диалога блока S-function (S-function parameters). Также на этой панелинаходится кнопка Build,предназначенная для запуска процесса компиляции S-функции. В нижней части окна S-Function Builder находятся кнопки Help (вызов справки) и Close/Cancel (закрыть окно).

Среднюю часть окна занимают шестьвкладок, предназначенных для задания свойств S-функции

и фрагментов ее кода:

1. Initialization - Инициализация. На вкладке Initialization задаются следующие свойства S-функции:

  • Input port width - Число входных переменных (размерностьвходного вектора).

  • Output port width - Число выходных переменных(размерность выходного вектора).

  • Number of parameters - Количество параметров,передаваемых в S-функцию через окно диалога блока.

  • Sample time - Шаг модельного времени. Может принимать значения (изсписка): Inherited - наследуемый, Continuous - непрерывный, Discrete- дискретный.

  • Discrete sample time value - Шаг модельного времени длядискретной системы. Параметр доступен для ввода значения, если выбрандискретный шаг расчета.

  • Number of discrete states - Число дискретныхпеременных состояния.

  • Discrete states IC - Начальные значения дискретных переменных состояния. Значения вводятся через запятую.

  • Number of continuous states -Число непрерывныхпеременных состояния.

  • Continuous states IC - Начальные значения непрерывных переменных состояния. Значения вводятся череззапятую.

Окно S-Function Builder с открытой вкладкой Ininializationпоказано на рис.16.13. Для рассматриваемого примера число входных переменных равно двум (напряжение наобмотке якоря и момент сопротивления). Число выходных переменных равно двум(момент и скорость). Количество переменных состояния также равно двум (токякоря и скорость). Число параметров S-функции, передаваемых через окнодиалога равно 6 (см. п. 16.7.6.2), шаг модельного времени -наследуемый, число дискретных переменных состояния - 0, начальныезначения дискретных и непрерывных переменных состояния нулевые.


Рис. 16.13 Окно S-Function Builder (вкладка Ininialization)

2. Libraries - Библиотеки. На вкладке имеется три окна для ввода фрагментов С-кода:

  • Library/Object/Source files - Имена подключаемых библиотечных(*.lib) иобъектных (*.obj) файлов. Указанные файлы должны находиться в текущей рабочей папке, либоследует полностью указать путь к этим файлам. Имена файлов указываются поодному в каждой строке.

  • Includes - Директивы для подключения заголовочных (*.h) и обычных (*.с, *.сpp) файлов. Например:
    # include <math.h>
    # include "myutils.c"
    и т.п.
    В данном окне следует записать файлы, содержащие функциипользователя, которые будут использоваться в проекте.

  • External Function Declarations - Объявления внешних функций, еслиони отсутствуют в заголовочных или иных подключаемых файлах. Например:
    extern double func(double a);

Окно S-Function Builder с открытой вкладкой Librariesпоказано на рис. 16.14.


Рис. 16.14 Окно S-Function Builder (вкладка Libraries)

3. Outputs - Выходы. Вкладка содержит текстовое окно,предназначенное для ввода выражений расчета выходных переменных. В расчетныхвыражениях можно использовать следующие переменные (не объявляя их специально):

  • u0[0], u0[1], u0[2] … u1[0], u1[1], u1[2]… и т.д. - Входные сигналы блока S-function. Входные сигналы должны бытьдействительными и иметь тип double.

  • y[0], y[1], y[2] и т.д. - Выходные сигналы блокаS-function. Выходные сигналы должны бытьдействительными и иметь тип double.

  • param1[0], param2[0], param3[0] и т.д. - Параметры блока S-function, передаваемые через окнодиалога. Параметры быть действительными и иметь тип double.

  • p_width0, p_width1, p_width2 - и т.д. Переменные целоготипа, значения которых равны размерности нулевого, первого, второго и т.д.параметров блока S-function, передаваемых через окнодиалога.

  • u _ width -Фактическая размерность входного сигнала (переменная целого типа). Переменнаядоступна, если размерность входного сигнала на вкладке Initialization задана равной -1 (минусодин). Если входной сигнал матрица - значением переменной u _ width будет вектор из двух элементов.

  • y _ width - Фактическаяразмерность выходного сигнала (переменная целого типа). Переменная доступна,если размерность выходного сигнала на вкладке Initialization задана равной -1 (минусодин). Если выходной сигнал матрица - значением переменной y _ width будет вектор из двух элементов.

  • xC[0], xC[1], xC[2] и т.д. - Непрерывные переменныесостояния. Тип переменных - double.

  • xD[0], xD[1], xD[2] и т.д. - Дискретные переменныесостояния. Тип переменных - double.

На вкладке имеется флажок для установки параметра Inputs are needed in the output function ( direct feedthrough )- использование входных сигналов длярасчета выходных (прямой проход).

Текст автоматически генерируемого метода mdl Outputs , приведен ниже:

void sfun_Outputs_wrapper(const real_T *u,real_T *y,const real_T *xD, /* optional */const real_T *xC, /* optional */const real_T *param0, /* optional */int_T p_width0 /* optional */real_T *param1 /* optional */int_t p_width1 /* optional */int_T y_width, /* optional */int_T u_width) /* optional */{/* Место для ввода расчетного кода */} ,

где sfun - имя S -функции.

Окно S-Function Builder с открытой вкладкой Outputs показано на рис. 16.15.


Рис. 16.15 Окно S-Function Builder (вкладка Outputs)

В примере на рис. 16.15 в первойстроке объявляются переменные - параметры электродвигателя, и этим переменнымприсваиваются значения параметров передаваемых в S-функцию через окно диалога. Во второйстроке объявляются и вычисляются переменные COO и С11, входящие вуравнения (17), (18). В третьей и четвертой строках записаны выражения длярасчета выходных сигналов в соответствии с уравнениями (17) и (18). Параметр Inputs are needed in the output function ( direct feedthrough ) не установлен, поскольку ввыражениях для расчета выходных сигналов отсутствуют входные. После генерации С-кодав тексте S-функциипоявится код, введенный в окне вкладки Outputs.

4. ContinuousDerivatives - Производные непрерывныхпеременных состояния. Вкладка содержит текстовое окно, предназначенное для ввода выраженийрасчета производных непрерывных переменных состояния. В расчетных выраженияхможно использовать те же переменные, что и на вкладке Outputs, за исключением дискретныхпеременных состояния xD. Сами производные обозначаются как dx[0], dx[1], dx[2] и т.п.

Текст автоматически генерируемого метода mdlDerivatives ,приведен ниже:

void sfun_Derivatives_wrapper(const real_T *u,const real_T *y,real_T *dx,real_T *xC,const real_T *param0, /* optional */int_T p_width0, /* optional */real_T *param1,/* optional */int_T p_width1, /* optional */int_T y_width, /* optional */int_T u_width) /* optional */{/* Место для ввода расчетного кода */}

Окно S-Function Builder с открытой вкладкой Continuous Derivatives показано на рис. 16.15.

 


Рис. 16.16 Окно S-FunctionBuilder (вкладка ContinuousDerivatives)

В примере на рис. 16.16 в первыхдвух строках объявляются переменные - параметры электродвигателя, и этимпеременным присваиваются значения параметров передаваемых в S-функцию через окно диалога. В следующихдвух строках объявляются и вычисляются переменные AOO B11, входящие в уравнения (15),(16). В последних двух строках записаны выражения для расчета производныхнепрерывных переменных состояния в соответствии с уравнениями (15) и (16).

5. DiscreteUpdate - Расчет дискретных переменныхсостояния. В текстовом окне вкладки записываются выражения для расчетадискретных переменных состояния. В расчетных выражениях можно использовать те жепеременные, что и на вкладке Outputs, заисключением непрерывных переменных состояния xС. Сами дискретные переменныесостояния обозначаются как xD[0], xD [1], xD [2] и т.п.

Текст автоматически генерируемо метода mdlUpdate , приведенниже:

void sfun_Update_wrapper(const real_T *u,const real_T *y,real_T *xD,const real_T *param0, /* optional */int_T p_width0, /* optional */real_T *param1,/* optional */int_T p_width1, /* optional */int_T y_width, /* optional */int_T u_width) /* optional */{/* Место для ввода расчетного кода */}

Окно S-Function Builder с открытой вкладкой Discrete Update показано на рис. 16.17.


Рис. 16.17 Окно S-FunctionBuilder (вкладка Discrete Update).

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

6. Build Info -Информация о компоновке.На вкладке в окне Compilation diagnostics (диагностические сообщения о ходе компиляции) отображаетсяинформацию о процессе компоновки S-функции.

На вкладке Build Info с помощью флажков можно установить следующиепараметры:

  • Show compile steps - Отображать стадии компиляции. При установленном флажкев окне Compilation diagnostics будутотображены все сообщения компилятора о процессе компиляции. Данный параметржелательно устанавливать при сборке S -функции, использующей внешние функции.

  • Create a debuggable MEX- file - Создаватьотлаживаемый исполняемый файл. При установленном флажке в процессе компиляциибудет создан файл, позволяющий выполнять отладку Simulink -модели.

  • Generate wrapper TLC - Создавать TLC- файл . Флажокустанавливается, если предполагается использовать ускоренный режим расчетов или Realtime Workshop .

  • Save code only - Создавать только текстовый код. Если флажокустановлен, то будут созданы только текстовые файлы на языке С.

Передначалом компиляции необходимо выбрать (настроить) компилятор. Для этого вкомандном окне MATLAB следует ввести команду:

mex - setup

идалее следовать диалогу с компилятором. С программой MATLAB поставляется компилятор Lcc . Ниже приводится примертакого диалога:

Please choose your compiler for building external interface(MEX) files:

Would you like mex to locate installed compilers[y]/n? n - Ответпользователя

Select a compiler: [1] Borland C++Builder version 5.0 [2] Borland C++Builder version 4.0 [3] Borland C++Builder version 3.0 [4] Borland C/C++ version 5.02 [5] Borland C/C++ version 5.0 [6] Borland C/C++ (free command line tools) version 5.5 [7] Compaq Visual Fortran version 6.1 [8] Compaq Visual Fortran version 6.5 [9] Digital Visual Fortran version 6.0 [10] Digital Visual Fortran version 5.0 [11] Lcc C version 2.4 [12] Microsoft Visual C/C++ version 6.0 [13] Microsoft Visual C/C++ version 5.0 [14] WATCOM C/C++ version 11 [15] WATCOM C/C++ version 10.6 

[0] None

Compiler: 11 - Ответ пользователя

Your machine has a Lcc C compiler located at

C:\MATLAB6\sys\lcc. Do you want to use this compiler[y]/n? y - Ответпользователя

Please verify your choices:

Compiler: Lcc C 2.4

Location: C:\MATLAB6\sys\lcc

Are these correct?([y]/n): y - Ответ пользователя

The default options file:

"C:\Documents andSettings\Администратор\Application Data\MathWorks\MATLAB\R12\mexopts.bat"

is being updated fromC:\MATLAB6\BIN\WIN32\mexopts\lccopts.bat...

 

Процесскомпиляции начинается после нажатия на кнопку Build . Об успешном завершениипроцесса компиляции свидетельствует сообщение вида:

### S-function 'DPT_Sfunc_1_C.dll' created successfully . По завершении процесса компиляции в рабочей папкебудут созданы текстовые файлы с названиями вида:

sfun_C.c , sfun_wrapper.c и sfun.dll> . Последний являетсяисполняемым файлом. В файле sfun_ C. c находитсятекст S-функции , ав файле sfun_ wrapper. c - методы,сгенерированные S-Function Builder .

Окно S-Function Builder с открытой вкладкой Build Info показано на рис. 16.18.


Рис. 16.18 Окно S-FunctionBuilder (вкладка Build Info).

Результаты расчетов, выполненных сиспользованием созданной таким образом S-функции, полностью совпадают срезультатами, приведенными в п.  16.7.6.2. Скорость расчета модели с использованием S-функции, написанной на языке C в несколько раз выше, чем прииспользовании языка MATLAB.

[Скачать пример]

16.9. Модернизация S-функций, созданных с помощью S-Function Builder

S-функции, созданные с помощью S-Function Builder обладают одним существенным недостатком. В большинстве случаев при расчете переменных состояния, выходных сигналов либо производных непрерывных переменных состояния должны использоваться некоторые ранее вычисленные константы. В задаче моделирования двигателя постоянного тока - это элементы матриц A, B, С уравнений пространства-состояния, рассчитываемые через параметры двигателя (сопротивление, индуктивность и т.п.). В примере на языке MATLAB (см. п. 16.7.6) расчет матриц выполняется в методе mdlInitializeSizes, благодаря чему этот расчет производится только один раз - на этапе инициализации модели. Далее рассчитанные матрицы только используются для вычисления производных переменных состояния в методе mdlDerivatives и выходных сигналов в методе mdlOutputs. Такая компоновка S-функции обеспечивает наибольшую скорость вычислений. К сожалению, в S-Function Builder отсутствует возможность ввести фрагмент кода на вкладке Initialization, а также скрыты заголовки методов, что делает невозможным добавление новых параметров, которые могли бы передаваться в эти методы. Такая ситуация приводит к тому, что константы, которые можно было бы вычислить всего один раз и, затем лишь использовать, вычисляются вновь и вновь на каждом шаге расчета (в примере с двигателем постоянного тока п.16.6 - это A00, A01, B00 и т.д.). И, если в относительно простых моделях с эти еще можно смириться, то для сложных моделей с большим объемом предварительных вычислений такая ситуация приведет к существенному замедлению процесса расчета.

Выходом из сложившейся ситуации может явиться редактирование автоматически сгенерированного кода S-функции. Редактирование должно обеспечить вычисление констант один раз на этапе инициализации и передачу их в нужные методы. В рассматриваемом примере модели двигателя постоянного тока на этапе инициализации должны вычисляться константы A00, A01, B00 и т.д., а затем, передаваться в методы для расчета производных и выходных переменных. Для реализации поставленной задачи следует проанализировать полученные с помощью S-Function Builder файлы DPT_Sfunc_1_C.c и DPT_Sfunc_1_C_wrapper.c. Первый файл содержит исходный текст S-функции, а второй текст методов этой S-функции.

Текст файла DPT_Sfunc_1_C.c приведен ниже:

/* * File: DPT_Sfunc_1_C.c * * * *   --- THIS FILE GENERATED BY S-FUNCTION BUILDER: BASIC, 1.0 --- * *   This file is an S-function produced by the Basic S-Function *   Builder which only recognizes certain fields.  Changes made *   outside these fields will be lost the next time the block is *   used to load, edit, and resave this file. This file will be overwritten *   by the S-function Builder block. If you want to edit this file by hand,  *   you must change it only in the area defined as:   * *        %%%-SFUNWIZ_defines_Changes_BEGIN *        #define NAME 'replacement text'  *        %%% SFUNWIZ_defines_Changes_END * *   DO NOT change NAME--Change te 'replacement text' only. * *   For better compatibility with the Real-Time Workshop, the *   "wrapper" S-function technique is used.  This is discussed *   in the Real-Time Workshop User's Manual in the Chapter titled, *   "Wrapper S-functions". * *  ------------------------------------------------------------------------ *| See matlabroot/simulink/src/sfuntmpl_doc.c for a more detailed template | *  ------------------------------------------------------------------------  * Created: Sun Mar 30 13:07:10 2003 * * */#define S_FUNCTION_NAME DPT_Sfunc_1_C#define S_FUNCTION_LEVEL 2/*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*//* %%%-SFUNWIZ_defines_Changes_BEGIN --- EDIT HERE TO _END */#define NUM_INPUTS           1         #define INPUT_0_WIDTH        2#define INPUT_0_FEEDTHROUGH  0#define NUM_OUTPUTS          1#define OUTPUT_0_WIDTH       2#define NPARAMS              6#define SAMPLE_TIME_0        INHERITED_SAMPLE_TIME#define NUM_DISC_STATES      0#define DISC_STATES_IC       [0]#define NUM_CONT_STATES      2#define CONT_STATES_IC       [0,0]#define SFUNWIZ_GENERATE_TLC 1#define SOURCEFILES "//my_lib.lib"#define PANELINDEX           5#define SFUNWIZ_REVISION     1.0/* %%%-SFUNWIZ_defines_Changes_END --- EDIT HERE TO _BEGIN *//*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/#include "simstruc.h"#define PARAM_DEF0(S) ssGetSFcnParam(S, 0)#define PARAM_DEF1(S) ssGetSFcnParam(S, 1)#define PARAM_DEF2(S) ssGetSFcnParam(S, 2)#define PARAM_DEF3(S) ssGetSFcnParam(S, 3)#define PARAM_DEF4(S) ssGetSFcnParam(S, 4)#define PARAM_DEF5(S) ssGetSFcnParam(S, 5)extern void DPT_Sfunc_1_C_Outputs_wrapper(const real_T *u,                             real_T       *y,                             const real_T *xC,                              const real_T  *param0, const int_T  p_width0, const real_T  *param1,
const int_T p_width1, const real_T *param2, const int_T p_width2, const real_T *param3, const
int_T p_width3, const real_T *param4, const int_T p_width4, const real_T *param5, const int_T
p_width5);extern void DPT_Sfunc_1_C_Update_wrapper(const real_T *u, const real_T *y, const real_T *param0, const int_T p_width0,const real_T *param1, const
int_T p_width1,const real_T *param2, const int_T p_width2,const real_T *param3, const int_T
p_width3,const real_T *param4, const int_T p_width4, const real_T *param5, const int_T p_width5);extern void DPT_Sfunc_1_C_Derivatives_wrapper(const real_T *u, const real_T *y, real_T *dx, real_T *xC, const real_T *param0, const int_T p_width0,const real_T *param1, const
int_T p_width1,const real_T *param2, const int_T p_width2,const real_T *param3, const int_T
p_width3,const real_T *param4, const int_T p_width4, const real_T *param5, const int_T p_width5);/*====================* * S-function methods * *====================*/#define MDL_CHECK_PARAMETERS#if defined(MDL_CHECK_PARAMETERS) && defined(MATLAB_MEX_FILE) /* Function: mdlCheckParameters========================================== * Abstract: * Validate our parameters to verify they are okay. */ static void mdlCheckParameters(SimStruct *S) { int i; bool validParam = false;/* All parameters must be scalar */ for (i = 0; i < ssGetSFcnParamsCount(S); i++) { const mxArray *pVal = ssGetSFcnParam(S,i); if ( !mxIsNumeric(pVal) || !mxIsDouble(pVal) || mxIsLogical(pVal) || mxIsComplex(pVal) || mxIsSparse(pVal) || !mxIsFinite(mxGetPr(pVal)[0])) { validParam = true; break; } } if (validParam) { ssSetErrorStatus(S,"All parameters must be a scalar or vectors"); return; } } #endif /* MDL_CHECK_PARAMETERS */ /* Function: mdlInitializeSizes =========================================== * Abstract: * Setup sizes of the various vectors. */static void mdlInitializeSizes(SimStruct *S){ DECL_AND_INIT_DIMSINFO(inputDimsInfo); DECL_AND_INIT_DIMSINFO(outputDimsInfo); ssSetNumSFcnParams(S, NPARAMS); /* Number of expected parameters */#if defined(MATLAB_MEX_FILE) if (ssGetNumSFcnParams(S) == ssGetSFcnParamsCount(S)) { mdlCheckParameters(S); if (ssGetErrorStatus(S) != NULL) { return; } } else { return; /* Parameter mismatch will be reported by Simulink */ }#endif ssSetNumContStates(S, NUM_CONT_STATES); ssSetNumDiscStates(S, NUM_DISC_STATES); if (!ssSetNumInputPorts(S, 1)) return; inputDimsInfo.width = INPUT_0_WIDTH; ssSetInputPortDimensionInfo(S, 0, &inputDimsInfo); ssSetInputPortFrameData(S, 0, FRAME_INHERITED); ssSetInputPortDirectFeedThrough(S, 0, INPUT_0_FEEDTHROUGH); ssSetInputPortRequiredContiguous(S, 0, 1); /*direct input signal access*/ if (!ssSetNumOutputPorts(S,1)) return; outputDimsInfo.width = OUTPUT_0_WIDTH; ssSetOutputPortDimensionInfo(S, 0, &outputDimsInfo); ssSetOutputPortFrameData(S, 0, FRAME_INHERITED); ssSetNumSampleTimes(S, 1); ssSetNumRWork(S, 0); ssSetNumIWork(S, 0); ssSetNumPWork(S, 0); ssSetNumModes(S, 0); ssSetNumNonsampledZCs(S, 0); /* Take care when specifying exception free code - see sfuntmpl_doc.c */ ssSetOptions(S, SS_OPTION_EXCEPTION_FREE_CODE | SS_OPTION_USE_TLC_WITH_ACCELERATOR);}/* Function: mdlInitializeSampleTimes ====================================== * Abstract: * Specifiy the sample time. */static void mdlInitializeSampleTimes(SimStruct *S){ ssSetSampleTime(S, 0, SAMPLE_TIME_0); ssSetOffsetTime(S, 0, 0.0);}#define MDL_INITIALIZE_CONDITIONS/* Function: mdlInitializeConditions ====================================== * Abstract: * Initialize the states */static void mdlInitializeConditions(SimStruct *S){ real_T *xC = ssGetContStates(S); xC[0] = 0; xC[1] = 0;}/* Function: mdlOutputs =================================================== **/static void mdlOutputs(SimStruct *S, int_T tid){ const real_T *u = (const real_T*) ssGetInputPortSignal(S,0); real_T *y = ssGetOutputPortRealSignal(S,0); const real_T *xC = ssGetContStates(S); const real_T *param0 = mxGetPr(PARAM_DEF0(S)); const real_T *param1 = mxGetPr(PARAM_DEF1(S)); const real_T *param2 = mxGetPr(PARAM_DEF2(S)); const real_T *param3 = mxGetPr(PARAM_DEF3(S)); const real_T *param4 = mxGetPr(PARAM_DEF4(S)); const real_T *param5 = mxGetPr(PARAM_DEF5(S)); const int_T p_width0 = mxGetNumberOfElements(PARAM_DEF0(S)); const int_T p_width1 = mxGetNumberOfElements(PARAM_DEF1(S)); const int_T p_width2 = mxGetNumberOfElements(PARAM_DEF2(S)); const int_T p_width3 = mxGetNumberOfElements(PARAM_DEF3(S)); const int_T p_width4 = mxGetNumberOfElements(PARAM_DEF4(S)); const int_T p_width5 = mxGetNumberOfElements(PARAM_DEF5(S)); DPT_Sfunc_1_C_Outputs_wrapper(u, y, xC, param0, p_width0, param1, p_width1, param2, p_width2,
param3, p_width3, param4, p_width4, param5, p_width5);}#undef MDL_UPDATE /* Change to #define to use the function */#if defined(MDL_UPDATE) /* Function: mdlUpdate ================================================== * Abstract:* This function is called once for every major integration time step.* Discrete states are typically updated here, but this function is useful * for performing any tasks that should only take place once per * integration step. */ static void mdlUpdate(SimStruct *S, int_T tid) { const real_T *u = (const real_T *) ssGetInputPortSignal(S,0); real_T *xD = ssGetDiscStates(S); const real_T *y = ssGetOutputPortSignal(S,0); const real_T *param0 = mxGetPr(PARAM_DEF0(S)); const int_T p_width0 = mxGetNumberOfElements(PARAM_DEF0(S)); const real_T *param1 = mxGetPr(PARAM_DEF1(S)); const int_T p_width1 = mxGetNumberOfElements(PARAM_DEF1(S)); const real_T *param2 = mxGetPr(PARAM_DEF2(S)); const int_T p_width2 = mxGetNumberOfElements(PARAM_DEF2(S)); const real_T *param3 = mxGetPr(PARAM_DEF3(S)); const int_T p_width3 = mxGetNumberOfElements(PARAM_DEF3(S)); const real_T *param4 = mxGetPr(PARAM_DEF4(S)); const int_T p_width4 = mxGetNumberOfElements(PARAM_DEF4(S)); const real_T *param5 = mxGetPr(PARAM_DEF5(S)); const int_T p_width5 = mxGetNumberOfElements(PARAM_DEF5(S));DPT_Sfunc_1_C_Update_wrapper(u, y, param0, p_width0, param1, p_width1, param2, p_width2, param3,
p_width3, param4, p_width4, param5, p_width5); } #endif /* MDL_UPDATE */#define MDL_DERIVATIVES /* Change to #undef to remove function */#if defined(MDL_DERIVATIVES) /* Function: mdlDerivatives ============================================== * Abstract: * In this function, you compute the S-function block's derivatives. * The derivatives are placed in the derivative vector, ssGetdX(S). */ static void mdlDerivatives(SimStruct *S) { const real_T *u = (const real_T *) ssGetInputPortSignal(S,0); real_T *dx = ssGetdX(S); real_T *xC = ssGetContStates(S); const real_T *y = ssGetOutputPortSignal(S,0); const real_T *param0 = mxGetPr(PARAM_DEF0(S)); const int_T p_width0 = mxGetNumberOfElements(PARAM_DEF0(S)); const real_T *param1 = mxGetPr(PARAM_DEF1(S)); const int_T p_width1 = mxGetNumberOfElements(PARAM_DEF1(S)); const real_T *param2 = mxGetPr(PARAM_DEF2(S)); const int_T p_width2 = mxGetNumberOfElements(PARAM_DEF2(S)); const real_T *param3 = mxGetPr(PARAM_DEF3(S)); const int_T p_width3 = mxGetNumberOfElements(PARAM_DEF3(S)); const real_T *param4 = mxGetPr(PARAM_DEF4(S)); const int_T p_width4 = mxGetNumberOfElements(PARAM_DEF4(S)); const real_T *param5 = mxGetPr(PARAM_DEF5(S)); const int_T p_width5 = mxGetNumberOfElements(PARAM_DEF5(S));DPT_Sfunc_1_C_Derivatives_wrapper(u, y, dx, xC, param0, p_width0, param1, p_width1, param2, p_width2,
param3, p_width3, param4, p_width4, param5, p_width5); }#endif /* MDL_DERIVATIVES *//* Function: mdlTerminate ================================================== * Abstract: * No termination needed, but we are required to have this routine. */static void mdlTerminate(SimStruct *S){}#ifdef MATLAB_MEX_FILE /* Is this file being compiled as a MEX-file? */#include "simulink.c" /* MEX-file interface mechanism */#else#include "cg_sfun.h" /* Code generation registration function */#endif

Жирным шрифтом в тексте S-функции выделены те строки кода, которые обеспечивают считывание параметров блока S-function, заданных в окне диалога. При инициализации S-функции создается структура с именем S, которая содержит в численном виде все свойства S-функции и из которой, собственно, и происходит извлечение параметров с помощью указанных строк кода. Например, строкаconst real_T *param0 = mxGetPr(PARAM_DEF0(S));обеспечивает извлечение первого (из списка в окне параметров блока S-function) параметра, а в строке const int_T p_width0 = mxGetNumberOfElements(PARAM_DEF0(S));переменной p_width0 присваивается значение размерности этого же параметра (параметры блока S-function могут быть не только скалярами, но и векторами). Отметим также, что такие строки кода имеются в каждом из методов - mdlDerivatives, mdlOutputs и mdlUpdate, благодаря чему параметры блока S-function являются доступными в каждом из методов. Таким образом, пользователю остается добавить выделенные строки в метод mdlInitializeSizes, записать в этом же методе выражения для вычисления нужных констант и обеспечить передачу рассчитанных значений в методы mdlDerivatives, mdlOutputs и mdlUpdate. Удобнее всего это сделать с помощью специально написанной функции. Ниже приводится текст такой функции (Sfun_Get_Parameters.c) для рассматриваемого примера.

Файл Sfun_Get_Parameters.c:

double  A00, A01, A10, B00, B11, C00, C11;void Sfun_Get_Parameters(SimStruct *S){    const real_T        *param0  = mxGetPr(PARAM_DEF0(S));    const real_T        *param1  = mxGetPr(PARAM_DEF1(S));    const real_T        *param2  = mxGetPr(PARAM_DEF2(S));    const real_T        *param3  = mxGetPr(PARAM_DEF3(S));    const real_T        *param4  = mxGetPr(PARAM_DEF4(S));    const real_T        *param5  = mxGetPr(PARAM_DEF5(S));    const int_T         p_width0  = mxGetNumberOfElements(PARAM_DEF0(S));    const int_T         p_width1  = mxGetNumberOfElements(PARAM_DEF1(S));    const int_T         p_width2  = mxGetNumberOfElements(PARAM_DEF2(S));    const int_T         p_width3  = mxGetNumberOfElements(PARAM_DEF3(S));    const int_T         p_width4  = mxGetNumberOfElements(PARAM_DEF4(S));    const int_T         p_width5  = mxGetNumberOfElements(PARAM_DEF5(S));    double L, R, J, Cm, Cw, Fi;    L=*param0;  R=*param1;  J=*param2; Cm=*param3; Cw=*param4;  Fi=*param5;    A00 = -R/L;   A01 = -Cw*Fi/L;  A10 = Cm*Fi/J;     B00 = 1/L;      B11 = -1/J;            C00 = Cm*Fi;    C11 = 1;}

В первой строке файла выполнено объявление переменных A00, A01, A10, B00, B11, C00, C11. Благодаря тому, что это объявление выполнено вне тела функции указанные переменные являются глобальными. Это облегчает реализацию их передачи в нужные методы. Затем в файле функции следует объявление самой функции, и, несколько строк кода, извлекающие параметры и их размерность из структуры S. Далее идет объявление переменных, являющихся параметрами электродвигателя и расчет значений переменных A00, A01, A10, B00, B11, C00, C11.

Таким образом, исходный файл DPT_Sfunc_1_C.c подвергается модернизации в двух местах:

  1. Необходимо вписать строку для подключения файла функции Sfun_Get_Parameters:
    #include "Sfun_Get_Parameters.c" .
    Указанную директиву необходимо записать сразу после всех директив #include и #define.

  2. В конце метода mdlInitializeSizes записать вызов функции Sfun_Get_Parameters:
    Sfun_Get_Parameters(S);

В результате файл DPT_Sfunc_1_C.c будет выглядеть следующим образом (жирным шрифтом выделены добавления):

/* * File: DPT_Sfunc_1_C.c * * * *   --- THIS FILE GENERATED BY S-FUNCTION BUILDER: BASIC, 1.0 --- * *   This file is an S-function produced by the Basic S-Function *   Builder which only recognizes certain fields.  Changes made *   outside these fields will be lost the next time the block is *   used to load, edit, and resave this file. This file will be overwritten *   by the S-function Builder block. If you want to edit this file by hand,  *   you must change it only in the area defined as:   * *        %%%-SFUNWIZ_defines_Changes_BEGIN *        #define NAME 'replacement text'  *        %%% SFUNWIZ_defines_Changes_END * *   DO NOT change NAME--Change the 'replacement text' only. * *   For better compatibility with the Real-Time Workshop, the *   "wrapper" S-function technique is used.  This is discussed *   in the Real-Time Workshop User's Manual in the Chapter titled, *   "Wrapper S-functions". * * ------------------------------------------------------------------------- *| See matlabroot/simulink/src/sfuntmpl_doc.c for a more detailed template | *  ------------------------------------------------------------------------  * Created: Sun Mar 30 13:07:10 2003 *  * */#define S_FUNCTION_NAME DPT_Sfunc_1_C#define S_FUNCTION_LEVEL 2/*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*//* %%%-SFUNWIZ_defines_Changes_BEGIN --- EDIT HERE TO _END */#define NUM_INPUTS           1         #define INPUT_0_WIDTH        2#define INPUT_0_FEEDTHROUGH  0#define NUM_OUTPUTS          1#define OUTPUT_0_WIDTH       2#define NPARAMS              6#define SAMPLE_TIME_0        INHERITED_SAMPLE_TIME#define NUM_DISC_STATES      0#define DISC_STATES_IC       [0]#define NUM_CONT_STATES      2#define CONT_STATES_IC       [0,0]#define SFUNWIZ_GENERATE_TLC 1#define SOURCEFILES "//my_lib.lib"#define PANELINDEX           5#define SFUNWIZ_REVISION     1.0/* %%%-SFUNWIZ_defines_Changes_END --- EDIT HERE TO _BEGIN *//*<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/#include "simstruc.h"#define PARAM_DEF0(S) ssGetSFcnParam(S, 0)#define PARAM_DEF1(S) ssGetSFcnParam(S, 1)#define PARAM_DEF2(S) ssGetSFcnParam(S, 2)#define PARAM_DEF3(S) ssGetSFcnParam(S, 3)#define PARAM_DEF4(S) ssGetSFcnParam(S, 4)#define PARAM_DEF5(S) ssGetSFcnParam(S, 5)//=========================NEW CODE==================================   #include "Sfun_Get_Parameters.c"//=========================NEW CODE==================================extern void DPT_Sfunc_1_C_Outputs_wrapper(const real_T *u,                             real_T       *y,                             const real_T *xC,                              const real_T  *param0, const int_T  p_width0, const real_T  *param1,
const int_T p_width1, const real_T *param2, const int_T p_width2, const real_T *param3, const
int_T p_width3, const real_T *param4, const int_T p_width4, const real_T *param5, const int_T
p_width5);extern void DPT_Sfunc_1_C_Update_wrapper(const real_T *u, const real_T *y, const real_T *param0, const int_T p_width0,const real_T *param1, const
int_T p_width1,const real_T *param2, const int_T p_width2,const real_T *param3, const int_T
p_width3,const real_T *param4, const int_T p_width4, const real_T *param5, const int_T p_width5);extern void DPT_Sfunc_1_C_Derivatives_wrapper(const real_T *u, const real_T *y, real_T *dx, real_T *xC, const real_T *param0, const int_T p_width0,const real_T *param1, const
int_T p_width1,const real_T *param2, const int_T p_width2,const real_T *param3, const int_T
p_width3,const real_T *param4, const int_T p_width4, const real_T *param5, const int_T p_width5);/*====================* * S-function methods * *====================*/#define MDL_CHECK_PARAMETERS#if defined(MDL_CHECK_PARAMETERS) && defined(MATLAB_MEX_FILE) /* Function: mdlCheckParameters ========================================= * Abstract: * Validate our parameters to verify they are okay. */ static void mdlCheckParameters(SimStruct *S) { int i; bool validParam = false; /* All parameters must be scalar */ for (i = 0; i < ssGetSFcnParamsCount(S); i++) { const mxArray *pVal = ssGetSFcnParam(S,i); if ( !mxIsNumeric(pVal) || !mxIsDouble(pVal) || mxIsLogical(pVal) || mxIsComplex(pVal) || mxIsSparse(pVal) || !mxIsFinite(mxGetPr(pVal)[0])) { validParam = true; break; } } if (validParam) { ssSetErrorStatus(S,"All parameters must be a scalar or vectors"); return; } } #endif /* MDL_CHECK_PARAMETERS *//* Function: mdlInitializeSizes ============================================ * Abstract: * Setup sizes of the various vectors. */static void mdlInitializeSizes(SimStruct *S){ DECL_AND_INIT_DIMSINFO(inputDimsInfo); DECL_AND_INIT_DIMSINFO(outputDimsInfo); ssSetNumSFcnParams(S, NPARAMS); /* Number of expected parameters */#if defined(MATLAB_MEX_FILE) if (ssGetNumSFcnParams(S) == ssGetSFcnParamsCount(S)) { mdlCheckParameters(S); if (ssGetErrorStatus(S) != NULL) { return; } } else { return; /* Parameter mismatch will be reported by Simulink */ }#endif ssSetNumContStates(S, NUM_CONT_STATES); ssSetNumDiscStates(S, NUM_DISC_STATES); if (!ssSetNumInputPorts(S, 1)) return; inputDimsInfo.width = INPUT_0_WIDTH; ssSetInputPortDimensionInfo(S, 0, &inputDimsInfo); ssSetInputPortFrameData(S, 0, FRAME_INHERITED); ssSetInputPortDirectFeedThrough(S, 0, INPUT_0_FEEDTHROUGH); ssSetInputPortRequiredContiguous(S, 0, 1); /*direct input signal access*/ if (!ssSetNumOutputPorts(S,1)) return; outputDimsInfo.width = OUTPUT_0_WIDTH; ssSetOutputPortDimensionInfo(S, 0, &outputDimsInfo); ssSetOutputPortFrameData(S, 0, FRAME_INHERITED); ssSetNumSampleTimes(S, 1); ssSetNumRWork(S, 0); ssSetNumIWork(S, 0); ssSetNumPWork(S, 0); ssSetNumModes(S, 0); ssSetNumNonsampledZCs(S, 0); /* Take care when specifying exception free code - see sfuntmpl_doc.c */ ssSetOptions(S, SS_OPTION_EXCEPTION_FREE_CODE | SS_OPTION_USE_TLC_WITH_ACCELERATOR);//=========================NEW CODE================================== Sfun_Get_Parameters(S);//=========================NEW CODE==================================}/* Function: mdlInitializeSampleTimes =================================== * Abstract: * Specifiy the sample time. */static void mdlInitializeSampleTimes(SimStruct *S){ ssSetSampleTime(S, 0, SAMPLE_TIME_0); ssSetOffsetTime(S, 0, 0.0);}#define MDL_INITIALIZE_CONDITIONS/* Function: mdlInitializeConditions ==================================== * Abstract: * Initialize the states */static void mdlInitializeConditions(SimStruct *S){ real_T *xC = ssGetContStates(S); xC[0] = 0; xC[1] = 0;}/* Function: mdlOutputs ================================================= **/static void mdlOutputs(SimStruct *S, int_T tid){ const real_T *u = (const real_T*) ssGetInputPortSignal(S,0); real_T *y = ssGetOutputPortRealSignal(S,0); const real_T *xC = ssGetContStates(S); const real_T *param0 = mxGetPr(PARAM_DEF0(S)); const real_T *param1 = mxGetPr(PARAM_DEF1(S)); const real_T *param2 = mxGetPr(PARAM_DEF2(S)); const real_T *param3 = mxGetPr(PARAM_DEF3(S)); const real_T *param4 = mxGetPr(PARAM_DEF4(S)); const real_T *param5 = mxGetPr(PARAM_DEF5(S)); const int_T p_width0 = mxGetNumberOfElements(PARAM_DEF0(S)); const int_T p_width1 = mxGetNumberOfElements(PARAM_DEF1(S)); const int_T p_width2 = mxGetNumberOfElements(PARAM_DEF2(S)); const int_T p_width3 = mxGetNumberOfElements(PARAM_DEF3(S)); const int_T p_width4 = mxGetNumberOfElements(PARAM_DEF4(S)); const int_T p_width5 = mxGetNumberOfElements(PARAM_DEF5(S)); DPT_Sfunc_1_C_Outputs_wrapper(u, y, xC, param0, p_width0, param1, p_width1, param2, p_width2,
param3, p_width3, param4, p_width4, param5, p_width5);}#undef MDL_UPDATE /* Change to #define to use the function */#if defined(MDL_UPDATE) /* Function: mdlUpdate ================================================= * Abstract: * This function is called once for every major integration time step. * Discrete states are typically updated here, but this function is useful * for performing any tasks that should only take place once per * integration step. */ static void mdlUpdate(SimStruct *S, int_T tid) { const real_T *u = (const real_T *) ssGetInputPortSignal(S,0); real_T *xD = ssGetDiscStates(S); const real_T *y = ssGetOutputPortSignal(S,0); const real_T *param0 = mxGetPr(PARAM_DEF0(S)); const int_T p_width0 = mxGetNumberOfElements(PARAM_DEF0(S)); const real_T *param1 = mxGetPr(PARAM_DEF1(S)); const int_T p_width1 = mxGetNumberOfElements(PARAM_DEF1(S)); const real_T *param2 = mxGetPr(PARAM_DEF2(S)); const int_T p_width2 = mxGetNumberOfElements(PARAM_DEF2(S)); const real_T *param3 = mxGetPr(PARAM_DEF3(S)); const int_T p_width3 = mxGetNumberOfElements(PARAM_DEF3(S)); const real_T *param4 = mxGetPr(PARAM_DEF4(S)); const int_T p_width4 = mxGetNumberOfElements(PARAM_DEF4(S)); const real_T *param5 = mxGetPr(PARAM_DEF5(S)); const int_T p_width5 = mxGetNumberOfElements(PARAM_DEF5(S)); DPT_Sfunc_1_C_Update_wrapper(u, y, param0, p_width0, param1, p_width1, param2, p_width2, param3,
p_width3, param4, p_width4, param5, p_width5); } #endif /* MDL_UPDATE */#define MDL_DERIVATIVES /* Change to #undef to remove function */#if defined(MDL_DERIVATIVES) /* Function: mdlDerivatives ============================================= * Abstract: * In this function, you compute the S-function block's derivatives. * The derivatives are placed in the derivative vector, ssGetdX(S). */ static void mdlDerivatives(SimStruct *S) { const real_T *u = (const real_T *) ssGetInputPortSignal(S,0); real_T *dx = ssGetdX(S); real_T *xC = ssGetContStates(S); const real_T *y = ssGetOutputPortSignal(S,0); const real_T *param0 = mxGetPr(PARAM_DEF0(S)); const int_T p_width0 = mxGetNumberOfElements(PARAM_DEF0(S)); const real_T *param1 = mxGetPr(PARAM_DEF1(S)); const int_T p_width1 = mxGetNumberOfElements(PARAM_DEF1(S)); const real_T *param2 = mxGetPr(PARAM_DEF2(S)); const int_T p_width2 = mxGetNumberOfElements(PARAM_DEF2(S)); const real_T *param3 = mxGetPr(PARAM_DEF3(S)); const int_T p_width3 = mxGetNumberOfElements(PARAM_DEF3(S)); const real_T *param4 = mxGetPr(PARAM_DEF4(S)); const int_T p_width4 = mxGetNumberOfElements(PARAM_DEF4(S)); const real_T *param5 = mxGetPr(PARAM_DEF5(S)); const int_T p_width5 = mxGetNumberOfElements(PARAM_DEF5(S)); DPT_Sfunc_1_C_Derivatives_wrapper(u, y, dx, xC, param0, p_width0, param1, p_width1, param2,
p_width2, param3, p_width3, param4, p_width4, param5, p_width5); }#endif /* MDL_DERIVATIVES *//* Function: mdlTerminate ================================================== * Abstract: * No termination needed, but we are required to have this routine. */static void mdlTerminate(SimStruct *S){}#ifdef MATLAB_MEX_FILE /* Is this file being compiled as a MEX-file? */#include "simulink.c" /* MEX-file interface mechanism */#else#include "cg_sfun.h" /* Code generation registration function */#endif

Следующим шагом является модернизация файла DPT_Sfunc_1_C_wrapper.c, в котором содержится вычислительный код методов mdlDerivatives, mdlOutputs и mdlUpdate. Для рассматриваемого примера модернизация данного файла сводится к следующим шагам:

  1. Необходимо добавить объявление глобальных переменных:
    double A00, A01, A10, B00, B11, C00, C11;
    Это объявление следует сделать сразу же за последней директивой #include.

  2. Убрать ("закомментировать") ставшие лишними строки, в которых выполняется объявление и расчет
    переменных A00, A01, A10, B00, B11, C00 и C11.

В результате файл DPT_Sfunc_1_C_wrapper.c будет выглядеть следующим образом (жирным шрифтом отмечены изменения в этом файле):

 /* * *   --- THIS FILE GENERATED BY S-FUNCTION BUILDER: BASIC, 1.0 --- * *   This file is a wrapper S-function produced by the S-Function *   Builder which only recognizes certain fields.  Changes made *   outside these fields will be lost the next time the block is *   used to load, edit, and resave this file. This file will be overwritten *   by the S-function Builder block. If you want to edit this file by hand,  *   you must change it only in the area defined as:   * *        %%%-SFUNWIZ_wrapper_XXXXX_Changes_BEGIN  *            Your Changes go here *        %%%-SFUNWIZ_wrapper_XXXXXX_Changes_END * *   For better compatibility with the Real-Time Workshop, the *   "wrapper" S-function technique is used.  This is discussed *   in the Real-Time Workshop User's Manual in the Chapter titled, *   "Wrapper S-functions". * *   Created: Sun Mar 30 13:07:10 2003 *//* * Include Files * */#include "tmwtypes.h"/* %%%-SFUNWIZ_wrapper_includes_Changes_BEGIN --- EDIT HERE TO _END */#include //=========================NEW CODE================================== double  A00, A01, A10, B00, B11, C00, C11;//=========================NEW CODE==================================/* %%%-SFUNWIZ_wrapper_includes_Changes_END --- EDIT HERE TO _BEGIN *//* * Create external references here.   * *//* %%%-SFUNWIZ_wrapper_externs_Changes_BEGIN --- EDIT HERE TO _END *///extern double func(double a);/* %%%-SFUNWIZ_wrapper_externs_Changes_END --- EDIT HERE TO _BEGIN *//* * Output functions * */void DPT_Sfunc_1_C_Outputs_wrapper(const real_T *u,                             real_T       *y,                             const real_T *xC,                              const real_T  *param0, const int_T  p_width0, const real_T  *param1,
const int_T p_width1, const real_T *param2, const int_T p_width2, const real_T *param3, const
int_T p_width3, const real_T *param4, const int_T p_width4, const real_T *param5, const int_T
p_width5){ /* This Outputs function allows for 1 input and 1 output * signal of any width, any number of discrete states and * parameters, all of type real_T. * * If you need the FULL POWER of the S-function interface, * familiarize yourself with the full template file at: * * matlabroot/simulink/src/sfuntmpl_doc.c * * and the "Writing S-functions" manual in the documentation. *//* %%%-SFUNWIZ_wrapper_Outputs_Changes_BEGIN --- EDIT HERE TO _END *///=========================OLD CODE==================================/* double Cm = param3[0], Fi = param5[0]; double C00=Cm*Fi, C11= 1; *///=========================OLD CODE================================== y[0] = C00*xC[0]; y[1] = C11*xC[1];/* %%%-SFUNWIZ_wrapper_Outputs_Changes_END --- EDIT HERE TO _BEGIN */}/* * Updates function * */void DPT_Sfunc_1_C_Update_wrapper(const real_T *u, const real_T *y, const real_T *param0, const int_T p_width0,const real_T *param1, const
int_T p_width1,const real_T *param2, const int_T p_width2,const real_T *param3, const
int_T p_width3,const real_T *param4, const int_T p_width4, const real_T *param5, const int_T p_width5){/* %%%-SFUNWIZ_wrapper_Update_Changes_BEGIN --- EDIT HERE TO _END *//* * Code example * xD[0] = u[0]; */ /* %%%-SFUNWIZ_wrapper_Update_Changes_END --- EDIT HERE TO _BEGIN */}/* * Derivatives function * */void DPT_Sfunc_1_C_Derivatives_wrapper(const real_T *u, const real_T *y, real_T *dx, real_T *xC, const real_T *param0, const int_T p_width0,const real_T *param1, const
int_T p_width1,const real_T *param2, const int_T p_width2,const real_T *param3, const int_T
p_width3,const real_T *param4, const int_T p_width4, const real_T *param5, const int_T p_width5){/* %%%-SFUNWIZ_wrapper_Derivatives_Changes_BEGIN --- EDIT HERE TO _END *///=========================OLD CODE==================================/* double L = param0[0], R = param1[0], J =param2[0]; double Cm = param3[0], Cw = param4[0], Fi=param5[0]; double A00 = -R/L , A01 = -Cw*Fi/L , B00 = 1/L; double A10 = Cm*Fi/J , B11 = -1/J; *///=========================OLD CODE================================== dx[0] = A00*xC[0]+A01*xC[1]+B00*u[0]; dx[1] = A10*xC[0]+B11*u[1]; /* %%%-SFUNWIZ_wrapper_Derivatives_Changes_END --- EDIT HERE TO _BEGIN */}

Выполнить сборку S-функции на основе измененных файлов следует командой из рабочего окна MATLAB:
mex DPT_Sfunc_1_C.c DPT_Sfunc_1_C_wrapper.cилиmex -g DPT_Sfunc_1_C.c DPT_Sfunc_1_C_wrapper.c .
При этом папка, где находятся исходные файлы, должна быть настроена как текущая. Команда mex с опцией -g создает отладочный вариант S-функции.

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

[Скачать пример]

В оглавление книги \ К следующему разделу \ К предыдущему разделу


Поиск по сайту:

Система Orphus

Яндекс.Метрика