このページの翻訳は最新ではありません。ここをクリックして、英語の最新版を参照してください。
カスタム ブロックの設計と作成
カスタム ブロックの設計方法
通常、カスタム ブロックの作成は次のプロセスを使用します。
カスタム化された飽和ブロックを作成する場合を例に挙げます。信号の上限と下限はブロック パラメーターまたは入力信号に基づくものとします。このブロックの 2 番目のバージョンでは、シミュレーションの終了後に飽和限界をプロットするオプションを付けます。次のチュートリアルではこのブロックの設計手順を案内します。ex_customsat_lib
ライブラリにはカスタマイズされた飽和ブロックの 2 つのバージョンがあります。
モデル例 sldemo_customsat
は基本バージョンのブロックを使用します。
カスタム ブロックの動作定義
カスタム ブロックの機能と制限の定義から始めます。この例では、ブロックが次の機能をサポートします。
上下の飽和限界をオン/オフする。
上限と下限をブロック パラメーターを介して設定する。
上限と下限を入力信号を使って設定する。
次の制限もあります。
飽和の入力信号はスカラーであること。
入力信号と飽和限界はすべて double のデータ型であること。
コード生成は要求されない。
カスタム ブロック タイプの決定
定義された機能に基づき、このカスタム ブロックには以下のサポートが要求されます。
複数の入力端子
比較的単純なアルゴリズム
連続システム状態も離散システム状態もない。
したがって、このチュートリアルでは Level-2 MATLAB® S-Function を使用してカスタム ブロックを作成します。MATLAB S-Function は複数の入力をサポートします。アルゴリズムが単純であるため、ブロック線図を更新するときにもモデルをシミュレーションするときにも大きなオーバーヘッドは発生しません。MATLAB S-Function が提供できる機能と他のカスタム ブロックとの比較の詳細は、カスタム ブロックの機能の比較を参照してください。
MATLAB S-Function のパラメーター化
S-Function パラメーターの定義から始めます。この例は 4 つのパラメーターを必要とします。
最初のパラメーターは飽和上限の設定方法を示します。この下限はオフにできます。ブロック パラメーターまたは入力信号がそのオン/オフを設定します。
2 番目のパラメーターは飽和上限の値です。この値は飽和上限がブロック パラメーターによってオンに設定されているときに使用されます。このパラメーターが使用される場合、シミュレーション中にパラメーター値が変更できる、つまりパラメーターが調整可能でなければなりません。
3 番目パラメーターは飽和下限の設定方法を示します。この下限はオフにできます。ブロック パラメーターまたは入力信号がそのオン/オフを設定します。
4 番目のパラメーターは飽和下限の値です。この値は飽和下限がブロック パラメーターによってオンに設定されているときに使用されます。飽和上限の場合と同様、このパラメーターは使用中に調整可能でなければなりません。
最初と 3 番目の S-Function パラメーターはモードを表しますが、S-Function が識別できる値に変換できるものでなければなりません。したがって、飽和上限と下限のモードを次の値で定義します。
1
は飽和限界をオフにします。2
は飽和限界がブロック パラメーターによって設定されることを示します。3
は飽和限界が入力信号によって設定されることを示します。
MATLAB S-Function の書き込み
S-Function のパラメーターと機能を定義した後で、S-Function を記述します。テンプレート msfuntmpl.m
は Level-2 MATLAB S-Function を記述するときの開始点を提供します。完成されたカスタム飽和ブロックは custom_sat.m
というファイルにあります。このチュートリアルを続けるには、このファイルを作業フォルダーにコピーしてください。
この S-Function は、S-Function テンプレートを次のように変更したものです。
setup
関数は、飽和の上限と下限のモードとして入力された値に基づいて、入力端子の数を初期化します。限界が入力信号によって設定される場合、メソッドはブロックに入力端子を追加します。setup
メソッドは次に、4 つの S-Function パラメーターがあることを示し、それらのパラメーターを調整可能に設定します。最後に、メソッドはシミュレーション中に使用された S-Function メソッドを登録します。function setup(block) % The Simulink engine passes an instance of the Simulink.MSFcnRunTimeBlock % class to the setup method in the input argument "block". This is known as % the S-function block's run-time object. % Register original number of input ports based on the S-function % parameter values try % Wrap in a try/catch, in case no S-function parameters are entered lowMode = block.DialogPrm(1).Data; upMode = block.DialogPrm(3).Data; numInPorts = 1 + isequal(lowMode,3) + isequal(upMode,3); catch numInPorts=1; end % try/catch block.NumInputPorts = numInPorts; block.NumOutputPorts = 1; % Setup port properties to be inherited or dynamic block.SetPreCompInpPortInfoToDynamic; block.SetPreCompOutPortInfoToDynamic; % Override input port properties block.InputPort(1).DatatypeID = 0; % double block.InputPort(1).Complexity = 'Real'; % Override output port properties block.OutputPort(1).DatatypeID = 0; % double block.OutputPort(1).Complexity = 'Real'; % Register parameters. In order: % -- If the upper bound is off (1) or on and set via a block parameter (2) % or input signal (3) % -- The upper limit value. Should be empty if the upper limit is off or % set via an input signal % -- If the lower bound is off (1) or on and set via a block parameter (2) % or input signal (3) % -- The lower limit value. Should be empty if the lower limit is off or % set via an input signal block.NumDialogPrms = 4; block.DialogPrmsTunable = {'Nontunable','Tunable','Nontunable', ... 'Tunable'}; % Register continuous sample times [0 offset] block.SampleTimes = [0 0]; %% ----------------------------------------------------------------- %% Options %% ----------------------------------------------------------------- % Specify if Accelerator should use TLC or call back into % MATLAB script block.SetAccelRunOnTLC(false); %% ----------------------------------------------------------------- %% Register methods called during update diagram/compilation %% ----------------------------------------------------------------- block.RegBlockMethod('CheckParameters', @CheckPrms); block.RegBlockMethod('ProcessParameters', @ProcessPrms); block.RegBlockMethod('PostPropagationSetup', @DoPostPropSetup); block.RegBlockMethod('Outputs', @Outputs); block.RegBlockMethod('Terminate', @Terminate); %end setup function
CheckParameters
メソッドは Level-2 MATLAB S-Function ブロックに入力された値を検証します。function CheckPrms(block) lowMode = block.DialogPrm(1).Data; lowVal = block.DialogPrm(2).Data; upMode = block.DialogPrm(3).Data; upVal = block.DialogPrm(4).Data; % The first and third dialog parameters must have values of 1-3 if ~any(upMode == [1 2 3]); error('The first dialog parameter must be a value of 1, 2, or 3'); end if ~any(lowMode == [1 2 3]); error('The first dialog parameter must be a value of 1, 2, or 3'); end % If the upper or lower bound is specified via a dialog, make sure there % is a specified bound. Also, check that the value is of type double if isequal(upMode,2), if isempty(upVal), error('Enter a value for the upper saturation limit.'); end if ~strcmp(class(upVal), 'double') error('The upper saturation limit must be of type double.'); end end if isequal(lowMode,2), if isempty(lowVal), error('Enter a value for the lower saturation limit.'); end if ~strcmp(class(lowVal), 'double') error('The lower saturation limit must be of type double.'); end end % If a lower and upper limit are specified, make sure the specified % limits are compatible. if isequal(upMode,2) && isequal(lowMode,2), if lowVal >= upVal, error('The lower bound must be less than the upper bound.'); end end %end CheckPrms function
ProcessParameters
とPostPropagationSetup
メソッドが S-Function パラメーターの調整を扱います。function ProcessPrms(block) %% Update run time parameters block.AutoUpdateRuntimePrms; %end ProcessPrms function function DoPostPropSetup(block) %% Register all tunable parameters as runtime parameters. block.AutoRegRuntimePrms; %end DoPostPropSetup function
Outputs
メソッドが S-Function パラメーターの設定と入力信号に基づいてブロックの出力を計算します。function Outputs(block) lowMode = block.DialogPrm(1).Data; upMode = block.DialogPrm(3).Data; sigVal = block.InputPort(1).Data; lowPortNum = 2; % Initialize potential input number for lower saturation limit % Check upper saturation limit if isequal(upMode,2), % Set via a block parameter upVal = block.RuntimePrm(2).Data; elseif isequal(upMode,3), % Set via an input port upVal = block.InputPort(2).Data; lowPortNum = 3; % Move lower boundary down one port number else upVal = inf; end % Check lower saturation limit if isequal(lowMode,2), % Set via a block parameter lowVal = block.RuntimePrm(1).Data; elseif isequal(lowMode,3), % Set via an input port lowVal = block.InputPort(lowPortNum).Data; else lowVal = -inf; end % Assign new value to signal if sigVal > upVal, sigVal = upVal; elseif sigVal < lowVal, sigVal=lowVal; end block.OutputPort(1).Data = sigVal; %end Outputs function
カスタム ブロックのライブラリへの配置
ライブラリは、カスタム ブロックを他のユーザーと共有する、カスタム ブロックのコピーの機能更新を容易にする、特定のプロジェクトのブロックを一箇所に集めておくなどを可能にします。カスタム ブロックにインターフェイスとしてバスが必要な場合、データ ディクショナリでバス オブジェクトを作成し、ディクショナリをライブラリに付加することにより、バス オブジェクトをライブラリのユーザーと共有できます (カスタム ライブラリへのデータ ディクショナリのリンクを参照)。
この例では、カスタム飽和ブロックをライブラリに配置します。
Simulink® エディターの [シミュレーション] タブで、[新規] 、 [ライブラリ] を選択します。
User-Defined Functions ライブラリから、Level-2 MATLAB S-Function ブロックを新しいライブラリにドラッグします。
ライブラリをファイル名
saturation_lib
で保存します。ブロックをダブルクリックして [関数ブロック パラメーター] ダイアログ ボックスを開きます。
[S-Function 名] フィールドに、S-Function の名前を入力します。たとえば「
custom_sat
」と入力します。[パラメーター] フィールドに、「2,-1,2,1
」と入力します。[OK] をクリックします。
カスタム飽和ブロックを他のユーザーと共有できるようになりました。
カスタムマイズしたユーザー インターフェイスを追加するとブロックが使いやすくなります。
カスタム ブロックへのユーザー インターフェイスの追加
Simulink のマスク機能を使用して、カスタム ブロックのブロック ダイアログ ボックスを作成できます。ブロックのマスクを使うと、端子にラベルを追加して、どの端子が入力信号と飽和限界に対応するかを示すこともできます。
作成したカスタム ブロックを含むライブラリ
saturation_lib
を開きます。Level-2 MATLAB S-Function ブロックを右クリックして、[マスク] 、 [マスクの作成] を選択します。
[アイコンを描画するコマンド] ボックスの [アイコンと端子] ペインに、「
port_label('input',1,'uSig')
」と入力し、[適用] をクリックします。このコマンドは、既定端子に飽和時の入力信号であることを示すラベルを付けます。
[パラメーターとダイアログ] ペインで、4 つの S-Function パラメーターに対応する 4 つのパラメーターを追加します。以下の表に表示されているとおりに、新しいパラメーターごとに、ポップアップまたは編集コントロールを [ダイアログ ボックス] セクションにドラッグします。各パラメーターは [パラメーター] グループにドラッグします。
タイプ プロンプト 名前 評価 調整可能 ポップアップ オプション コールバック popup
Upper boundary: upMode
✓ 制限なし
制限をパラメーターとして入力する
入力信号を使用して制限する
customsat_callback('upperbound_callback', gcb)
edit
Upper limit: upVal
✓ ✓ N/A customsat_callback('upperparam_callback', gcb)
タイプ プロンプト 名前 評価 調整可能 ポップアップ オプション コールバック popup
Lower boundary: lowMode
✓ 制限なし
制限をパラメーターとして入力する
入力信号を使用して制限する
customsat_callback('lowerbound_callback', gcb)
edit
Lower limit: lowVal
✓ ✓ N/A customsat_callback('lowerparam_callback', gcb)
MATLAB S-Function スクリプト
custom_sat_final.m
にはマスク パラメーターのコールバックが含まれます。custom_sat_final.m
を作業フォルダーに保存し、この例のコールバックを定義します。この MATLAB スクリプトは 2 つの入力引数を使用します。最初の入力引数はどのマスク パラメーターがコールバックを起動したかを示す文字ベクトルです。2 番目の入力引数は、関連付けられている Level-2 MATLAB S-Function ブロックへのハンドルです。次の図は、マスク エディターの完成した [パラメーターとダイアログ] ペインを示しています。
[初期化] ペインで、[ライブラリ ブロックで内容を変更することを許可] チェック ボックスをオンにします。この設定は、S-Function がブロック上の端子数を変更できるようにします。
[ドキュメンテーション] ペインで、以下を実行します。
[マスク タイプ] フィールドに、次のように入力します。
Customized Saturation
[マスクの説明] フィールドに、次のように入力します。
Limit the input signal to an upper and lower saturation value set either through a block parameter or input signal.
[OK] をクリックします。
S-Function パラメーターをマスク パラメーターにマッピングするには、Level-2 MATLAB S-Function ブロックを右クリックして [マスク] 、 [マスク内を表示] を選択します。
[S-Function 名] フィールドを
custom_sat_final
に変更し、[パラメーター] フィールドをlowMode,lowVal,upMode,upVal
に変更します。この図は、変更後の [Function ブロック パラメーター] ダイアログ ボックスを示しています。
[OK] をクリックします。ライブラリを保存して閉じ、編集モードを終了します。
ライブラリをもう一度開き、カスタマイズした飽和ブロックをダブルクリックしてマスク パラメーター ダイアログ ボックスを開きます。
複雑なユーザー インターフェイスを作成するには、マスクされたブロックの上に MATLAB グラフィックスのユーザー インターフェイスを置きます。ブロックの OpenFcn
が MATLAB グラフィックスのユーザー インターフェイスを起動し、それが set_param
を呼び出すと、ユーザー インターフェイスの設定に基づいて S-Function ブロックのパラメーターが変更されます。
マスク コールバック コードの記述
関数 customsat_callback.m
にはカスタム飽和ブロックのマスク パラメーター ダイアログ ボックスに表示されるマスク コールバックのコードが含まれています。この関数は、feval
への呼び出しを通して各マスク パラメーターに対応するローカル関数を呼び出します。
以下のローカル関数は、飽和上限モードの選択に基づいて飽和上限フィールドの可視性を制御します。コールバックは、プロパティ名 MaskValues
を指定して get_param
を呼び出すことによって、すべてのマスク パラメーターの値を取得することから始めます。コールバックでマスク パラメーターが 1 つだけ必要な場合、get_param
をそのマスク パラメーター名を付けて、たとえば、get_param(block,'upMode')
のようにして呼び出すことができます。この例では 2 つのマスク パラメーター値が必要なので、get_param
への呼び出し回数を減らすために MaskValues
プロパティを使っています。
次にコールバックは、プロパティ名 MaskVisbilities
を付けて get_param
を呼び出すことによって、マスク パラメーターの可視性を取得します。この呼び出しは、各マスク パラメーターの可視性を示す文字ベクトルが入った cell 配列を返します。コールバックは、飽和上限のモードに基づいてマスクの可視性の値を変更し、端子のラベル テキストを更新します。
コールバックは最後にブロックの入力端子にラベルを付けるために、set_param
コマンドを使ってブロックの MaskDisplay
プロパティを更新します。
function customsat_callback(action,block) % CUSTOMSAT_CALLBACK contains callbacks for custom saturation block % Copyright 2003-2007 The MathWorks, Inc. %% Use function handle to call appropriate callback feval(action,block) %% Upper bound callback function upperbound_callback(block) vals = get_param(block,'MaskValues'); vis = get_param(block,'MaskVisibilities'); portStr = {'port_label(''input'',1,''uSig'')'}; switch vals{1} case 'No limit' set_param(block,'MaskVisibilities',[vis(1);{'off'};vis(3:4)]); case 'Enter limit as parameter' set_param(block,'MaskVisibilities',[vis(1);{'on'};vis(3:4)]); case 'Limit using input signal' set_param(block,'MaskVisibilities',[vis(1);{'off'};vis(3:4)]); portStr = [portStr;{'port_label(''input'',2,''up'')'}]; end if strcmp(vals{3},'Limit using input signal'), portStr = [portStr;{['port_label(''input'',',num2str(length(portStr)+1), ... ',''low'')']}]; end set_param(block,'MaskDisplay',char(portStr));
set_param
への最後の呼び出しでは、MATLAB S-Function custom_sat.m
内の関数 setup
が呼び出されます。したがって、関数 setup
を変更して、入力端子の数の設定が S-Function パラメーター値ではなく、マスク パラメーター値に基づくようにできます。この関数 setup
に対する変更は、Level-2 MATLAB S-Function ブロックの中の端子の数をマスク パラメーターのダイアログ ボックスに表示される値に一致させます。
変更された MATLAB S-Function custom_sat_final.m
には、次の新しい関数 setup
が入ります。このチュートリアルに従っている場合は、このファイルを開いて自分の作業フォルダーに保存してください。
%% Function: setup =================================================== function setup(block) % Register original number of ports based on settings in Mask Dialog ud = getPortVisibility(block); numInPorts = 1 + isequal(ud(1),3) + isequal(ud(2),3); block.NumInputPorts = numInPorts; block.NumOutputPorts = 1; % Setup port properties to be inherited or dynamic block.SetPreCompInpPortInfoToDynamic; block.SetPreCompOutPortInfoToDynamic; % Override input port properties block.InputPort(1).DatatypeID = 0; % double block.InputPort(1).Complexity = 'Real'; % Override output port properties block.OutputPort(1).DatatypeID = 0; % double block.OutputPort(1).Complexity = 'Real'; % Register parameters. In order: % -- If the upper bound is off (1) or on and set via a block parameter (2) % or input signal (3) % -- The upper limit value. Should be empty if the upper limit is off or % set via an input signal % -- If the lower bound is off (1) or on and set via a block parameter (2) % or input signal (3) % -- The lower limit value. Should be empty if the lower limit is off or % set via an input signal block.NumDialogPrms = 4; block.DialogPrmsTunable = {'Nontunable','Tunable','Nontunable','Tunable'}; % Register continuous sample times [0 offset] block.SampleTimes = [0 0]; %% ----------------------------------------------------------------- %% Options %% ----------------------------------------------------------------- % Specify if Accelerator should use TLC or call back into % MATLAB script block.SetAccelRunOnTLC(false); %% ----------------------------------------------------------------- %% Register methods called during update diagram/compilation %% ----------------------------------------------------------------- block.RegBlockMethod('CheckParameters', @CheckPrms); block.RegBlockMethod('ProcessParameters', @ProcessPrms); block.RegBlockMethod('PostPropagationSetup', @DoPostPropSetup); block.RegBlockMethod('Outputs', @Outputs); block.RegBlockMethod('Terminate', @Terminate); %endfunction
custom_sat_final.m
内のローカル関数 getPortVisibility
は、飽和限界モードを使用して、関数 setup
に戻されるフラグを構築します。関数 setup
はこのフラグを使って必要な入力端子の数を決定します。%% Function: Get Port Visibilities ======================================= function ud = getPortVisibility(block) ud = [0 0]; vals = get_param(block.BlockHandle,'MaskValues'); switch vals{1} case 'No limit' ud(2) = 1; case 'Enter limit as parameter' ud(2) = 2; case 'Limit using input signal' ud(2) = 3; end switch vals{3} case 'No limit' ud(1) = 1; case 'Enter limit as parameter' ud(1) = 2; case 'Limit using input signal' ud(1) = 3; end
ブロック コールバックを使ったブロック機能の追加
ex_customsat_lib
内の User-Defined Saturation with Plotting ブロックは元のカスタム飽和ブロックに機能を追加するためにブロック コールバックを使用します。このブロックは、シミュレーションの終わりに飽和限界をプロットするオプションを提供します。以下の手順では元のカスタム飽和ブロックを変更してこの新しいブロックを作成する方法を示します。
チェック ボックスをマスク パラメーターのダイアログ ボックスに追加して、プロット オプションをオン/オフできるようにします。
saturation_lib
の Level-2 MATLAB S-Function ブロックを右クリックして、[マスク] + [マスクの作成] を選択します。マスク エディターの [パラメーター] ペインで、5 番目のマスク パラメーターを追加して次のプロパティを指定します。
プロンプト 名前 タイプ 調整可能 タイプ オプション コールバック Plot saturation limits plotcheck
チェック ボックス
不可 NA customsat_callback('plotsaturation',gcb)
[OK] をクリックします。
新しいチェック ボックス用のコールバック コードを記述します。コールバックは、シミュレーション中に飽和限界値を保存するために Level-2 MATLAB S-Function ブロックの
UserData
内で構造体を初期化します。MATLAB スクリプトcustomsat_plotcallback.m
には、この新しいコールバックが入っています。新しいマスク パラメーターを処理するために以前のコールバックの修正バージョンも入っています。この例に従っている場合、customsat_plotcallback.m
を開いて、customsat_callback.m
でそのローカル関数をコピーし、以前のローカル関数を上書きします。%% Plotting checkbox callback function plotsaturation(block) % Reinitialize the block's userdata vals = get_param(block,'MaskValues'); ud = struct('time',[],'upBound',[],'upVal',[],'lowBound',[],'lowVal',[]); if strcmp(vals{1},'No limit'), ud.upBound = 'off'; else ud.upBound = 'on'; end if strcmp(vals{3},'No limit'), ud.lowBound = 'off'; else ud.lowBound = 'on'; end set_param(gcb,'UserData',ud);
新しい MATLAB S-Function
custom_sat_plot.m
の場合と同じように、該当する場合、MATLAB S-Function のOutputs
メソッドを更新して飽和限界を保存します。この例に従っている場合、custom_sat_plot.m
内のOutputs
メソッドをコピーして、custom_sat_final.m
内の元のOutputs
メソッドを上書きします。%% Function: Outputs =================================================== function Outputs(block) lowMode = block.DialogPrm(1).Data; upMode = block.DialogPrm(3).Data; sigVal = block.InputPort(1).Data; vals = get_param(block.BlockHandle,'MaskValues'); plotFlag = vals{5}; lowPortNum = 2; % Check upper saturation limit if isequal(upMode,2) upVal = block.RuntimePrm(2).Data; elseif isequal(upMode,3) upVal = block.InputPort(2).Data; lowPortNum = 3; % Move lower boundary down one port number else upVal = inf; end % Check lower saturation limit if isequal(lowMode,2), lowVal = block.RuntimePrm(1).Data; elseif isequal(lowMode,3) lowVal = block.InputPort(lowPortNum).Data; else lowVal = -inf; end % Use userdata to store limits, if plotFlag is on if strcmp(plotFlag,'on'); ud = get_param(block.BlockHandle,'UserData'); ud.lowVal = [ud.lowVal;lowVal]; ud.upVal = [ud.upVal;upVal]; ud.time = [ud.time;block.CurrentTime]; set_param(block.BlockHandle,'UserData',ud) end % Assign new value to signal if sigVal > upVal, sigVal = upVal; elseif sigVal < lowVal, sigVal=lowVal; end block.OutputPort(1).Data = sigVal; %endfunction
飽和限界をプロットするための関数
plotsat.m
を記述します。この関数は Level-2 MATLAB S-Function ブロックへのハンドルを取得して、それをブロックのUserData
を取り出すために使用します。このチュートリアルに従っている場合は、plotsat.m
を作業フォルダーに保存します。function plotSat(block) % PLOTSAT contains the plotting routine for custom_sat_plot % This routine is called by the S-function block's StopFcn. ud = get_param(block,'UserData'); fig=[]; if ~isempty(ud.time) if strcmp(ud.upBound,'on') fig = figure; plot(ud.time,ud.upVal,'r'); hold on end if strcmp(ud.lowBound,'on') if isempty(fig), fig = figure; end plot(ud.time,ud.lowVal,'b'); end if ~isempty(fig) title('Upper bound in red. Lower bound in blue.') end % Reinitialize userdata ud.upVal=[]; ud.lowVal=[]; ud.time = []; set_param(block,'UserData',ud); end
Level-2 MATLAB S-Function ブロックを右クリックして、[プロパティ] を選択します。[ブロックプロパティ] ダイアログ ボックスが開きます。下図に示すように、[コールバック] ペインで
StopFcn
をプロット コールバックを呼び出すように変更して、[OK] をクリックします。