文章目录
前言
在基于Simulink的模型开发中,对于标定量和观测量的管理大部分都是通过.sldd的数据字典。但对于数据字典来说,创建,修改变量都不是很方便,特别是在大的模型开发过程中,标定量和观测量可能成千上万个。所以,引入Excel来管理标定量和观测量是非常有必要的。
标定量的格式
通过Simulink手动建立一个Paramter,主要参数界面如下:
导出m文件的格式如下:
MyPortParam = mypackage.Parameter;
MyPortParam.Value = [0 300 600 900 1200 1500 1800];
MyPortParam.CoderInfo.StorageClass = 'Custom';
MyPortParam.CoderInfo.Identifier = '';
MyPortParam.CoderInfo.Alignment = -1;
MyPortParam.CoderInfo.CustomStorageClass = 'mysc';
MyPortParam.CoderInfo.CustomAttributes.HeaderFile = '';
MyPortParam.CoderInfo.CustomAttributes.DefinitionFile = '';
MyPortParam.CoderInfo.CustomAttributes.Owner = '';
MyPortParam.Description = ['this is my description'];
MyPortParam.DataType = 'uint16';
MyPortParam.Min = 0;
MyPortParam.Max = 10000;
MyPortParam.DocUnits = 'mA';
MyPortParam.GenericProperty = [];
MyPortParam.DoubleProperty = 0;
MyPortParam.Int32Property = int32(0);
MyPortParam.LogicalProperty = false;
MyPortParam.CharProperty = '';
MyPortParam.OnOffCharProperty = 'off';
MyPortParam.ColorCharProperty = 'red';
主要的参数如下:
ParameterName:标定量名
Package:一般就是自定义的package或者Simulink package
Object:Parameter or Siganl
DataType:数据类型
Value:参数值,可能是数值,也可能是一维数组,也可能是二维数组,这个比较麻烦,需要特殊处理
Min:最小值,在A2L导入标定工具标定时会有影响
Max:最大值,在A2L导入标定工具标定时会有影响
Unit:单位
Dimensions:维度,根据实际输入的value来的,可以不用填
StrorageClass:自定义的存储类,在生成标定量时会添加#pragam宏
Description:描述信息
Excel表格式
以三个标定量为例,一个为二维数组,一个为一维数组,一个为常量
建立了两个sheet,一个为Caliration,一个为MapData,将标定量为数组的value链接到对应的MapData表中的数据上
MapData表
设置链接属性
在参数名上右键,选择定义名称
新建好名称后,在Caliration中可以新建超链接
定义超链接
在Caliration value处右键新建一个超链接,链接到之前定义的对应名称上
以上,关于Paramter的Excel表格的格式就建立好了。下面需要解析Excel表中的内容到matlab中的.m文件中
maltab脚本解析Excel信息
解析Parameter所在列
考虑兼容性,先查找对应参数所在的列,这样的话在列位置改变后仍然可以获取正确的信息。
Parametercolumn = {'ParameterName','ParameterPort','DataElement','SwCalibrationAccess',...
'DisplayFormat','Package','Object','DataType','Value','Min','Max','Unit','Dimensions',...
'StrorageClass', 'Description'};
column_num = size(Parameter,2);%获取列数
row_num = size(Parameter,1);%获取行数
%获取参数在表中的列数
for j = 1:column_num
for jj = 1:length(Parametercolumn)
if strcmpi(Parameter{1,j},Parametercolumn{jj})
Parameter_column_num(j) = jj;%Parameter所在列
break;
else
Parameter_column_num(j) = 0;
end
end
end
for ii = 1:column_num%找不到对应列名称时报错
if Parameter_column_num(ii) == 0
error('not find Parametercolumn:%s',Parametercolumn{ii});
end
end
解析MapData
思路是通过Paramter名来查找,数据在Paramter名的下一行。
优先找到Paramter个数,然后循环查找Value。**注意:**最后一个参数需要特殊处理,其他按位置赋值就好了。
[~,~,Mapdata] = xlsread(Excel_Name,Sheet_Cell{ii})%获取map表中的信息
MapDatacolumn_num = size(Mapdata,2);%获取列数
MapDatarow_num = size(Mapdata,1);%获取行数
for i = 1:MapDatarow_num
if isnumeric(Mapdata{i,1}) == 0 & ~isnan(Mapdata{i,1})
MapDataNamerow(i) = i;
end
end
MapDataNamerow(find(MapDataNamerow==0))=[];%去除数组中为0的元素
for i=1:length(MapDataNamerow)
if i==length(MapDataNamerow)%最后一个需要特殊处理
MapDataName{i} = Mapdata{MapDataNamerow(i),1};
MapDataValue{i,1} = Mapdata(MapDataNamerow(i)+1:end,1:end);
else
MapDataName{i} = Mapdata{MapDataNamerow(i),1};%获取名称
MapDataValue{i,1} = Mapdata(MapDataNamerow(i)+1:MapDataNamerow(i+1)-2,1:end);%获取数组
end
end
循环写Paramter
Value参数需要特殊处理,其他正常转换就好了。目前只判断参数名和Value不为空时就可以写。部分代码如下:
output_m_file = 'Model_parameter.m';
fid = fopen(output_m_file,'wt');
for row = 2:row_num
if ~isnan(Parameter{row,Parameter_column_num(1)}) & ~isnan(Parameter{row,Parameter_column_num(9)})
ParameterName = Parameter{row,Parameter_column_num(1)};
ParameterPackage = Parameter{row,Parameter_column_num(6)};
ParameterObject = Parameter{row,Parameter_column_num(7)};
ParameterPackageObject = strcat(ParameterPackage,'.',ParameterObject);
ParameterDataType = Parameter{row,Parameter_column_num(8)};
if isnumeric(Parameter{row,Parameter_column_num(9)}) == 1%判断输入是否为数值
ParameterValue = Parameter{row,Parameter_column_num(9)};
ParameterValue_str = num2str(ParameterValue);%转为字符串
else
for ii = 1:length(MapDataName)
if strcmp(MapDataName{ii},ParameterName)
ParameterValue = MapDataValue{ii,1};
if size(ParameterValue,1)>1
for i = 1:size(ParameterValue,1)
ParameterValueS=cell2mat(ParameterValue(i,:));%cell转为数组
ParameterValueS=ParameterValueS(~isnan(ParameterValueS))%去除NaN
ParameterValue_str = num2str(ParameterValueS);%转为字符串
if i == 1
ParameterValue_allstr = strcat('[...\n',ParameterValue_str,';\n');
elseif i == size(ParameterValue,1)
ParameterValue_allstr = strcat(ParameterValue_allstr,ParameterValue_str,']');
else
ParameterValue_allstr = strcat(ParameterValue_allstr,ParameterValue_str,';\n');
end
end
ParameterValue_str = ParameterValue_allstr;
else
ParameterValue=cell2mat(ParameterValue);%cell转为数组
ParameterValue=ParameterValue(~isnan(ParameterValue))%去除NaN
ParameterValue_str = num2str(ParameterValue);%转为字符串
ParameterValue_str = strcat('[',ParameterValue_str,']');
end
end
end
end
outputParameter_str = strcat(ParameterName,' = ',ParameterPackageObject,';\n');
fprintf(fid,outputParameter_str);
outputParameter_str = strcat(ParameterName,'.Value',' = ',ParameterValue_str,';\n');
fprintf(fid,outputParameter_str);
end
end
对一维和二维数组需要特殊处理,具体可以参考上面的代码。
生成的m文件
% --------------------------------------------
%Auto Generated at:2022-07-17 10:25:27
%----------------Designed by Zan--------------%
%----------------Version : V101---------------%
%---------------------------------------------
MyPortParam =mypackage.Parameter;
MyPortParam.Value =[...
-155 -120 -85 -80 -75 -60 -55 -40 -35 30 195 205 475 565 575 665 600 735;
-1505 -1185 -840 -760 -670 -565 -510 -470 -380 355 1130 2290 4060 5055 5310 5470 6350 7230;
-1460 -1090 -725 -640 -555 -455 -405 -365 -295 345 1095 2170 3385 3795 4015 4245 5235 6220;
-1310 -965 -620 -535 -445 -350 -305 -270 -195 335 1065 1665 2270 2575 2830 3085 4070 5055;
-1240 -875 -510 -420 -325 -230 -185 -155 -85 220 470 530 770 1205 1565 1905 3040 4180;
-1120 -785 -455 -365 -280 -200 -165 -135 -75 95 135 195 340 645 960 1255 2390 3525;
-1135 -775 -415 -340 -260 -190 -160 -130 -70 90 130 190 300 510 735 970 1960 2950];
MyPortParam.CoderInfo.StorageClass ='Custom';
MyPortParam.CoderInfo.CustomStorageClass ='mysc';
MyPortParam.Description ='test parameter';
MyPortParam.DataType ='int16';
MyPortParam.Min =-32768;
MyPortParam.Max =32767;
MyPortParam.DocUnits ='N';
MyPortParam1 =mypackage.Parameter;
MyPortParam1.Value =[1800 1500 1200 900 600 300 100 0];
MyPortParam1.CoderInfo.StorageClass ='Custom';
MyPortParam1.CoderInfo.CustomStorageClass ='mysc';
MyPortParam1.Description ='test parameter2';
MyPortParam1.DataType ='uint16';
MyPortParam1.Min =0;
MyPortParam1.Max =5000;
MyPortParam1.DocUnits ='mA';
MyPortParam3 =mypackage.Parameter;
MyPortParam3.Value =22;
MyPortParam3.CoderInfo.StorageClass ='Custom';
MyPortParam3.CoderInfo.CustomStorageClass ='mysc';
MyPortParam3.Description ='test parameter3';
MyPortParam3.DataType ='uint8';
MyPortParam3.Min =0;
MyPortParam3.Max =255;
MyPortParam3.DocUnits ='';
运行m文件后生成的Paramter
注意:如果需要生成的是mypackage类型的Parameter,请确保已经建立了对应的mypackage,否则请选择Simulink Parameter,不然的话运行m文件会报错。
用到的函数记录
size
size-获取二维数组的大小
size(A,1)-获取行数
size(A,2)-获取列数
strcmpi
比较两个字符串是否相等,相等时为1,否则为0,带i的是不区分大小写,不带i的是区分大小写
error
报错到命令行,error(‘message’);和输出printf一样,可以加入占位符
isnumeric
判断输入是否为数字,1为真,0为假
isnan
判断输入是否为NaN,1为真,0为假
find
通过find函数去除数组中非0的元素
MapDataNamerow(find(MapDataNamerow==0))=[];
strcat
拼接字符串,第一个参数为输入的字符串,后面跟的为需要拼接的字符串
num2str
数值转字符串
去除NaN
ParameterValueS=ParameterValueS(~isnan(ParameterValueS))%去除NaN
fopen
打开文件,若文件不存在,则创建文件,wt,可读可写,r,可读。返回值为文件句柄
cell2mat
cell转数组
fprintf
向文件中写入数据,第一个参数为文件句柄,后面为需要写入的内容
若你觉得本文对你有帮助,欢迎点赞,关注,收藏,转发~~~
你的鼓励是对小弟的最大支持~~~
建了一个WX公众号,《汽车电子学习笔记》感兴趣可以关注一下~~~文章都会同步更新~