このページは機械翻訳を使用して翻訳されました。最新版の英語を参照するには、ここをクリックします。
MDF ファイルのチャネルを Simulink モデル入力ポートにマッピングする
この例では、MDF ファイルからチャネルをプログラムでマップし、Simulink ® モデルの入力ポートを介してそのデータを使用する方法を示します。これは、Simulink モデルの入力ポート名の収集を実行し、それらを特定の MDF ファイルの内容と関連付けます。次に、モデルの実行時に MDF ファイルから取得されたチャネル データを消費するリンクがそれらの間に作成されます。
モデルの詳細を取得
サンプルモデル名を定義して開きます。
mdlName = "ModelForMDFInput";
open_system(mdlName);
モデルとその入力に関する全体的な情報を取得するには、createInputDataset (Simulink) 関数を使用します。データセット信号要素を timetable として構成するには、DatasetSignalFormat オプションを "timetable" として指定します。
dsObj = createInputDataset(mdlName, UpdateDiagram=true, DatasetSignalFormat="timetable")dsObj =
Simulink.SimulationData.Dataset '' with 2 elements
Name BlockPath
________ _________
1 [2x1 timetable] triangle ''
2 [1x1 struct ] busInput ''
- Use braces { } to access, modify, or add elements using index.
モデル入力ポート名を取得する
このモデルにはバスと個別の入力ポートの両方があります。helperGetMdlInputNames 関数は、モデル内での定義方法に関係なく、すべてのモデル入力の名前を取得する方法を示します。
mdlInputNames = helperGetMdlInputNames(mdlName)
mdlInputNames = 4×1 string
"triangle"
"pwm"
"pwm_level"
"pwm_filtered"
MDFファイルを調査する
モデルの入力ポート名がわかったので、MDF ファイルに存在するチャネルを確認して、それらの一致を試みることができます。mdfChannelInfo 関数を使用すると、MDF ファイル内にある利用可能なチャネルにすばやくアクセスできます。
mdfName = "CANape.MF4";
channelInfo = mdfChannelInfo(mdfName)channelInfo=42×13 table
Name GroupNumber GroupNumSamples GroupAcquisitionName GroupComment GroupSourceName GroupSourcePath DisplayName Unit Comment ExtendedNamePrefix SourceName SourcePath
______________________________________ ___________ _______________ ____________________ ____________ _______________ _______________ ___________ ___________ _________________________________________________ __________________ ___________ __________
"Counter_B4" 1 1993 10 ms 10 ms <undefined> XCPsim "" <undefined> Single bit demo signal (bit from a byte shifting) XCPsim <undefined> XCPsim
"Counter_B5" 1 1993 10 ms 10 ms <undefined> XCPsim "" <undefined> Single bit demo signal (bit from a byte shifting) XCPsim <undefined> XCPsim
"Counter_B6" 1 1993 10 ms 10 ms <undefined> XCPsim "" <undefined> Single bit demo signal (bit from a byte shifting) XCPsim <undefined> XCPsim
"Counter_B7" 1 1993 10 ms 10 ms <undefined> XCPsim "" <undefined> Single bit demo signal (bit from a byte shifting) XCPsim <undefined> XCPsim
"PWM" 1 1993 10 ms 10 ms <undefined> XCPsim "" <undefined> Pulse width signal from PWM_level and Triangle XCPsim <undefined> XCPsim
"PWMFiltered" 1 1993 10 ms 10 ms <undefined> XCPsim "" <undefined> Low pass filtered PWM signal XCPsim <undefined> XCPsim
"PWM_Level" 1 1993 10 ms 10 ms <undefined> XCPsim "" <undefined> <undefined> XCPsim <undefined> XCPsim
"Triangle" 1 1993 10 ms 10 ms <undefined> XCPsim "" <undefined> Triangle test signal used for PWM output PWM XCPsim <undefined> XCPsim
"ampl" 2 199 100ms 100ms <undefined> XCPsim "" <undefined> Amplitude of channel 1-3 XCPsim <undefined> XCPsim
"channel1" 2 199 100ms 100ms <undefined> XCPsim "" <undefined> FLOAT demo signal (sine wave) XCPsim <undefined> XCPsim
"map1_8_8_uc_measure" 1 1993 10 ms 10 ms <undefined> XCPsim "" <undefined> 8*8 fixed axis, permanently morphing XCPsim <undefined> XCPsim
"syncArrayStruct.mem_charArray[000]" 2 199 100ms 100ms <undefined> XCPsim "" <undefined> <undefined> XCPsim <undefined> XCPsim
"syncArrayStruct.mem_charArray[001]" 2 199 100ms 100ms <undefined> XCPsim "" <undefined> <undefined> XCPsim <undefined> XCPsim
"syncArrayStruct.mem_doubleArray[000]" 2 199 100ms 100ms <undefined> XCPsim "" <undefined> <undefined> XCPsim <undefined> XCPsim
"syncArrayStruct.mem_doubleArray[001]" 2 199 100ms 100ms <undefined> XCPsim "" <undefined> <undefined> XCPsim <undefined> XCPsim
"syncArrayStruct.mem_floatArray[000]" 2 199 100ms 100ms <undefined> XCPsim "" <undefined> <undefined> XCPsim <undefined> XCPsim
⋮
関心のある項目を管理するためのテーブルを構築する
テーブルを使用して、モデルの入力ポートを MDF チャネルにマッピングします。
channelTable = table(); channelTable.PortNames = mdlInputNames; n = size(channelTable.PortNames,1); channelTable.GroupNumber = NaN(n,1); channelTable.ChannelName = strings(n,1); channelTable
channelTable=4×3 table
PortNames GroupNumber ChannelName
______________ ___________ ___________
"triangle" NaN ""
"pwm" NaN ""
"pwm_level" NaN ""
"pwm_filtered" NaN ""
入力ポートとチャネルのマッチングを実行する
helperReportChannelInfo 関数は、MDF ファイル内でモデルの入力ポート名と一致するチャネル名を検索します。見つかった場合、チャネルの詳細がテーブルに記録されます。具体的には、ファイル内で指定されたチャネルが存在するチャネル グループ番号と、その実際の定義名です。実際のチャネル名はモデル ポート名と完全に一致しないことに注意してください。この例では、チャネル名の一致は大文字と小文字を区別せずに実行され、アンダースコア文字は無視されます。このアルゴリズムは、アプリケーション固有の一致基準に基づいて必要に応じて調整できます。
channelTable = helperReportChannelInfo(channelTable, channelInfo)
channelTable=4×3 table
PortNames GroupNumber ChannelName
______________ ___________ _____________
"triangle" 1 "Triangle"
"pwm" 1 "PWM"
"pwm_level" 1 "PWM_Level"
"pwm_filtered" 1 "PWMFiltered"
Simulinkデータセットオブジェクトにチャネルデータを入力する
先ほど作成したデータセット オブジェクトには、単一の timetable と timetable の構造体の両方が含まれています。これにより、データを再度割り当てることが多少困難になります。留意すべき点は次のとおりです。
dataset オブジェクトには異なる要素 (timetable と timetable の構造体) があるため、コレクションを手動で管理し、正しい場所に書き込んでいることを確認する必要があります。
mdfRead関数は、デフォルトでデータを物理値として読み取ります。ただし、関心のあるチャネルの 1 つである「PMW」には、ValueToText変換が含まれています。生の数値が読み取られてデータセット オブジェクトに入力されるようにするには、ReadRawオプションをtrueに設定する必要があります。
for ii = 1:dsObj.numElements switch class(dsObj.getElement(ii)) case 'timetable' % Read the input port data from the MDF file one channel at a time. mdfData = mdfRead(mdfName, Channel=channelTable.ChannelName(ii), ReadRaw=true); % Populate the dataset object. dsObj{ii} = mdfData{1}; % For a port that accepts a bus, the data to be loaded must be arranged in a struct % that matches the structure of the bus object attached to the input port. case 'struct' names = fieldnames(dsObj.getElement(ii)); for jj = 1:numel(names) % Find row index of this signal name in the channel table. rowIdx = find(channelTable.PortNames == names(jj)); % Read the input port data from the MDF file one channel at a time. mdfData = mdfRead(mdfName, Channel=channelTable.ChannelName(rowIdx), ReadRaw=true); % Populate the dataset object. dsObj{ii}.(channelTable.PortNames{rowIdx}) = mdfData{1}; end end end dsObj
dsObj =
Simulink.SimulationData.Dataset '' with 2 elements
Name BlockPath
________ _________
1 [1993x1 timetable] triangle ''
2 [1x1 struct ] busInput ''
- Use braces { } to access, modify, or add elements using index.
データセットをSimulinkモデルへの入力として有効にする
set_param(mdlName, "LoadExternalInput", "on"); set_param(mdlName, "ExternalInput", "dsObj");
モデルの実行
モデルを実行すると、MDF ファイルのチャネル データが指定された入力ポートに適切にマップされ、期待どおりに Simulink を通じてプロットされることに注意してください。
open_system(mdlName); bp = find_system(mdlName, "BlockType", "Scope"); open_system(bp); pause(1) sim(mdlName, "TimeOut", 10);

