01--背景
去年由于工作岗位的动荡,于是面试了一家知名车企,上来进行了一番简单的介绍之后,被告知需要进入笔试环节,以往单位面试都是简单聊聊技术问题,比如对软件开发的流程或者使用的工具等待问题的交流,但是笔试的话一般是写代码的人这样要求多些,Simulink的笔试还真是头一家。对方直接开线上会议之后,需要我这边进行投屏,并把笔试题目发过来,限时一个小时完成,全程线上对方技术人员会观看你通过Simulink建模的直播。
02--题目
1.Implement the following logic use simulink
Input signal: A(single);
Oupt signal: B(uint8);
Control Logic:
- Average filtering for Input signal A, Output the average of 10 cycle.
- If A>30, then B=30; if A<25, then B=0;
If A>40, then B=50; if A<35, then B=30;
If A>50, then B=80; if A<45, then B=50;
- Oupt signal B ,rate limitation, increase 3 and reduce 5 for one cyrcle.
- Carry out unit test for item 2) ,and generate unit test report ( include 10 test cases at
least )
03--题目分析
当收到题目之后,发现只有一道题,一个小时岂不是绰绰有余,但是是纯英文的,先是通读了一番题目,乍一看,好像难度还不是很高,但是最后的事实结果发现一个小时还完成不了,前面有点想当然了。第1小问就是求输入信号10个周期的平均值,第2小问是求分段函数并加上回滞功能,第3小问是求斜率限制即rate limit,第4小问是求单元测试,并生成单元测试报告(包含至少10个测试用例)。
看起来是一道简单的题目,但是把软件开发流程简单过了一遍,要开发还要测试,就差没有生成代码了,那一刻我也发现没那么简单了,而且需要进行单元测试生成报告,之前我们工作中有专门的工具去干这种事,现在只能用Simulink自带的Simulink Test去做了,还好当时还会这个,不然第4小问直接接挂了。感兴趣的同学也可以自己试一试,看看1小时是否能够完成。
以下是我的解题,不见得完全正确,也不见得所用的模块是最好最简洁的,欢迎其他大佬提出更简洁的思路。
04--建模
1.求解器设置
首先新建了模型,并先按如下设置了求解器设置,题目没有指定采样时间,我就自行进行了设置
2.第1小问:当时能想到的最快的方式就是直接用10个delay去求10个周期的平均值,但是对于前面10个时刻的值都需要去被平均,不知道这点理解是否准确。并设置了信号A的数据类型为single
封装子系统
3.第2小问:主逻辑搭建
当时读到题目的时候发现这是一个简单的模型搭建,只需要用到滞环relay模块和Switch模块即可完成这个功能搭建,于是搭建如下:
以上需要设置好数据类型,A相关为single,B相关为uint8
relay的On 及 Off点的设置为50,45;40,35;30,25.
但是这样搭建看上去没问题,实际上如果去做单元测试就会发现问题,那就是滞回的On 及 Off点这个relay模块都是包含的,也就是说你搭建的模型是当A**>=**30,B=30,这和题目中If A>30, then B=30; 不一样,你多了一个"="好。就像图中把这些点刨去了一样,而你没刨去,显然这样的建模不符合题目的要求。
接下来我们可以以这个模型进行仿真验证一下:
将该模块也以子系统封装起来,并用Signal Builder模块设计一组数据作为测试用例来验证,用示波器进行观测
由于Signal Builder默认数据类型为double,需要进行转换一下,不然会报错
Signal Builder内的测试用例设计为,一组从0到30,一组从0到34的数据,按照题目要求,结果应该为第一组数据对应结果为0,第二组数据对应结果为30
而示波器显示的结果2组都为30,证实了这样的建模不符合题目要求
那么既然自带的relay模块不行,接下来可以自己创建一个relay模块去解决这个问题 ,这样的话可以自行去设置判断的关系逻辑符号
relay模块的需求为,当输入信号大于On点时,输出置1,当输入信号小于Off点时,输出信号置0,在On 和Off点之间的输出值保持上一时刻的值。,那么relay模块可搭建如下:
那么上面的关系符可以进行设置了,去掉=号,将上面进行封装后替代relay模块,并设置常数On及Off点,再次进行验证仿真
运行后,示波器的结果:
更新之后的模型符合题目的需求,但是仔细的同学还会发现在满足A大于30时,不是直接从大于的那一时刻突变到30,而是延时了一个时刻从5.9s到6s的过程中从0-30,斜着上去的,因为求解器为0.1s,这个由采样导致问题实际上可以忽略不计的。
接下来我想着还可以通过另外一个途径来搭建通用功能的模型,那就是Stateflow
搭建的模型如下:最需要注意的是各个状态之间执行的顺序,顺序不对那么整个设计就会背道而驰
把所有关系写出来后就是需要调整执行顺序了,A为某个值,但是同时满足了好几个条件,肯定是最大值为第一顺序,后面依次排开。执行顺序的设置为直接点击线条右键设置即可
将Stateflow设置好数据类型并进行封装起来
用刚刚的测试用例再进行测试一遍,并读取示波器结果:
可以看到,结果验证符合需求
4.第3小问:rate limit功能
输出信号B在单个周期,值增加时最大不能超过3,值减小时最大不能减小超过5,其余情况按原值输出
这个可以用系统自带的模块也可以自行进行搭建
先看自行搭建的模块
用当前时刻与上一时刻的差值如果在-5和3之间则原值输出,如果大于等于3,则由上一时刻的值加3,小于-5则由上一时刻的值减去5,模型搭建如下:
注意数据类型不能全部设置为uint8,涉及到负数
封装后,进行如下测试用例进行仿真
示波器结果:
放大后量斜率发现:
(23.99-8.99)/(6.7-6.2)=3
另外,可通过自带的rate limit模块进行
在设置斜率的时候要设置步长/采样时间
由于上升步长为3,采样时间为0.1,鼓上升斜率为3/0.1=30,下降则为-50
封装后进行测试
示波器结果一致
把所有子系统连起来用以下测试用例测试一遍:
示波器结果
5.第4小问
至于单元测试及报告等可以参考之前写的另一篇博文
这里就不再赘述了