%% Read and Write Block Parameters to Excel
% If you manage model data in external files, you can use scripts to pass the data between the data file and a Simulink® model. This example shows you how to read block parameter data from and write parameter data to an Excel® data file. Specifically, the example provides functions that read and write Mapped SI Engine parameter data. You can adapt the functions to read and write parameters for additional blocks.
%% Open Mapped SI Engine Block
% Open the Mapped SI Engine block in the hybrid electric vehicle P2 reference application.
%% Open the Hybrid Electric Vehicle P2 Reference Application

workDir = pwd;
autoblkHevP2Start;
cd(workDir);

% Set a variable equal to the block path.

bp = 'SiMappedEngine/Mapped SI Engine'; % block path

%% Open Mapped SI Engine Block
% In the HevP2ReferenceApplication model, navigate to Passenger Vehicle > Ideal Mapped Engine > SiMappedEngine . Open the Mapped SI Engine block. The Breakpoints for commanded torque, Breakpoints for engine speed input, Number of cylinders, Crank revolutions per power stroke, and Total displaced volume parameters are set to workspace variables.
%
% The functions in the example overwrite the workspace variables with the values in the data file.
%
%% Specify Data File Configuration
% First, specify the file name. This example file SiEngineData.xlsx contains three sheets. The first sheet contains scalar values for commanded torque breakpoints, breakpoints for engine speed input breakpoints, number of cylinders, crank revolutions, and total displaced volume. The second sheet contains a table values for the brake torque map. The third sheet contains table values for the fuel torque map.

fileName = 'SiEngineData.xlsx';

% Note that the first sheet in the file specifies the Number of cylinders, Ncyl parameter as 6.
%
% Next, define the configuration data for the engine subsystem. This example sets a configuration for double variables of size scalar, vector, or a 2D array.
% Scalar data structure specifies the data on the first sheet.
% Vector data structure specifies the data on the second sheet.
% Array data structure specifies the data on the third sheet.

engData = struct(); % engine parameter data

% Scalar data
engData.Ncyl = struct('xlSheet','Main', 'xlRange','C7:C7', 'slBlockPath',bp, 'slBlockParam','Ncyl');
engData.Cps = struct('xlSheet','Main', 'xlRange','C8:C8', 'slBlockPath',bp, 'slBlockParam','Cps');
engData.Vd = struct('xlSheet','Main', 'xlRange','C9:C9', 'slBlockPath',bp, 'slBlockParam','Vd');

% Vector data
engData.t_bpt = struct('xlSheet','Main', 'xlRange','C3:R3', 'slBlockPath',bp, 'slBlockParam','f_tbrake_t_bpt');
engData.n_bpt = struct('xlSheet','Main', 'xlRange','C4:R4', 'slBlockPath',bp, 'slBlockParam','f_tbrake_n_bpt');

% 2D array data
engData.torque = struct('xlSheet','Brake Torque', 'xlRange','B2:Q17', 'slBlockPath',bp, 'slBlockParam','f_tbrake');
engData.fuel = struct('xlSheet','Fuel Map', 'xlRange','B2:Q17', 'slBlockPath',bp, 'slBlockParam','f_fuel');

%% Read Mapped SI Engine Block Parameters
% Update the Mapped SI Engine block  to the values specified in the data file.
%% Read Data File and Update Parameters
% Use this code to read the data file and update the Mapped SI Engine block parameters.

f = fields(engData);
for idx = 1:length(f)
    try
        var = getfield(engData, f{idx});
        % read value from Excel
        val = readmatrix(fileName, 'Sheet',var.xlSheet, 'Range',var.xlRange);
        % open Simulink model
        mdl = fileparts(var.slBlockPath);
        open_system(mdl);
        % set parameter value and save model
        set_param(var.slBlockPath, var.slBlockParam, mat2str(val));
        save_system(mdl);
    catch ME
        % return any error info
        disp(getReport(ME, 'extended', 'hyperlinks', 'on'))
        fprintf('\nContinuing to next variable...\n\n');
    end
end
fprintf('Done writing values to Simulink\n')

%% Open Mapped SI Engine Block
% In the HevP2ReferenceApplication model, navigate to Passenger Vehicle > Ideal Mapped Engine > SiMappedEngine. Open the Mapped SI Engine block. The Breakpoints for commanded torque, Breakpoints for engine speed input, Number of cylinders, Crank revolutions per power stroke, and Total displaced volume parameters are set to the values specified in the data file. Confirm that the Brake torque map and Fuel flow map parameters are the same as the values specified in the data file.
%
%% Write Modified Parameters to Data File
% In the Mapped SI Engine block, change the Number of cylinders, NCyl parameter from 6 to 8. Click Apply. Save the model.
%
% Alternatively, use this code to update the parameter and save the model.

set_param(bp,'Ncyl','8');
save_system('SiMappedEngine');

%% Write Parameter Data to File
% First, create a copy of the data file. Write the modified parameter data to the copy of the data file.

copyfile('SiEngineData.xlsx','SiEngineDataCopy.xlsx','f');
fileName = 'SiEngineDataCopy.xlsx';

% Next, use this code to write the Mapped SI Engine block Breakpoints for commanded torque, Breakpoints for engine speed input, Number of cylinders, Crank revolutions per power stroke, Total displaced volume, Brake torque map, and Fuel flow map parameters to the data file.

% Read data from Simulink model then write to Excel
f = fields(engData);
for idx = 1:length(f)
    try
        var = getfield(engData, f{idx});
        % open Simulink model
        mdl = fileparts(var.slBlockPath);
        open_system(mdl);
        % read value from Simulink
        val = str2num(get_param(var.slBlockPath, var.slBlockParam));
        % write value to Excel
        writematrix(val, fileName, 'Sheet',var.xlSheet, 'Range',var.xlRange);
    catch ME
        % return any error info
        disp(getReport(ME, 'extended', 'hyperlinks', 'on'))
        fprintf('\nContinuing to next variable...\n\n');
    end
end
fprintf('Done writing values to Excel\n')

% Open the file with the modified data. Confirm that the number of cylinders in the data file is 8.
%
%
% Copyright 2020 The MathWorks, Inc.
%