補助関数
function mdlInputNames = helperGetMdlInputNames(mdlName) % helperGetMdlInputNames Find input port names of a Simulink model. % % This function takes in the name of a Simulink model and returns the names of each model input. This specific model has % both a bus and a standalone input port going into it. To drive an input port that expects a bus means you need to supply % the signals as timetables in a struct that matches the structure of the bus object attached to the input port. % Test to see if the model is currently loaded in memory. isLoaded = bdIsLoaded(matlab.lang.makeValidName(mdlName)); % If the model is not open then load it. if ~isLoaded load_system(mdlName); end dsObj = createInputDataset(mdlName, UpdateDiagram=true); numElements = dsObj.numElements; isStruct = zeros(1, numElements); % Check to see if any of the elements in the returned dataset object are % structs. If they are, assume they are for an input port that accepts a bus. for elementIdx = 1:numElements isStruct(elementIdx) = isa(dsObj.getElement(elementIdx),"struct"); end % Initialize an empty string array to hold names of all input ports. If % your model has a very large number of inputs, consider preallocating the % string array for performance. mdlInputNames = string.empty; for idx = 1:numElements if isStruct(idx) % Get names of signals from a bus input port. mdlInputNames = [mdlInputNames; string(fieldnames(dsObj.getElement(idx)))]; %#ok<AGROW> else % Get signal name from a non-bus input port. mdlInputNames = [mdlInputNames; string(dsObj.getElement(idx).Name)]; %#ok<AGROW> end end end
function channelTableOut = helperReportChannelInfo(channelTableIn, channelInfo) % channelTableOut Reports if a channel is present in a set of channel names. % Assign the output data. channelTableOut = channelTableIn; % Remove underscores and make everything lowercase for matching. inPortChannelNames = lower(erase(channelTableIn.PortNames,"_")); mdfChannelNames = lower(erase(channelInfo.Name,"_")); % Match the input channel names to the channel names in the MDF file. [~, inPortIdx] = ismember(inPortChannelNames, mdfChannelNames); % Assign the relevant information back to the channel table. channelTableOut.GroupNumber = channelInfo.GroupNumber(inPortIdx); channelTableOut.ChannelName = channelInfo.Name(inPortIdx); end