搞并联式混合动力控制的同学,十有八九都绕不开Simulink这套环境。最近整理项目交付资料,翻出之前做的一套并联式混合动力系统控制策略模型,正好借这个机会把建模思路、工况自定义、仿真图像分析这些实操细节系统地捋一遍。这套模型不是花架子,把驾驶员需求扭矩解析、模式切换状态机、扭矩分配和电池SOC协调都串起来了,工况可以自行往里加,跑完直接看仿真图像。如果你正在做混动整车控制策略开发、Simulink仿真的入门进阶,或者马上要毕设答辩,这篇应该能帮你省不少折腾时间。
1. 并联式混合动力系统:结构原理与控制需求
1.1 从串联、混联讲到并联:为什么选这种构型
混合动力系统构型大体分串联、并联和混联三类。串联结构发动机只驱动发电机,不直接驱动车轮,相当于一个增程式方案,能量要经历机械能到电能再到机械能的两次转换,高速工况效率吃亏。混联结构两套动力路径都保留,控制最复杂,成本也最高。并联结构则是发动机和电机通过机械耦合装置(比如离合器、齿轮箱或扭矩耦合器)共同驱动车轮,电机既可以做驱动,也可以做发电。
选择并联构型做控制策略模型,看中的是两点:一是结构相对简单,扭矩叠加关系清晰,控制策略的实现路径短;二是高速巡航工况下发动机效率区间好,不用像串联那样绕一圈电能转换,经济性表现扎实。当然并联也有它的难处——没有独立的发电路径来保证电池SOC的持续平衡,低速频繁启停时发动机工况点控制不好,油耗反而可能上去。所以在并联模型中,控制策略的核心任务之一,就是在合适的时候让电机“填坑”、在合适的时候让发动机“补电”,把两种动力源的效率揉到一起去。
1.2 多动力源协同的核心矛盾:扭矩分配与模式切换
并联式混动的本质矛盾,是两套动力源同时出现在轴上,谁出力、出多少力、什么时候由谁来主导,必须有一套决策规则。驾驶员的油门刹车踏板信号实际上是一个扭矩需求:踩油门,整车需要一个正的驱动扭矩;踩刹车,整车需要一个负的制动扭矩(先回收再生制动,再叠加机械制动)。发动机扭矩和电机扭矩加起来,要等于这个总需求扭矩,这个关系可以写成:
T_req = T_eng + T_mot(驱动工况)
在制动回收工况下,电机扭矩为负值,代表电机工作在发电状态,把动能转成电充进电池。
由此引出三个核心设计问题:第一,模式怎么定义——纯电、纯发动机、混合驱动、行车发电、再生制动,这些模式之间的切换条件是什么;第二,扭矩怎么分配——同一个模式下,发动机和电机各自的扭矩目标值如何计算;第三,系统级的约束怎么处理——电机外特性有扭矩上限,电池有SOC上下限,发动机有怠速转速和最低稳定扭矩,这些约束必须在分配逻辑里体现。控制策略模型的全部工作,就是围绕这三个问题展开的。
1.3 模型必须覆盖的工况类型
控制策略能不能验证,关键看工况覆盖是否全。我做这套模型时,至少内置了三类工况:
第一类是标准法规工况,比如NEDC、WLTC、CLTC,这些工况用于横向对比和方案评价,不同地区的标准差异比较大,WLTC的瞬态加减速频率明显高于NEDC,对模式切换逻辑的考验更严苛。第二类是自定义行驶工况,模拟特定场景,比如市区拥堵、郊区道路、高速巡航,可以通过车速-时间表来定义,这也是模型标题里“工况可自行添加”的设计诉求。第三类是极限与边界工况,比如急加速全油门、急减速制动、坡道起步、低温/高温环境下的功率限制等,这些工况主要用于压力测试,看控制策略在极端条件下是否会触发保护逻辑或者产生扭矩振荡。
我建议初学者先跑标准工况,把逻辑调试顺了,再自己构造组合工况去“折腾”模型。比如把市区拥堵低速段和高速段拼在一起,专门测试模式频繁切换时的平顺性和电量平衡能力,这比单跑一个标准工况更能暴露问题。
2. Simulink控制策略模型整体设计思路
2.1 顶层架构:从驾驶员需求到扭矩分配
搭建Simulink模型的习惯,先画顶层数据流。我用的架构是三层结构:输入层、决策层、执行层。
输入层负责处理驾驶员操作信号和整车状态信号,包括加速踏板开度、制动踏板开度、当前挡位、车速、电机转速、发动机转速、电池SOC、母线电压等。这里的核心处理逻辑是“踏板开度转扭矩需求”——加速踏板开度线性映射到一个驾驶员期望扭矩,但需要根据当前车速做修正,避免低温起步或者低速大踏板时给出超出物理能力的扭矩请求。
决策层是控制策略核心,负责接收输入信号,经过模式状态机识别当前应该处在什么工作模式,再根据模式执行扭矩分配算法,输出发动机目标扭矩和电机目标扭矩。执行层则负责输出到被控对象模型,包括发动机模型、电机模型、电池模型、传动系模型和车辆动力学模型。当然,如果你只做控制策略模型验证,被控对象可以用简化的等效模型替代,重点是控制逻辑本身。
2.2 模式定义与切换逻辑状态机
模式状态机是整个控制策略的骨架。我常用的模式划分如下:
- EV模式(纯电驱动):发动机停机或断开,电机单独驱动车辆,适合低速、低负荷、SOC充足时使用。
- 发动机驱动模式:发动机单独驱动车辆,适合中高速稳定工况,此时电机可空转或待机。
- 混动模式(联合驱动):发动机和电机同时驱动车辆,适合大扭矩需求,比如急加速、爬坡、高负载工况。
- 行车发电模式:发动机驱动车辆的同时带动电机发电给电池充电,适合SOC偏低但整车需求扭矩不高的场合。
- 再生制动模式:电机回馈制动,把车辆动能转化为电能充入电池,适合减速或制动工况,整车需求扭矩为负。
状态机的切换条件要综合考虑车速、SOC、需求扭矩、发动机效率、电子节气门需求等信号。在Simulink里,我习惯用Stateflow实现状态机,也可以用有限状态逻辑模块配合逻辑表达式实现。关键是状态切换必须设置迟滞区间,防止两个模式之间在边界处反复抖动。比如纯电模式切发动机模式,可以设置车速超过40 km/h且需求扭矩超过某个阈值时才切;切回纯电时,要等车速降到35 km/h以下或者扭矩需求显著降低时再切,这样可以避免临界点附近的振荡。
2.3 电池SOC与扭矩分层的协调策略
SOC是混动控制的眼睛。电池SOC的高低直接决定了控制策略偏向“用电”还是“用油”。我的策略思路是分SOC区间管理:
- SOC高(比如高于0.6),控制策略偏向维持纯电比例,优先用电,发动机尽量晚介入。
- SOC中等(0.3到0.6之间),维持电量平衡,发动机和电机协同工作,行车发电窗口逐步放开。
- SOC低(低于0.3),策略强制提高发动机介入度,必要时让发动机在高效点工作并额外带动发电,快速回充。
这里有个细节:SOC的上下限最好不要做成硬开关,建议做SOC修正系数,去乘扭矩分配系数,实现“软约束”。例如发动机扭矩占比的修正系数,在SOC偏低时增大,在SOC偏高时减小。这样模型跑起来更平滑,不会因为SOC在边界跳变导致整车扭矩突然插动。我还习惯把电池充放电功率限制做成一个二维查表,横轴是SOC,纵轴是温度,输出是允许的充电/放电功率上限。这样电池模型和保护逻辑就直接闭环了,不会在仿真中让电机请求一个超出电池能力的功率导致电压骤降甚至仿真发散。
3. 控制策略实现细节与Simulink搭建实操
3.1 输入信号处理与工况自定义方法
先说输入信号处理。Simulink模型中对工况的导入,有几种常用路径。最简单粗暴的方法是用Signal Builder块或者Signal Editor块,直接把时间序列数据拖进模型。但我个人更推荐用From Workspace或者From Spreadsheet块,配合一个MATLAB脚本把工况数据(时间、车速、坡度、挡位等)写成矩阵或时间序列对象,然后载入模型。这样做的好处是批量跑工况时不用反复在GUI里拖拽,脚本一改就全换了。
如果你要自行添加工况,我提供一个标准做法。在MATLAB工作区定义一个结构体变量:
cycle.time = (0:0.1:1800)'; % 时间列,单位秒 cycle.signals.values = [v_kmh, grade_percent]; % 第一列车速(km/h),第二列坡度(%) cycle.signals.dimensions = 2;然后用From Workspace块,参数设置为cycle,采样时间设为0.1。模型内部再用查表或者线性插值,把车速(km/h)转成m/s,同时把坡度角转成坡度阻力扭矩叠加到需求扭矩上。这样从NEDC换到WLTC,你只需要替换cycle变量里的时间和车速列,模型内部不用动一根线。
3.2 扭矩分配核心逻辑:基于规则的能量管理
并联式混动控制策略里,最经典也最稳妥的是基于规则的能量管理策略。所谓规则,本质上是一组“如果-那么”的判定,把不同的需求扭矩和状态组合映射到发动机、电机的目标扭矩上。我给模型定的核心规则如下:
如果是制动工况(需求扭矩为负),优先从再生制动取值,再根据电池SOC修正回收扭矩强度。这里必须要设置一个回收扭矩下限,防止在电池接近满充时仍然强制回收,导致过充保护。
如果是驱动工况,先看SOC。SOC低时,再结合需求扭矩大小决定是否启动发动机。如果需求扭矩小于发动机经济扭矩下限,可以让发动机在高效点工作,同时把多余扭矩发电给电池充电,这属于行车充电的工况。
如果需求扭矩大于发动机当前经济扭矩上限,差额由电机补齐,进入联合驱动模式。注意这个“差额”不能超过电机峰值扭矩,如果超过,则整车实际输出扭矩会被限制,即扭矩源出现饱和,模型要加限幅。
在发动机启动的条件中,还要叠加发动机起动最小转速和当前车速的关系。发动机转速过低时不宜直接结合到传动系,否则会发生拖转,引起严重的转速冲击。
发动机目标扭矩的计算,我用的方法是查经济扭矩表,横轴是发动机转速,纵轴是节气门需求,查出在该转速下发动机的最优扭矩点或者在最佳燃油消耗率曲线附近的扭矩值。电机目标扭矩则由总需求扭矩减去发动机实现扭矩得到,再经过电机外特性表限制在峰值扭矩范围内。
3.3 状态机与查表模块的实现细节
状态机用Stateflow实现时,有几点值得注意。第一,状态切换条件不要只写一个信号表达式,尽量把条件拆成逻辑组合,减少信号噪声引起的误触发。比如判断“发动机启动”,条件可以是:需求扭矩>阈值,车速>阈值,SOC<阈值,三者的逻辑与。第二,状态内部的动作最好区分为进入动作(entry)、驻留动作(during)、退出动作(exit),这样可以在进入发动机模式时初始化发动机目标扭矩为当前可用的最小稳定扭矩,避免从纯电切入时扭矩从0突变。第三,Stateflow的默认转移方向要设置明确,不要让两个状态之间的转移互相纠缠,导致不可达状态。
查表模块方面,我通常会建立以下几个二维查表:
- 发动机外特性扭矩表:横轴发动机转速,纵轴节气门开度,输出最大可用扭矩。
- 电机外特性扭矩表:横轴电机转速,纵轴母线电压或SOC修正系数,输出驱动/回馈峰值扭矩。
- 电机驱动效率表、发电效率表:横轴转速,纵轴扭矩,输出效率,用于估算电耗。
- 电池开路电压和内阻表:横轴SOC,纵轴温度,用于电池模型计算。
查表模块建议使用Lookup Table (n-D) 并勾选“线性插值,端点外推”还是“端点饱和”要看场景。扭矩限制表建议用端点饱和,防止查表外推出现超出物理极限的数值;效率表建议用线性插值,提高精度。这个细节看似小,但在仿真跑极端工况时直接影响结果会不会失真。
3.4 仿真图像分析与验证指标
仿真完成后,图像分析是最能反映策略好坏的环节。我一般分四组图看。
第一组是车速跟随图:目标车速 vs 实际车速。如果两者贴合紧密,说明车辆动力学模型和控制策略配合正常;如果实际车速偏离目标,优先排查扭矩需求解析是否合理、整车阻力是否设置正确。
第二组是扭矩分配图:总需求扭矩、发动机扭矩、电机扭矩画在同一张图里,用不同线型/颜色区分。这张图可以直观看到哪个时刻谁在出力,模式切换点是不是合理,是否出现扭矩跳变。正常情况,切换瞬间发动机扭矩应该从最小稳定扭矩开始平缓爬升,而不是从0瞬间跳到300 Nm。
第三组是模式切换状态图:把模式编号(1代表EV,2代表发动机模式,3代表混动,4代表行车发电,5代表再生制动)输出成信号并绘图,结合扭矩图看切换时机是否跟预期一致,切换频率是否过高。
第四组是SOC和油耗(或电耗)累积图:SOC曲线看电量平衡情况,标准工况一个完整周期下来SOC末值不应跟初值差太远(除非是纯电消耗测试场景)。累计油耗曲线用来比较不同策略的优劣。
这里提供一个我常用的油耗统计方法:在仿真循环里对发动机瞬时燃油消耗率积分,输出累计油耗(单位升或者克),再根据工况总里程计算百公里油耗,这样不同工况之间才有可比性。
4. 工况自定义与批量仿真的实操技巧
4.1 如何把自定义工况导入Simulink
我把前面提过的From Workspace方法再细化一下。实际操作中,你需要先用脚本生成工况矩阵,比如:
% 自定义工况:0-500秒城市低速,500-800秒郊区,800-1200秒高速 t = (0:0.1:1200)'; v1 = interp1([0 300 500], [0 60 0], t(1:5001)); % 第一段 v2 = interp1([0 200 300], [0 80 0], t(5002:8001)); % 第二段 v3 = interp1([0 400], [0 120], t(8002:12001)); % 第三段 v = [v1; v2; v3]; v = min(v, 120); % 限速 cycle.time = t; cycle.signals.values = [v, zeros(size(v))]; % 第二列为坡度,暂时为0 cycle.signals.dimensions = 2;然后模型里的From Workspace块,名称填cycle,运行前把脚本跑一遍即可。如果你想更灵活,可以建一个MATLAB函数脚本函数,输入工况名称参数,输出对应的cycle结构体。这样以后加新工况,只需要扩展一份文本数据文件,例如Excel或者CSV,脚本读表并生成cycle,不用逐行改代码。
4.2 多工况仿真自动化与参数扫描
手动一个一个跑工况太慢,批量跑才是正经做法。我建议搭一个主脚本,用sim函数带参数方式执行模型仿真。做法是把模型参数都设置成工作区变量,比如电机峰值扭矩参数,电池容量参数,然后写循环遍历不同工况和参数组合:
cycles = {'NEDC', 'WLTC', 'CLTC', 'City_custom', 'Highway_custom'}; params = [case1_params; case2_params; case3_params]; % 每种参数组合一行 for i = 1:length(cycles) assignin('base', 'cycle', loadCycleData(cycles{i})); for j = 1:size(params, 1) setModelParams(params(j,:)); simOut = sim('PHEV_Control_Model', 'StopTime', '1200'); % 收集指标,保存到表格 fuel_calc(i,j) = extractFuel(simOut); end end这样跑完之后,直接得到一个对比矩阵,谁优谁劣一目了然。要注意,批量仿真时模型里不要有手动开关或弹窗提示,所有模式、参数都必须从工作区绑定,否则脚本每跑一步就要停下来等人点鼠标,效率极低。
4.3 仿真结果提取与可视化方法
模型仿真完,结果数据在simOut里,可以用如下方式提取:
logsOut = simOut.get('logsOut'); v_actual = logsOut.get('VehicleSpeed').Values.Data; t_eng = logsOut.get('EngineTorque').Values.Data; t_mot = logsOut.get('MotorTorque').Values.Data; t_req = logsOut.get('ReqTorque').Values.Data; mode = logsOut.get('ModeState').Values.Data; time = logsOut.get('ModeState').Values.Time;然后直接用MATLAB的figure绘图。我习惯把多工况结果叠加在一张图上用不同透明度对比,容易看出趋势。模拟图像导出时,保存为矢量图(svg或者pdf)放论文和报告里效果更好,不要用截图。
5. 常见问题与排查技巧实录
5.1 模型发散与代数环问题
Simulink仿真发散,十有八九是代数环或者控制器增益设置不当。代数环常见于扭矩需求信号和转速信号相互依赖的环节,比如发动机扭矩决定转速,转速又通过传动比影响电机转速,电机转速又反过来决定扭矩限值。解决办法是在环中加一个memory或者unit delay,把信号打一拍断环,或者用求解器配置改一下代数环处理方式。注意加延迟会影响控制相位,加入的位置尽量在非关键的滤波环节里加,别在扭矩主通道里乱加。
另一个导致发散的常见原因是积分器和限幅搭配不对。比如车速是通过驱动力减去阻力后积分得到的,如果驱动力信号过大而阻力限幅没有做,时间长了一积分数据就飞了。我建议在积分环节前设置物理限幅,比如车速不超过200 km/h、扭矩不超过外特性曲线值,防止模型飞出物理边界。
5.2 模式切换瞬间的扭矩跳变处理
这是并联混动模型最经典的问题。发动机模式切入瞬间,如果发动机目标扭矩直接从0给定到300 Nm,整车必定顿挫。处理办法在于两点:一是引入扭矩速率限制模块,比如发动机扭矩变化率限制在200 Nm/s以内;二是让离合器(或者扭矩耦合机构)在结合前先做转速同步,进入状态机的“启动发动机”子状态,等发动机转速接近电机转速后再接合。在简化的控制策略模型里,如果不对动力学做太细的模拟,至少要加一个一阶惯性环节模拟扭矩上升过程,否则图像分析时你会看到阶跃跳变,结果看起来像逻辑bug,其实差的是平滑处理。
5.3 SOC初始值与收敛问题
SOC初始值设置会影响仿真结果,尤其是单循环仿真的末尾SOC]。做WLTC这种长周期工况时,如果初始SOC设得偏低,控制策略会倾向于持续发动机行车发电,导致前半段油耗偏高;如果初始SOC设得偏高,电机介入多,电耗高但油耗偏低,末尾SOC可能掉到下一个循环低电量区间。为了做公平对比,我建议把初始SOC统一设为0.5或0.6,并且跑两个连续循环,看第二个循环的SOC末值与初值之差是否趋近于零,大约调用一次就稳定。如果出现SOC持续下降,就要调整行车发电阈值,让发动机在较低负荷时多发电;如果SOC持续上升,则要放宽纯电使用窗口。
5.4 仿真时间与步长设置误区
仿真步长设置上,固定步长和变步长各有适用场景。控制策略层面我建议用固定步长0.01秒或0.001秒,这样和实际ECU控制周期更接近,状态机和时间相关逻辑也更容易对应。如果用变步长,可能在模式切换点附近步长突然变小,耗时猛增,而固定步长能保证全仿真过程行为一致。制动回收工况对步长比较敏感,如果步长太大,车速变化剧烈时扭矩积分误差会积累,建议制动工况加密步长。另外,Simulink中如果你用了Pulse Generator这类模块产生PWM信号,固定步长一定要是PWM周期的约数,否则输出波形会出现毛刺。
6. 控制策略的标定参数与可扩展方向
6.1 关键标定参数的整定思路
控制策略模型里,有很多阈值类参数需要整定。常碰到的几个参数包括:
- 发动机介入车速阈值,一般设置在30~50 km/h之间,太低则发动机频繁启停,太高则低速纯电里程不足。
- SOC目标区间上/下限,这个与电池容量和充电倍率有关,通常设置上下限差值不小于0.2,否则容易进入频繁充放循环。
- 行车发电功率需求,SOC偏低时希望发动机多发电,一般设置一个发电扭矩附加值,然后叠加到发动机目标扭矩上。
- 模式切换迟滞窗,迟滞车速一般为2~5 km/h,迟滞扭矩一般为10~20 Nm。
参数整定的思路是:先用典型工况跑仿真,记录关键性能指标(油耗、电耗、SOC平衡、模式切换次数),然后做参数灵敏度分析,锁定影响最大的参数,再手动标定或配合优化算法整定。纯靠手工边改边跑效率很低,建议用MATLAB的sensitivity analysis脚本或者Simulink Design Optimization工具箱扫面参数组合。
6.2 从规则策略升级到优化策略的过渡
基于规则的控制策略虽然直观好调试,但不是最优解。如果你想把模型往学术层面推,可以在规则策略基础上加入全局优化或实时优化层。常见做法是先跑动态规划(DP)或者庞特里亚金极小值原理(PMP)离线求全局最优解,然后把最优解的规律提取成规则或查表,用于在线实时控制。另一种更直接的路线是搭建ECMS(等效燃油消耗最小化策略),把电池电耗等效为燃油消耗,然后在每个时刻求解一个瞬时优化问题,分配发动机和电机的扭矩占比。这套思路在后来的项目迭代中很有用,因为并联式混动本身是一个带约束的优化问题,规则法只是其中一种工程近似解法。
6.3 模型从仿真走向嵌入式部署的衔接
很多读者会把Simulink模型止步于仿真阶段,但实际项目里下一步往往是生成代码。Simulink模型可以通过Embedded Coder生成嵌入式C代码,部署到VCU、HCU之类的控制器中。这里有个关键点:仿真模型里不要使用仿真专用模块,比如Signal Builder、Scope、To Workspace等,这些模块在代码生成时要么报错、要么被忽略。正确的做法是:控制策略模型单独建一个子系统,输入输出用Inport/Outport,所有信号采集用接口层接入,这样代码生成时只生成控制策略子系统的代码。另外,代码生成前要配置好求解器和数据类型。控制策略实现中所有浮点数运算要定型为single或者double,如果目标MCU不支持浮点运算,还需要做定点化处理,这又是一轮大工程,但仿真的价值就体现在这个环节能提前暴露问题。
7. 关于这套模型,我最后想说的几句实战心得
并联式混合动力控制策略的研究,本质上是在整车约束、动力源效率、电池寿命和驾驶感受之间找平衡。Simulink模型给了我们一个把复杂系统分层拆解的工具,但工具只是辅助,真正值钱的是你对自己控制逻辑的理解深度。我在实际搭建过程中,最大的体会是不要把模型做得太复杂——能用查表解决的别写超级复杂的状态机,能用简单速率限制解决的别急着上滤波优化算法,每一层逻辑都要能在仿真图像上找到对应的事件,否则后期排查问题会非常痛苦。
另外一个小技巧分享给正在调模型的朋友:每次大改策略后,先跑一个最简单的等速工况验证基础逻辑,再跑完整工况对比结果。我发现不少Bug都是在等速工况下暴露出来的,比如扭矩稳态偏差、SOC静态漂移等。把一个简单工况跑稳定了,再进入复杂的多模式连续切换,你会少走很多弯路。希望这篇经验对正在折腾并联混动控制模型的朋友有帮助。