做混动整车仿真这几年有一个体会特别深并联式混合动力系统Simulink控制策略模型表面上是个建模问题实际上是个决策问题。它真正检验的不是你会不会搭Simulink模块而是你能不能把“发动机和电机分别在什么时刻出力、各出多少力”这件事想清楚、写明白。前两年我搭这套并联式混合动力控制策略模型时踩了不少坑从工况数据导入格式不对、代数环导致仿真跑不动到模式切换逻辑频繁跳变、SOC持续跌落几乎把新手能遇到的问题都过了一遍。这篇文章打算把整个搭建过程完整拆开来讲覆盖并联式混动的工作模式、Simulink模型架构、规则式能量管理策略的实现细节、工况自定义方法以及仿真结果的分析和常见问题排查。如果你正在搭或者准备搭并联式混动控制策略模型希望这篇能帮你少走点弯路。1. 并联式构型的控制逻辑到底在管什么1.1 并联式混合动力的工作模式速览并联式混合动力的结构特征简单说就是发动机和驱动电机都通过机械路径连接到了传动系统两个动力源都能独立驱动车轮也能耦合在一起共同出力。这和串联式有个明显区别串联式的发动机只负责发电不直接驱动车轮并联式则有发动机机械直驱这条路径传动效率更高但控制起来也更复杂。我在实际建模时先做了这样一步把工作模式全部列出来再一个一个梳理切换条件。并联式混动常见的模式有这几类。纯电动模式发动机停机电机单独提供驱动扭矩。适合起步、低速巡航、倒车等场景。发动机单独驱动模式电机不参与驱动由发动机经变速器直接驱动车轮。高速巡航时用这个模式通常效率最优。混合驱动模式发动机和电机同时输出扭矩。急加速、大负荷爬坡时驾驶员需求扭矩超过了发动机单机能力或者最优工作区间的上限电机就作为动力补充。行车充电模式发动机除了维持车辆行驶所需功率外还额外输出一部分功率给电池充电。SOC偏低时需要进入这个模式。制动能量回收模式松开加速踏板或者踩制动时电机反转运行作为发电机把整车动能转化为电能回充到电池。怠速/停机模式车辆静止或者不需要动力输出时发动机熄火或怠速避免无谓的油耗。模式划分没有标准答案有的策略还把“起发动机时用电机辅助拖动”单独拆成一种模式有的则把低速纯电和倒车纯电区分开。我建议按你的控制需求来定不必过度细分但也不要少了对关键场景的覆盖。注意模式定义越细切换逻辑就越复杂调试时状态机反复跳变的概率也越高。第一次建模时建议先保守一点用5到6个基本模式把主要场景覆盖住跑通了再逐步细化。1.2 控制策略要解决的核心问题扭矩分配、模式切换、SOC维持并联式混动的控制策略本质上是在回答三个问题这三个问题也是Simulink模型里控制策略子系统的三大输出任务。第一个问题当前时刻整车应该工作在哪个模式这个判断依赖车速、驾驶员需求扭矩、SOC、发动机状态等信号。模式切换过快会让车辆有顿挫感切换太慢又可能导致动力不足或者电量失衡。它是一个典型的离散决策问题。第二个问题在混合驱动模式下需求扭矩如何分配给发动机和电机按照什么原则分最常见的思路是先让发动机工作在燃油经济性较优的区域剩余扭矩由电机补足或吸收。第三个问题如何让SOC在整个仿真周期内保持平衡纯电模式下SOC会持续下降行车充电模式下SOC会回升。策略需要设定一个SOC目标带让SOC在带内波动既不深度放电损伤电池也不频繁充电浪费燃油。这三个问题并不是独立存在的。模式切换要参考SOC扭矩分配要考虑电池的放电能力SOC维持又依赖行车充电模式和回收策略。在Simulink里建模时这三个逻辑通常都集中在同一个控制策略子系统内共享同一组输入信号输出互相耦合。这也是为什么很多人觉得并联式混动控制策略比串联式难做的原因。1.3 为什么选择Simulink来做策略验证可能有人会问控制策略用C代码写不行吗为什么非要用Simulink我的一个切身体会混动控制策略开发是一个反复迭代的过程。策略要不断改、不断试今天调整一下扭矩分配系数明天加一个模式切换约束条件。如果用C代码写每次改动都要重新编译、重新对接整个仿真环境效率很低。Simulink的模块化建模天然适合这种快速迭代的节奏。另外Simulink里做策略仿真是分层的底层是整车纵向动力学模型、发动机模型、电机模型、电池模型上层是控制策略。想换策略的时候只需要动控制策略子系统底层部件模型可以完全复用。如果后面要往实车控制器移植还可以用自动代码生成工具把控制策略子系统直接生成C代码。还有一个很实际的原因Simulink的调试手段丰富Scope、Data Inspector、信号日志都能用仿真结果可视化非常方便。策略里某个参数不合理跑完一看曲线就能定位到问题。2. Simulink模型的整体架构与各子系统划分2.1 模型顶层布局从驾驶输入到整车纵向动力学搭建并联式混动Simulink模型我建议按照信号流的方向组织顶层架构。一个完整的并联式混动整车模型大致包含以下子系统子系统主要功能关键输入关键输出驾驶工况输入提供目标车速曲线即测试工况时间目标车速驾驶员模型模拟驾驶员对工况的跟踪行为目标车速、实际车速加速踏板开度、制动踏板开度整车控制器策略能量管理与扭矩分配决策踏板开度、转速、SOC、档位发动机扭矩请求、电机扭矩请求、模式指令发动机模型输出发动机可用扭矩与油耗发动机扭矩请求、转速实际扭矩、燃油消耗率电机及控制器模型实现电机驱动/发电电机扭矩请求、转速、母线电压实际扭矩、电功率电池模型模拟电池充放电动态与SOC计算电功率需求、SOCSOC、开路电压、母线电压传动系统模型变速器、主减速器、车轮耦合发动机扭矩、电机扭矩、档位驱动扭矩、转速整车纵向动力学模型计算车辆阻力与车速响应车轮驱动力、制动需求实际车速、轮端转速搭这个顶层结构时我习惯让信号流保持单向尽量避免形成大的反馈回路。比如驾驶员模型的输出是踏板开度整车控制器根据踏板开度计算需求扭矩再分别给发动机、电机发扭矩请求部件模型返回实际输出扭矩最终通过动力学模型算出实际车速实际车速又反馈回驾驶员模型。这条链路里反馈是必然的但要让各个子系统内部的信号尽量单向流动这样后面排查问题会轻松很多。2.2 控制策略子系统的信号流与参数来源控制策略子系统是并联式混动仿真的核心。它的输入输出设计直接决定了模型的灵活性。我在模型里给控制器定义的输入信号包括加速踏板开度、制动踏板开度、实际车速、发动机转速、电机转速如果发动机和电机转速不同轴则分别采集、SOC、当前档位。输出信号包括发动机扭矩请求、电机扭矩请求、模式状态、发动机启停指令、变速器目标档位。有一点值得注意发动机和电机的扭矩请求必须区分“驱动扭矩”和“发电扭矩”。如果电机工作在发电状态它的扭矩就是负值。很多第一次建模的人会在这里把符号搞混导致策略里扭矩分配方向反了电机一边放电一边又在发电SOC曲线乱得没法看。部件模型的参数来源我踩过一些坑之后总结出一个比较可靠的做法把参数统一放在模型初始化脚本里集中管理。发动机的外特性曲线、万有特性油耗Map、电机效率Map、电池开路电压与内阻数组、整车质量、风阻系数、轮胎半径、主减速比等全部在脚本里定义为变量模型中直接用变量名引用。这样做的原因是Simulink模型文件里如果写死了数值每次改参数都要打开模型改模块效率低且容易出错。用脚本管理参数后改策略标定参数时只要改脚本、重新初始化再运行模型即可。后面做参数扫描或优化时这个习惯能帮你省下大量时间。2.3 各部件模型建模时的一些取舍经验部件模型的精度怎么选是很多人容易纠结的问题。我的建议是先保证策略闭环能跑起来再逐步增加模型复杂度。发动机模型不需要用复杂的燃烧模型用查表模型就够了。输入是转速和扭矩请求输出是当前转速下能输出的最大扭矩、实际扭矩、燃油消耗率。最大扭矩来自外特性曲线燃油消耗率来自万有特性Map。这套模型结构简单仿真速度快策略验证的精度完全够用。电机模型同理用效率Map查表的方法建模。输入是转速和扭矩请求输出是实际扭矩和电功率。计算电功率时要注意效率的方向性驱动时电功率 机械功率 / 效率发电时电功率 机械功率 × 效率。这个方向如果搞反了电池的SOC保护逻辑就会出问题。电池模型最常用的是Rint等效电路模型也就是一个理想电压源串联一个内阻。输入是电功率需求输出是直流电流、端电压和SOC。SOC用安时积分法计算仿真里足够用。传动系统模型把发动机、电机的扭矩按照当前档位的传动比和主减速比换算到轮端。如果采用单轴并联构型发动机和电机在变速器输入端就完成了扭矩叠加只需要一个输入扭矩即可如果采用双轴并联构型则要按耦合齿轮的速比进行计算模型稍复杂一些。提示如果你的模型里发动机和电机各有独立的转速注意先确认整车架构是同轴耦合还是分轴耦合。很多建模错误都出在这里因为同轴并联模式下发动机和电机转速是绑定的不存在两个独立转速而分轴并联则存在转速差扭矩叠加公式完全不同。3. 规则式控制策略从设计到实现3.1 模式定义与切换条件设计并联式混动控制策略里工程上用得最多、最稳定可靠的还是规则式策略。所谓规则式就是人为设定一系列判断条件根据当前车速、SOC、需求扭矩等信号决定车辆进入哪个模式以及如何分配扭矩。以我搭建的模型为例我把模式切换条件整理成了一张表用Stateflow来实现模式切入条件退出条件纯电动EV车速 60km/h、SOC 35%、需求扭矩 电机峰值扭矩、发动机处于停机状态任一条件不满足发动机单独驱动车速 60km/h、SOC 35%、需求扭矩在发动机高效区内需求扭矩超出高效区上限/下限、SOC低于阈值混合驱动需求扭矩 发动机外特性扭矩的90%、且这时车速 20km/h需求扭矩回落到发动机可独立承担范围行车充电SOC 35%、车速 20km/h、发动机已启动SOC回升至40%以上或车辆进入停车状态制动能量回收制动踏板开度 0 或 加速踏板开度 0 且车速 5km/h车速过低或SOC 95%停机车速 0 且无起步需求驾驶员踩下加速踏板这里面的数值只是我测试时用的初版标定值实际项目里要根据目标车型的动力参数、工况特征重新标定。但逻辑框架是通用的先根据车速决定能否进入纯电根据需求扭矩决定要不要启动发动机根据SOC决定要不要充电根据制动信号决定是否回收。有一类在策略初稿阶段很容易犯的错误模式切换条件之间互相覆盖导致状态机在几个模式之间高频跳变。比如车速在59km/h附近波动时纯电模式和发动机驱动模式之间来回切换发动机会在短时间内反复启停。解决思路是给切换条件设置滞后区间比如纯电切入车速是60km/h退出发动机模式的回滞车速设为55km/h。两个临界值之间留5km/h的缓冲带就能避免这种高频启停问题。3.2 扭矩分配算法的MATLAB Function实现模式定义完之后下一步就是最核心的扭矩分配逻辑。我在模型里用MATLAB Function模块来写这部分因为它比纯Simulink模块画出来的逻辑更容易阅读和维护。下面是一个简化版的策略代码结构可以作为参考function [T_eng_req, T_mot_req, mode] energy_mgt(acc_pedal, brk_pedal, speed, soc, T_demand, T_eng_max) % 输入: % acc_pedal : 加速踏板开度 0-1 % brk_pedal : 制动踏板开度 0-1 % speed : 当前车速, km/h % soc : 电池荷电状态 0-1 % T_demand : 驾驶员需求扭矩, Nm % T_eng_max : 当前转速下发动机最大扭矩, Nm % 输出: % T_eng_req : 发动机扭矩请求, Nm % T_mot_req : 电机扭矩请求, Nm % mode : 模式标志位 mode 0; T_eng_req 0; T_mot_req 0; % 制动回收模式 if brk_pedal 0 mode 5; T_mot_req -brk_pedal * T_demand * 0.5; % 回收扭矩不超过总制动需求的一半 return; end % 停车状态 if speed 0.5 acc_pedal 0.1 mode 6; return; end % 纯电模式 if speed 60 soc 0.35 T_demand 0.9 * T_eng_max mode 1; T_mot_req T_demand; return; end % 低SOC时行车充电 if soc 0.35 speed 20 mode 4; T_eng_req min(T_eng_max, T_demand 10); % 额外增加10Nm扭矩用于发电 T_mot_req -10; % 电机发电, 负扭矩 return; end % 混合驱动: 需求扭矩超出发动机经济区 if T_demand 0.85 * T_eng_max mode 3; T_eng_req 0.85 * T_eng_max; T_mot_req T_demand - T_eng_req; return; end % 发动机单独驱动 mode 2; T_eng_req T_demand; T_mot_req 0;这段代码的逻辑很直观适合做第一版跑通流程。当然它的策略相对粗糙扭矩分配系数是固定的。实际项目中我见过比较好的做法是把“发动机工作在最优经济曲线”写成查表逻辑发动机扭矩请求不是简单地取固定系数而是根据当前转速查经济曲线得到最优扭矩然后让电机去补足剩余部分。把这个MATLAB Function放进Simulink的MATLAB Function模块里时要注意端口的尺寸和数据类型保持一致。一个常见的报错是“Data type mismatch”通常是某个信号线没设置好解决办法是在模型里加Data Type Conversion模块做显式转换。3.3 发动机启停控制与SOC平衡处理发动机启停控制是整个策略里看起来简单、实际最容易出问题的部分。很多初学者把发动机启停简单理解成“SOC低了就启动发动机”但实际工程里要考虑的细节多得多。发动机频繁启停不仅影响燃油经济性还会加速起动电机和发动机零部件的磨损。另外发动机从停机到稳定运行的动态过程在Simulink模型里如果描述得太简略会导致仿真结果偏乐观。我的处理思路是在策略里加一个“发动机运行延续时间计数器”。也就是说发动机一旦启动至少要运行一段时间比如30秒即使这期间已经满足了停机条件也先保持运行状态。这个逻辑在Stateflow里实现很自然用一个驻留时间的计时状态就能搞定。SOC平衡方面我采用的是目标带控制法。设定目标SOC为50%当SOC落在45%到55%区间内时策略不做额外的充电操作只按常规逻辑分配扭矩当SOC高于55%时偏好多用电驱适当推迟发动机介入当SOC低于45%时偏好多用发动机并视情况增加一点充电功率当SOC低于30%时强制进入行车充电模式同时限制电机驱动功率。目标带控制的好处是策略行为可预期不会因为SOC的微小波动引发模式频繁切换。需要注意的是SOC的仿真初值要设置合理。如果你把SOC初值设成80%又在低SOC阈值设为30%的策略里做长工况仿真那前半程SOC可能始终在阈值之上行车充电逻辑根本没机会触发整个策略验证就算白做了。4. 工况自定义的实现方式4.1 内置工况库与自定义工况数据导入并联式混动仿真的一个核心需求就是“工况可自行添加”。这一点我能理解因为单纯靠内置的几组标准工况很难模拟出实际使用场景。我做模型时常用的是下面两种工况导入方式。第一种是直接用Simulink里的Drive Cycle Source模块。这个模块自带了一些常见工况可以用来做标准测试。比如你做完一个策略想快速验证逻辑是否正常选一段标准工况直接跑一遍非常方便。第二种是自定义工况。真正的实际项目里客户给的往往是特定路段的实测车速数据或者自定义的测试工况。这时就需要把工况文件导入模型中。我用得最顺的方法是把工况数据存放在Excel或MAT文件里通过模型初始化脚本加载到工作空间再由Drive Cycle Source模块读取。具体操作流程是这样的准备两列数据第一列是时间序列单位秒第二列是对应的车速单位km/h。在模型初始化脚本里用xlsread或readmatrix读取Excel文件生成时间向量t和车速向量v。在模型里放置Drive Cycle Source模块双击打开配置界面设置从工作空间读取填写对应的变量名。把仿真时长设置为工况的总时长。有一个点要特别注意Drive Cycle Source模块读取的数据格式要求是结构体或时序信号。如果直接用两个数组赋值需要在配置界面里勾选正确的数据格式选项否则会报“Invalid Drive Cycle Data”之类的错误。我一般是在初始化脚本里习惯性构造一个含time和signals字段的结构体一步到位。4.2 工况文件的格式要点与常见坑工况文件看似简单但格式问题却是我见过最多的报错来源。这里分享几个实际踩过的坑。单位问题工况数据里的车速单位必须和驾驶员模型内部的速度单位一致。Simulink模型内部如果用的是m/s而工况文件给的是km/h那仿真结果一定是车速跟不上目标偏差大得离谱。我的做法是在读取工况数据的脚本里做一次强制换算把单位统一成模型内部单位。时间步长问题标准工况数据通常是1秒一个点Drive Cycle Source模块内部自带线性插值1秒间隔完全够用。但如果你自己采集的真实工况数据时间间隔不均匀比如有的0.5秒、有的1.2秒直接导入后模块也能处理但要注意原数据的采样率不能太低否则车速曲线会严重失真。仿真步长设置模型求解器的步长设置要和工况时间步长匹配。我在做并联式混动仿真时习惯把模型配置成变步长、最大步长设为0.1秒。如果把最大步长设得太大比如等于工况采样间隔的整数倍就可能丢失一些瞬态响应影响控制策略的评估结果。% 自定义工况加载脚本示例节选 t (0:1:1200); % 1200秒时长 v interp1([0 200 400 600 800 1200], [0 40 60 0 30 0], t, linear); v max(v, 0); % 车速不允许为负 drive_cycle.time t; drive_cycle.signals.values v; % 构造Drive Cycle Source需要的数据格式 drive_cycle.signals.dimensions 1; v v / 3.6; % km/h 转 m/s供驾驶员模型使用工况突然跳变问题自己拼工况时很容易把车速从一个值瞬间跳到另一个值。比如200秒时车速是60km/h201秒直接变成0。这样的工况在仿真里会产生一个非常大的减速度需求策略会瞬间请求很大的制动能量回收扭矩。这不是工况本身的错但如果回收扭矩限值没有约束好电池就会收到一个过大的充电功率请求容易引起SOC在短时间内异常跳升。我的建议是自建工况时给车速曲线增加一个斜坡过渡环节例如用速率限幅模块把目标车速的变化率限制在3m/s²以内更贴近真实驾驶行为。5. 仿真结果处理与常见问题排查5.1 仿真输出图像如何看车速跟随、SOC轨迹、发动机工作点标题里提到的“仿真图像包括”后面虽然内容没有写完但我猜里面大概率包含这几类曲线目标车速与实际车速对比图、SOC随时间变化曲线、发动机工作点分布图、电机扭矩曲线、电池充放电功率曲线。这些曲线里我最先看的是目标车速与实际车速的跟随效果。如果在某些时间段实际车速明显跟不上目标需要优先检查驾驶员模型的PID参数。驾驶员模型本质上是目标车速和实际车速的偏差控制器PID参数设得不好车辆就会表现出起步反应慢、超调、震荡等问题。第二看的是SOC轨迹。SOC曲线能直接反映策略的能耗平衡能力。如果SOC在仿真后期持续走低说明策略整体偏向用电充电逻辑触发得不够如果SOC始终在高位附近徘徊说明发动机介入太积极策略的节油潜力没有充分发挥。正常一个完整的循环工况跑下来SOC的终值和初值差距应该在合理范围之内波动幅度大致在预设SOC带的边界之间。第三看的是发动机工作点分布。把仿真过程中每个时刻的发动机转速和扭矩提取出来叠加到发动机万有特性Map上就可以直观看出策略是否让发动机工作在经济区域内。如果大量工作点集中在高油耗区说明扭矩分配策略的分配系数需要调整。5.2 仿真报错排查代数环、数值发散、状态机卡死做并联式混动Simulink模型时有几个报错或者异常现象非常典型我逐一分享一下排查经验。代数环问题。代数环在控制策略模型里几乎是必遇的。典型场景是整车控制器需要根据电机扭矩计算电池功率电池功率又反过来影响控制器可用功率。Simulink会提示但很多情况下只是警告不终止仿真。如果代数环参与的是高增益回路仿真步长会被压得极慢甚至出现数值振荡。我的处理方式是在反馈回路里加Memory模块或Unit Delay模块打破代数环。这个方法会引入一步延迟对于控制策略验证来说影响很小但能大幅加速仿真。数值发散问题。仿真跑到某个时间点后车速变成NaN或者无穷大通常原因有两个一是某个查表模块的输入超出了给定的断点范围查表外推得到异常数值二是模式切换瞬间产生了过大的扭矩阶跃让动力学积分器无法收敛。查表问题好解决把输入限幅到断点范围内扭矩阶跃问题则需要检查模式切换逻辑必要时给扭矩请求加上变化率限制。状态机卡死。Stateflow里某个模式进入后无法退出仿真就一直卡在一个固定状态。这个问题的排查方法是用Stateflow的调试功能单步执行查看状态转移是否按预期发生。我实际遇到最多的卡死原因是切入条件满足、但退出条件里包含了互斥的约束比如退出条件要求车速大于0而实际状态就是停在那里。单位错误导致的“假故障”。有一次电机扭矩始终偏大仿真结果怎么看怎么不对劲查了很久发现是扭矩单位混用了Nm和N·m换算问题。这类问题很难通过报错定位因为模型正常跑完了只是结果不对。我的经验是在初始化脚本里统一约定单位并在模型的关键信号线上做单位标注养成习惯后能少踩很多坑。一些实操体会最后分享一点个人体验。并联式混动Simulink模型搭建这件事最大的难点不在Simulink工具本身而在于你是否能把控制逻辑想清楚。工具层面的操作看几天教程就能上手但扭矩分配、模式切换、SOC平衡这些控制策略的决策点需要你对混合动力系统的工作特性有充分理解。我见过不少人一上来就追求模型复杂度把发动机瞬态过程、电池热模型、电机温度模型全都加进去结果模型越搭越重、仿真速度越来越慢控制策略的迭代效率反而大打折扣。我的建议是做混动控制策略验证部件模型够用就好参考精度只要能支撑策略层面的逻辑判断没有必要一上来就上高保真模型。先跑通逻辑再回头精修部件模型这条路走起来会更顺。另外如果还有余力可以把这套控制策略的参数标定和优化流程做成半自动化的脚本用批量仿真去扫描不同参数组合的效果那样你手里这套模型的可复用价值会高很多。