01--Stateflow建模
1.背景
很多时候,我们在拿到需求之后搭建模型,到底是选用Simulink还是Stateflow,经常会不够清晰,也跟自己掌握的技能有关系,有些人接触Simulink较多,不管什么逻辑都要Simulink来做。其实往往是需要去区别情况的,看看哪一个更加方便的去实现需求。
当逻辑仅仅是数据流,一般的算法时可以选择Simulink,而逻辑较多且状态量切换比较复杂等应该选用Stateflow进行建模。
2.按需求建模
下面我们以一个简单的例子来串一下Stateflow建模可能常用的一些功能
假设有如下需求:
①有一个混动变速器,上电后需要自检,假设所有部件均是低压供电,自检后上高压,整车进入ready状态,档位在P档
②整车根据控制开关选择进入纯电或者混动模式
③根据模式和档位传感器的信号进行简单的档位判断,档位有PRND档位,其中混动模式D档中包含4个档位
④纯电模式和混动模式在模式开关切换的过程中能够去到对应的档位
⑤混动模式升降档可根据车速进行简单的判断
3.枚举量介绍
只要涉及了状态的跳转,就有专门的数据类型来支撑这个功能的实施。有很多工程师不太习惯运用枚举来进行状态量的定义,取而代之的是用常数进行定义,每次看到数字后还需要再进行查找表格,而枚举量能够直接以字面意思进行命名,非常直观,便于管理且可读性高。
根据上述需求,我们需要定义如下4个枚举量
传感器读来的档位信号:lever_pos_raw
模式切换开关传过来的信号:VehMode
档位显示信号:lever_pos
模式显示信号:ModeState
定义上述信号,需要新建sldd数据字典,在字典中定义枚举量
打开Model Explorer→File→New→Data Dictionary
在新增里面选择枚举类型
将新增的4个变量命名为上述名字
VehMode
lever_pos_raw
pos(对应上述lever_pos)
State(对应上述ModeState)
4.模型关联数据字典sldd
定义好之后,需要新建一个模型,把sldd与新模型关联起来
关联有如下2种方法:
直接在模型内空白处右键,选择模型属性(Model Properties)
在对话框中选择Data,并把sldd导入即可
第二种方法直接在刚刚的Model Explorer中按下图选择即可
5.建模
按需求简单搭建,如下模型:
这里的建模细节跳过了,主要是为了引出后续需要记录的笔记
模型内的输入及输出量需要在Model Explorer进行定义,也就是说除了sldd中定义的那几个枚举量,在本处也需要再定义一次,不然状态机将无法识别,此处上述枚举量定义时关键点是变量的数据类型的选取,由于sldd中已经定义,所有在数据类型下拉中会出现
运行后,发现没有报错
给定p r n d几个点进行步进仿真,仿真时间设置为无穷大inf
lever_pos_raw.p模拟传感器的p档信号,车速(Sine Wave)按照如下设置
代表最高车速95
给定r档
内部激活的状态:
给定n档
给定d档,步进一次之后,直接继续运行仿真
由于车速Sine Wave的原因,档位一直在D1-D4之间来回跳转
6.state flow的语言选择
可以看到右下角为matlab语言,如果模型引用了跟C代码相关的逻辑,则需要改为C语言
在该界面右键点击属性,如下图进行语言切换
语言的不同会导致逻辑符号的差别,这点需要格外注意
02--模型引用
我们把刚刚建立好的模型连上输入输出,并命名为lever后保存
新建一个模型,在库里面找到模型引用,
双击之后把之前保存的lever模型导入进来,如下:
可以看到显示了所有的输入输出,双击进去后多了一个图示的图标
如果想找到源模型,让该模型成为Top层,需要点击左下角图标
会自动跳转到源模型中
为什么要介绍模型引用,因为很多时候有新项目的话,很多模型是可以复用的,只需要微调或者较小改动一些参数,这就引出了模型平台化的概念。
变体模型 模块此时派上用场了
前面我们已经有了模型lever
此时我们再新增2个模型,一个模型只有纯电模式,一个模型只有燃油模式
纯电模式的模型接口信号我们全部保留,但是把内部Hev这一路的逻辑全部删掉
如下,并把该模型命名为lever_EV
内部逻辑:运行没有报错
同样的,另外一个模型,把EV相关的删掉,并命名为lever_HEV
内部:
处理上面的时候,sldd及Model Explorer内的变量定义均不需要修改
接下来新建一个模型,在模型库内找到变体模型
默认只有2个模型引用框,我们新增一个并且把上述3个模型导入进去,再把所有的输入输出信号新增,信号与系统直接不需要连接(也连不上)
现在可以看到所有的模块都是显示的透明颜色,说明都没有被激活
去到图下所示的选项去设置
在红框处标记出来的变量,我们可以设置一个标定量来对不同模型进行选择
这个标定量我们可以去sldd中进行设置
默认值我们设置为3,数据类型给uint8
设置好后,我们需要再把这个sldd关联到当前这个模型
再把该变量填到下面的地方
再回到模型中,发现被选中的模型已经高亮了
由于变量veh_mode_select的默认值为3,所以模型lever被高亮选中
现在我们在sldd中把该变量值veh_mode_select标定为1
可以看到模型lever_HEV被高亮
我们再把之前的常数值给进来进行仿真
模型运行正常
同样的,我们还可以用相同的方法来处理变体子系统
03--定点数据类型
我们注意到,在数据类型的选取时,除了我们常用的整型数据外,还有定点数据类型,在现如今的软件开发过程中,定点的数据类型已经很少被使用,但是在以前的软件开发过程中,由于处理器的限制比如32位或64位,使得我们使用定点类型数据来精准的利用数据的存储空间。
定点数据最容易带来的问题就是数据溢出。
现在普遍使用了浮点处理器之后,定点数据已经很少使用,可以用数据类型single进行代替。
定点数据类型的优势是节省空间(RAW)
一般single占用4个字节,而定点数2字节
有时候如果RAW空间不够,可以使用一部分数据用定点数据类型
下面来看一些例子,认识下定点数据类型
fixdt(1,16,1)
第一个1代表符号位,(0-无符号,1-有符号),第二个数据16代表位数,也就是2字节,第三个符合代表小数位(精度位),1为2的-1次方即0.5,2为2的-2次方即0.25
我们如果设置0.24,0.24没有到0.5的一半,那么不足单位精度0.5,结果应为0
设置0.26,超过0.5一半,结果应为0.5
所谓最小精度0.5,代表的意思是最终的结果都是最小精度的整数倍
而上述中位数为16位,2的16次方为65535,由于小数(精度)只占用1位,符号占用1位,故该数的最大值为2的14次方,即16384,如果超出这个数,则会造成数据溢出
检测到数据类型溢出错误
但是如果把符号位去掉,则数据范围扩大一倍,但不支持负数的表达了
同样的,最大数来到2的15次方,即32768,由于包含了0,实际最大整数为32767
溢出如下
如果使用定点数去做运算,那么经常会出现精度的丢失
假设有如下数据的计算,数据类型设置为fixdt(1,16,3)
即精度为0.125
那么数10+3.122将不等于13.122了,而是13.125
并且该数,符号位和精度位占用4位,那么最大值将为4096
在使用定点数的模型中出现最多的将是数据类型的问题以及溢出等等,需要特别注意。
上述使用的模型在附件进行下载。