4. 扭矩协调核心概念
好,咱们直接进入正题。这一章,我们要开始真正动手了。
前面几章讲了VCU的硬件选型、底层驱动、通信协议,那些都是骨架。从今天开始,我们要给VCU注入灵魂——应用层软件。说白了,就是让VCU知道“什么时候该干什么事”。
我个人习惯用MATLAB/Simulink来做应用层建模。为什么?因为快。你想想看,在VCU开发前期,控制策略一天改三版是常事。用C代码硬写,改一次编译一次烧录一次,黄花菜都凉了。Simulink里拖几个模块,改改参数,仿真跑一遍,结果立竿见影。等策略稳定了,再一键生成代码,直接部署到芯片上。这才是现代VCU开发的正确姿势。
核心观点:Simulink建模不是花架子,它是VCU应用层开发的“快速原型”利器。模型即文档,模型即代码。
4.1 Simulink环境配置——别让工具卡住你
我记得刚带团队的时候,有个同事装了Simulink,打开后一脸懵:怎么全是白的?模块库在哪?
嗯,这里要注意。Simulink不是装完就能直接用的,你得先配环境。尤其是做VCU开发,有几个关键配置项必须搞定。
4.1.1 必备工具箱检查
做VCU应用层建模,下面这几个工具箱是标配。缺一个,后面就可能干到一半发现“此路不通”。
| 工具箱名称 | 用途 | 是否必须 |
|---|---|---|
| Simulink | 基础建模环境 | 必须 |
| Stateflow | 状态机建模(模式切换、故障处理) | 必须 |
| Embedded Coder | 生成嵌入式C代码 | 强烈推荐 |
| Simulink Design Verifier | 模型静态检查、测试用例生成 | 推荐 |
| Vehicle Network Toolbox | CAN/CANFD通信仿真 | 视项目而定 |
我的小技巧:在MATLAB命令行输入 ver,可以查看已安装的工具箱列表。别等到项目中期才发现缺东西,那时候再补授权流程,能急死人。
4.1.2 求解器与步长设置
做VCU模型,我建议用固定步长求解器。为什么?因为VCU的底层任务通常是周期调度的,比如10ms、5ms。你用变步长求解器,仿真结果可能很漂亮,但生成代码后跑在芯片上,时间对不上,控制效果全乱套。
我个人习惯这样设置:
- 求解器类型:Fixed-step(固定步长)
- 求解器:discrete(离散)——VCU模型里几乎没有连续积分环节,用离散就够了
- 固定步长:0.01(对应10ms任务周期)
避坑指南:我曾经有个项目,同事用了变步长求解器,仿真结果完美。结果生成代码后,VCU在实车上跑起来,扭矩输出抖得像筛糠。查了两天才发现是求解器类型没改。从那以后,我要求团队所有VCU模型必须用固定步长+离散求解器。
4.2 基础模块使用——搭积木的艺术
Simulink建模,说白了就是搭积木。但积木怎么搭,搭出来稳不稳,这里面有门道。
VCU应用层里,最常用的基础模块就那么几个:In/Out、Gain、Sum、Switch。别小看它们,90%的控制逻辑都能用这几个模块拼出来。
4.2.1 In/Out模块——模型的“嘴巴”和“耳朵”
Inport(输入)和Outport(输出)是模型与外界通信的接口。在VCU里,输入通常来自传感器信号(加速踏板、制动踏板、车速等),输出则是给执行器的指令(电机扭矩、继电器通断等)。
命名规范很重要。我见过有人把Inport命名为“In1”、“In2”……等模型复杂了,根本分不清哪个是哪个。我的建议是:命名必须与信号名一致。
// 不好的命名
In1 -> 加速踏板开度
In2 -> 制动开关状态
// 好的命名
AccPedalPos -> 加速踏板开度
BrakeSwtSts -> 制动开关状态
4.2.2 Gain模块——信号调理的“放大器”
Gain模块就是乘一个系数。但你别小看它,在VCU里,传感器信号往往需要标定。比如加速踏板,ADC采回来是0-5V的电压,但VCU需要的是0-100%的开度。这时候,一个Gain模块就能搞定。
举个例子:
- 输入:加速踏板电压(0-5V)
- Gain系数:20(5V * 20 = 100%)
- 输出:加速踏板开度(0-100%)
经验之谈:Gain模块的系数,我建议用参数对象(Simulink.Parameter)来定义,而不是直接写死数值。这样后期标定时,可以直接在MATLAB工作空间里批量修改,不用打开模型一个一个找。
4.2.3 Sum模块——信号的“加减法”
Sum模块做加减运算。在VCU里,最常见的用法是闭环控制中的误差计算。
比如扭矩控制:
- 目标扭矩(+)
- 实际扭矩(-)
- 输出:扭矩误差
这个误差值,后面会送给PID控制器。嗯,PID我们后面章节会细讲。
4.2.4 Switch模块——逻辑的“分岔路口”
Switch模块是VCU控制逻辑的核心。它根据控制信号,选择不同的输出路径。
我举个例子,制动优先逻辑:
- 控制信号:制动开关状态(0或1)
- 输入1:0(制动未踩下,正常输出驾驶员需求扭矩)
- 输入2:0(制动踩下,输出0扭矩)
- 输出:最终扭矩指令
你看,一个Switch模块,就实现了“踩刹车就断动力”的安全逻辑。
关键点:Switch模块的阈值设置要小心。比如用“u2 >= Threshold”模式,阈值设成0.5,那制动开关信号0.6和0.4就会产生完全不同的结果。实际项目中,制动开关信号一定要做防抖处理,否则Switch会在临界点来回跳。
4.3 Stateflow状态机建模入门——让VCU“有状态”
基础模块能解决“线性”和“简单逻辑”问题。但VCU的控制逻辑,很多是状态依赖的。
比如:
- 上电初始化 -> 待机 -> 行驶 -> 故障 -> 下电
- 正常模式 -> 运动模式 -> 经济模式
这些场景,用Switch模块硬拼,模型会变成一团乱麻。这时候,Stateflow就派上用场了。
4.3.1 什么是状态机?
状态机,说白了就是“在什么状态,做什么事”。
一个状态机有三个要素:
- 状态(State):系统当前所处的模式
- 转移(Transition):从一个状态切换到另一个状态的条件
- 动作(Action):进入/退出/停留在某个状态时执行的操作
4.3.2 第一个Stateflow模型:VCU上电状态机
咱们来做一个最简单的VCU上电状态机。这个状态机有三个状态:
- OFF:VCU未上电,所有输出为0
- INIT:上电初始化,自检、传感器校准
- READY:就绪,可以响应驾驶员操作
转移条件:
- OFF -> INIT:钥匙上电信号(KeyOn == 1)
- INIT -> READY:自检完成(SelfCheckDone == 1)
- READY -> OFF:钥匙下电信号(KeyOn == 0)
在Stateflow里,这个状态机画出来就是三个方框,几条带箭头的线。每个方框里可以写进入动作(entry:)、离开动作(exit:)、持续动作(during:)。
// Stateflow伪代码示例
State OFF {
entry: MotorTorqueCmd = 0; // 进入OFF状态,扭矩指令清零
on KeyOn == 1: goto INIT; // 检测到上电信号,跳转到INIT
}
State INIT {
entry: StartSelfCheck(); // 进入INIT状态,启动自检
on SelfCheckDone == 1: goto READY; // 自检完成,跳转到READY
on KeyOn == 0: goto OFF; // 中途下电,回到OFF
}
State READY {
entry: EnableDriverInput(); // 进入READY状态,使能驾驶员输入
on KeyOn == 0: goto OFF; // 检测到下电信号,回到OFF
}
避坑指南:我曾经在项目里犯过一个低级错误——状态转移条件没做防抖。结果钥匙信号在临界点抖动,VCU在OFF和INIT之间来回跳,自检永远完不成。后来加了50ms的延时确认,问题才解决。记住:所有来自硬件的状态切换信号,都必须做防抖处理。
4.4 本章知识体系总览
下面这张图,把本章的核心知识点串起来了。你可以把它当作一个“思维导图”来看。
4.5 本章小结
这一章,我们走完了Simulink建模的“入门三件套”:
- 环境配好:工具箱、求解器、步长,一个都不能少
- 积木搭对:In/Out、Gain、Sum、Switch,四个模块玩转基础逻辑
- 状态机入门:Stateflow让VCU“有状态”,上电状态机就是第一个实战案例