
最近在做增程式电动汽车EREV的整车能量管理仿真时最折腾我的问题就是电池从亏电到满电这段过程里增程器到底该怎么工作。刚开始我搭的模型非常简单——SOC低了就启动增程器SOC高了就关掉结果仿真曲线像锯齿一样增程器几分钟就启停一次电池充电功率也经常顶到保护限值。后来把整套逻辑重新梳理了一遍用MATLAB/Simulink按整车动力学、电池、增程器、控制策略四层重新搭才真正跑通从SOC 15%亏电状态一路充到95%以上的完整过程。这篇文章就把整个建摸过程和控制逻辑完整拆开讲一遍包括模型架构、子系统模型、亏电到满电的控制策略设计以及我在调参过程中踩过的坑。想用MATLAB做新能源整车仿真特别是EREV/PHEV能量管理策略的同学可以直接按这套思路去复现。1. EREV模型到底要解决什么问题架构、目标与仿真方式的选择1.1 增程式电动车和插混、纯电在建模上的本质差异很多人一开始会把EREV当成纯电发电机的组合模型上直接拿纯电模型加一个受控电流源后来发现完全不是这么回事。EREV的动力传递路径是固定的电池给电机供电电机驱动车轮增程器里的发动机带动发电机发电电能可以给电池充电也可以直接给电机供电但发动机和车轮之间没有机械连接。这一点和插电混动PHEV有本质区别——PHEV存在发动机直接驱动车轮的并联模式建模时必须考虑离合器状态、变速器挡位、扭矩叠加甚至模式切换的平顺性复杂度要高一个量级。EREV的优势恰恰在于解耦。发动机的工作点不受车速约束控制策略可以始终让增程器运行在效率较高的点。反映到建模上就是增程器不需要建立详细的发动机瞬态模型只需要一个输入功率指令、输出发电功率和油耗的准静态模型就够用了。而真正的难点全部集中在能量管理层增程器什么时候启动、发多少电、发电优先给驱动还是优先给电池充电、SOC目标定多少、接近满电时怎么降功率。这套从亏电到满电的逻辑才是EREV模型的核心价值。1.2 模型用途决定细节粒度后向仿真还是前向仿真动工之前先想清楚一个事你搭这个模型是干什么用的。如果只是算综合油耗、续航里程用后向仿真就够了也就是直接根据循环工况的车速反推整车需求功率再沿着传动链从车轮推到电池和发动机模型简单、仿真速度快适合做大量参数扫描。但后向仿真有一个问题它假设车辆完全按目标工况行驶没有驾驶员模型动态控制过程中的功率响应、SOC波动、模式切换都被抹掉了。拿它研究亏电到满电的控制逻辑基本等于拿着地图找下水道方向对但看不到细节。我这次的目标是研究和验证控制策略所以选择前向仿真。前向仿真以驾驶员需求扭矩作为输入信号流是真实的因果链目标车速进入驾驶员模型驾驶员模型输出加速踏板或制动踏板开度整车控制器根据当前状态给出扭矩和功率分配指令电机执行指令车辆纵向动力学计算实际车速再反馈给驾驶员模型形成闭环。前向仿真能清楚看到增程器启动瞬间的功率分配、电池SOC的响应轨迹、以及策略参数变化带来的影响代价是模型更重、调试更麻烦但对控制逻辑研究来说这是必须的。1.3 顶层架构怎么搭前向仿真的顶层架构我在模型里分了五层工况层输入CLTC/WLTC等目标车速序列驾驶员层PID控制器输出需求扭矩策略层能量管理逻辑决定增程器启停和发电功率执行器层电机、增程器、电池的物理响应车辆层整车纵向动力学计算实际车速控制策略层是大脑但大脑的信号离不开物理层反馈。电池SOC估算模块计算当前SOC反馈给策略层策略层根据SOC、驾驶员需求功率、附件功率计算增程器发电功率指令增程器模块执行这个指令把发电功率送入DC母线母线功率平衡决定了电池是放电还是充电进而影响SOC。这个闭环一旦建立后续所有控制逻辑都在这套架构上改。2. 把整车拆成四块电池、增程器、电机和纵向动力学建模细节2.1 电池模型安时积分SOC和二阶RC等效电路电池是EREV的能量缓冲器它的模型精度直接影响SOC变化趋势。我选择的是二阶RC等效电路模型包含一个电压源OCV(SOC)、一个内阻R0、两组RC并联网络。为什么不直接用理想电压源加内阻因为电池在动态工况下会出现极化效应电流突变后端电压不会立刻跳变而是有一个渐变过程。一阶RC能模拟一部分极化但响应太单调三阶RC精度更高可是参数辨识工作量大幅增加对于能量管理策略研究来说性价比不高。二阶RC是比较好的折中。模型方程很简单端电压U_t OCV(SOC) - I_bat * R0 - U_1 - U_2RC网络动态dU_1/dt -U_1/(R1C1) I_bat/C1dU_2/dt -U_2/(R2C2) I_bat/C2SOC估算SOC SOC0 - 1/(3600 * Q) * ∫I_bat dt其中Q是电池安时容量。以38kWh电池包、标称电压350V为例容量大约是108Ah。如果图省事用能量积分法也可以但电压变化会造成偏差我建议还是用安时积分配合OCV查表。R0、R1、C1、R2、C2都可以标成SOC的函数做成二维查表在Simulink里直接用Lookup Table模块比用simscape电学元件更轻量仿真也稳定。在MATLAB里搭的时候注意一点电池的充放电内阻可能不同最好分别建表。另外SOC的积分环节记得加初始值和上下限饱和否则仿真中途出现SOC超过0~1的区间后面的查表和逻辑判断全都会乱。2.2 增程器模型发动机BSFC MAP和发电机效率MAP增程器建模的思路和电池类似不需要把发动机缸内燃烧过程建出来那是发动机开发团队的事。能量管理仿真只关心一个问题在某一个转速和扭矩下增程器消耗多少燃油、输出多少电功率。所以发动机部分用BSFCBrake Specific Fuel ConsumptionMAP表示横轴是转速、纵轴是扭矩等值线是燃油消耗率g/kWh。发电机部分用效率MAP表示给定转速和扭矩查出发电效率。增程器功率计算关系发动机输出机械功率 P_ice T_ice * n_ice / 9550油耗率 m_dot_fuel P_ice * BSFC / 3600发电机输出电功率 P_gen P_ice * η_gen同一发电功率下发动机可以有不同的转速扭矩组合但BSFC差别很大。所以在控制策略里需要预先把最优工作线整理出来对每个功率需求找出BSFC最低或综合效率最高的转速扭矩点作为目标工作点。这个最优工作线可以做成二维表也可以写成一个MATLAB脚本在离线环境下预先算好再给Simulink查表。我还加了两个工程化细节。第一增程器从启动指令到稳定输出发电功率有一个响应时间我把它简化为一阶惯性环节时间常数大约1~2秒这样不会出现功率指令阶跃导致母线电压过冲。第二增程器输出功率变化率要限幅我设定为5kW/s模拟真实发动机的加/减速能力也让控制策略的功率调整不会太激进。2.3 电机与传动驱动、回馈和传动效率电机模型在外特性上是一条扭矩-转速包络线低速区域受峰值扭矩限制高速区域受峰值功率限制。电机效率用效率MAP给定扭矩和转速查效率这个MAP通常可以从供应商数据或台架实验得到。在EREV中电机是唯一的驱动单元必须同时考虑驱动和发电两种工作状态驱动时电池放电效率η_mot再生制动时电机反转发电把动能回收到电池效率同样按MAP查但功率方向相反。整车纵向动力学是模型反馈回路的终点也是标定基础。滚动阻力、空气阻力、坡道阻力、加速阻力四部分叠加function F vehicle_resistance(v, a, grade, m, Cd, A, rho, f) g 9.81; F_roll m * g * f * cos(grade); % 滚动阻力 F_aero 0.5 * rho * Cd * A * v^2; % 空气阻力 F_grade m * g * sin(grade); % 坡道阻力 F_acc m * a; % 加速阻力 F F_roll F_aero F_grade F_acc; end得到车轮端需求力之后乘以车速得到车轮端功率再除以传动效率 η_trans就是电机需要输出的机械功率。如果车辆有减速器主减速比会影响电机转速和扭矩换算我在参数表里用了9这个速比轮端扭矩除以速比再除以传动效率就是电机扭矩需求。2.4 驾驶工况与驾驶员模型研究亏电到满电控制逻辑工况选择很关键。我建议先用CLTC或WLTC做基础验证再叠加一段70~80km/h左右的恒速路段。CLTC低速启停多SOC消耗快中高速恒速段可以让增程器发电功率大于驱动需求SOC实打实往上涨。只跑一个NEDC或只看WLTC可能看不到完整的亏电-满电过程因为高速大功率工况下增程器可能连维持SOC都困难更别提充电。驾驶员模型我用了PID控制输入目标车速和实际车速的偏差输出需求扭矩。PID参数不能随手拍调得太激进会导致车速震荡调得太慢会导致工况跟随误差大。我的经验是先P后PIP给20~50I给2~5保证需求扭矩平滑即可。这个模块在Simulink里直接放一个PID Controller模块就能实现注意把输出限幅在电机最大扭矩和最大再生制动扭矩之间。3. 亏电到满电的控制逻辑从单阈值切到状态机闭环3.1 为什么SOC到了就启停会失败先说我的反面教材。第一版控制逻辑很简单SOC低于20%就启动增程器高于30%就关掉。仿真结果惨不忍睹——增程器启动后给电池充电SOC很快升到30%然后停机停机后纯电行驶又把SOC拉低不到两分钟又触发启动条件。整个仿真过程增程器反复启停燃油消耗和排放特性完全失真电机母线电压也跟着来回波动。问题本质是缺了两个东西滞回比较和状态记忆。单阈值带只有20%~30%的区间SOC实际在区间边界来回穿越时控制指令也跟着来回切换。解决办法不是把区间拉大就完事而是要把控制逻辑从if-else改成状态机滞回最小运行时间。增程器一旦启动至少要稳定运行一段时间比如120秒不允许因为SOC短暂越过阈值就立刻关停SOC一旦低于下限也不会因为SOC升到30%就马上停机而是保留一个安全余量。3.2 状态机设计CD、CS、强制充电和满电停机我最终用Stateflow实现了四状态控制逻辑这四个状态完成了从亏电到满电的所有场景表格里的SOC阈值都来自实际参数表的默认值不是拍脑袋状态进入条件退出条件增程器输出CD纯电行驶SOC 30%且无强制充电请求SOC ≤ 20%0纯电驱动CS电量维持SOC ≤ 20%且无强制充电请求SOC ≥ 30%P_load P_chg_set维持SOC在目标区间Charge强制充电手动开启或SOC ≤ 12%SOC ≥ 95%发电功率尽量大充电优先Stop停机Charge状态下SOC达到95%SOC ≤ 90%0等待下次循环自动模式下从亏电状态进入CS增程器跟随驱动功率并叠加一段充电功率SOC爬到30%后进入CD这是常规的维持逻辑。强制充电模式下就不一样了增程器持续运行目的是把SOC从亏电一路送到95%再进入Stop状态。Stop状态不是终态SOC之后因为行驶消耗掉5%~10%又会重新进入CS或者Charge所以状态机是循环的。为了防止状态边界上的抖动所有状态切换条件都用了滞回。比如Charge状态退出条件是SOC95%重新进入条件是SOC90%中间5%的空档就是缓冲区。CD和CS之间同样有20%/30%的滞回。3.3 SOC闭环调节和充电功率限幅状态机只解决了什么时候启停还要解决发多少电也就是功率闭环。这里我用了一个非常直接的功率平衡关系P_gen P_load P_chg_target其中P_load是驱动功率加附件功率P_chg_target是希望给电池充进去的功率。只要增程器输出电功率大于负载消耗多余部分自然流入电池SOC上升反过来SOC就下降。P_chg_target用一个PI控制器调节输入是SOC目标值和当前SOC的偏差输出是期望充电功率再限幅到0到P_chg_max之间。之所以用PI而不是直接查表是因为接近目标SOC时需要平滑降功率。如果SOC在90%之前一直是30kW恒功率充电到95%瞬间变成0电池端电压会有一个明显的突变BMS保护逻辑很可能介入。用PI或者分段线性降功率让充电功率在SOC 90%~95%区间逐步减到0就相当于模拟了电池CC-CV充电曲线的CV段。MATLAB里实现这个限幅逻辑可以直接写一个MATLAB Functionfunction Pchg chargePowerLimit(SOC, SOC_target, Pchg_max) taper_zone 5; % 进入目标SOC前5%开始降功率 if SOC SOC_target Pchg 0; elseif SOC SOC_target - taper_zone Pchg Pchg_max * (SOC_target - SOC) / taper_zone; else Pchg Pchg_max; end end增程器端还要加一层功率变化率限制我设成5kW/s。这样即使PI输出一个大的阶跃增程器也不会瞬间从0跳到60kW更接近真实发动机响应也避免母线电压过冲。3.4 从亏电到满电的完整过程把上述逻辑串起来一个典型仿真过程是这样的初始SOC 15%打开强制充电模式。第一段SOC在15%~20%增程器启动并迅速升功率到60kW除满足驱动和附件负载外剩余功率全部充电第二段SOC进入20%~90%增程器仍按较高功率输出充电功率限制在30kW第三段SOC超过90%充电功率按线性降到0第四段SOC到达95%增程器停机系统回到纯电驱动。整个过程大约需要40到50分钟仿真时间。这里有几个细节值得注意。一是行车过程中如果驱动功率本身就很大比如高速爬坡增程器即使满功率60kW也可能不够同时驱动和充电此时电池反而会小幅度放电。这不是控制逻辑错误而是物理功率上限决定的策略设计时要接受这种合理的SOC波动。二是为什么目标定95%而不是100%因为充电末段的效率极低且高SOC状态下电池回收再生制动的能力下降日常行车到100%反而对能量管理和电池寿命都不利。4. MATLAB模型的实现方式Simulink结构、Stateflow和关键参数4.1 工具选型从零搭建还是用Powertrain Blockset这个问题我纠结了很久也建议你先想清楚再动手。Simscape Electrical里有很多现成的电池、电机、发电机模块拖动就能搭画出来的模型很接近物理结构看起来专业。但Simscape模型是物理域的网络仿真步长和代数环问题会让人头疼而且控制策略里很多信号无法直接接入物理端口调试成本高。Powertrain Blockset更夸张它自带EREV Reference Application点一下就能生成一整套带参考控制策略的整车模型发动机、电机、电池、驾驶员、工况全都有。如果你只是想做整车参数分析直接改参数跑就行。但问题是这个参考模型层级非常多代码生成、总线信号、配置界面都封装好了想在里面改SOC控制逻辑反而比从零搭更难。我的建议是研究控制逻辑阶段用纯Simulink查表模型加Stateflow物理结构用公式或者查表近似这样每一个信号都能看到、能改、能调试等逻辑验证完毕再迁移到Powertrain Blockset或者Simscape做高保真验证。从零搭的模型虽然看起来朴素但它是完全透明的方便后续加需求、加约束。4.2 Simulink模型层级和关键模块顶层模型我按信号流分成六个部分清晰也好定位问题Drive CycleFrom Workspace读入目标车速序列Driver ModelPID Controller输出需求加速度Energy ManagementStateflow模块输出增程器启停命令和发电功率指令EREV Plant包含电池、电机、增程器、纵向动力学这些被控对象Bus直流母线功率平衡Scope/Data Logging记录SOC、增程器功率、电池电流等所有物理量单位统一。我用的策略是功率统一用kW转速用rpm扭矩用Nm车速用km/h换算成m/s。很多仿真问题最后都出在单位不一致上尤其是km/h和m/s的换算在Simulink里最容易被忽略。求解器我选择离散定步长固定步长0.001秒控制策略的采样周期单独设为0.01秒用Rate Transition模块做不同步长之间的信号缓存。整车动力学模型的响应频率不高1ms足够的但比控制周期细能捕捉到控制量变化引发的物理量振荡。4.3 Stateflow状态机怎么落地Stateflow是这套模型里我最喜欢的部分。建一个Chart输入是SOC、P_load、force_charge_request输出是eng_on和P_gen_ref。Chart内部就是上一节说的四个状态和状态切换条件。在这里提醒几个容易踩的细节状态内部不要直接输出P_gen_ref的连续计算值然后马上反馈给增程器否则容易产生代数环。输出端加一个Memory或者Rate Transition把计算值作为一个采样信号传给物理层。状态切换条件里用的SOC阈值不能只在进入状态时判断一次要在整个状态运行期间持续判断。Stateflow默认的transition是在每个采样周期都检查的所以设置条件是OK的。增加一个duration条件防止频繁切换例如eng_on持续运行超过120秒后才允许从CS切换到CD这个功能在Stateflow里可以直接用after(120,sec)这种时序运算符实现。4.4 关键参数标定建议这套模型里常用的参数我列成一个表基本可以直接照抄参数数值说明整车质量1800 kg含电池、增程器风阻系数0.28常见SUV/轿车水平迎风面积2.2 m²常见轿车水平滚动阻力系数0.012沥青路面轮胎半径0.33 m约18英寸轮胎主减速比9单级减速器传动效率0.95包括减速器和半轴电机峰值功率120 kW满足整车动力性电池容量38 kWh标称350V增程器额定功率60 kW可覆盖大部分巡航负载SOC低阈值20%自动模式增程器启动点SOC高阈值30%自动模式增程器停机点强制充电目标SOC95%不追求100%最大充电功率30 kW受电池许可限制增程器功率变化率5 kW/s模拟真实响应控制周期10 msStateflow采样时间这些参数不需要一次调准先跑通再根据曲线调整。比如说如果高速段SOC持续下滑说明增程器功率不够要么提高增程器额定功率要么降低目标充电功率如果增程器启停频繁就扩大滞回区间或者增加最小运行时间。5. 调参和踩坑实录从波形异常反推问题根源5.1 增程器频繁启停不是阈值问题是状态记忆问题第一版仿真跑完我看到增程器启停信号就像心电图一样密集一秒钟的仿真数据里on/off切换了十几次。刚开始怀疑是阈值区间设得太窄把20%~30%改成15%~35%没用只是把锯齿间隔拉长了一点。后来才意识到单纯靠SOC阈值切换是省事但问题是增程器停机后电动机立刻从电池取电SOC的下滑速度非常快而增程器再启动需要时间SOC会跌穿下阈值很多于是整个过程变成了启动→充满→停机→立马又被拉低→再启动的恶性循环。解决办法不只在阈值而是状态机加了两个约束最小运行时间120秒最小停机时间60秒。增程器启动后即使SOC已经升到30%只要运行时间没满120秒不允许切换回CD停机后即使SOC已经降到20%如果停机时间没满60秒不允许重新启动。这两个时间窗口加进去启停次数立刻降了一个数量级。5.2 SOC接近满电时过充恒功率充电的坑另一个问题出现在强制充电模式。SOC从15%一路充到90%都很顺利再往上去仿真突然报错提示电池端电压超过允许最大值。查了半天发现不是电池模型的问题是控制策略的锅——充电功率一直保持30kW到了SOC 92%的时候电池OCV明显升高内阻压降叠加之后端电压突破了BMS保护限值。真实电池在充电末段会切换为恒压充电充电电流逐渐减小。我在策略里加了一个线性降功率区间SOC在90%到95%之间充电功率从30kW线性降到0同时把强制充电目标定在95%而不是100%。这样既避免了过压保护也符合实际电池管理策略仿真曲线变得平滑很多。5.3 功率指令和SOC反馈之间的代数环模型里还有一个让我查了半天的Simulink报错代数环。报错信息指向Stateflow输出的增程器功率指令和电池SOC计算模块之间存在循环依赖。因为P_gen_ref的取值会影响电池充放电功率电池功率影响SOCSOC又反过来影响P_gen_ref的计算如果模型里没有离散化缓存Simulink必须在同一个步长内解这个环。我的处理方式是把控制策略整体离散化Stateflow和控制逻辑模块的采样周期设为10ms增程器和电池等物理模型仍然用1ms步长中间所有跨采样周期的信号都加Rate Transition。这样一来控制策略在一个控制周期内使用的是上一拍采样的SOC物理层在当前周期内执行最新的指令循环依赖自然断开。对于整车能量管理这个量级的仿真10ms控制延迟完全不影响结果。5.4 用能量守恒校验模型对不对调试到最后我还会做一次能量守恒校验这是判断模型是否可靠的关键一步。把所有能量源和能量消耗方积分起来燃油消耗的化学能、电池初始电能、电机驱动消耗的能量、再生制动回收的能量、附件消耗、增程器发电量以及电池最终剩余能量两边应该基本相等。误差在5%以内说明模型没有明显丢能量如果误差大于10%基本可以确定模型里有信号单位错误、效率算了两遍或者某个积分模块的初值设错。我的做法是在模型里加一个Energy Meter子系统用积分模块分别统计各支路能量然后在MATLAB脚本里跑完仿真后自动对比。这个方法花不了多少时间但能救你很多次因为单位写错这种问题从波形上看不出来只有从能量守恒的角度才能暴露。最后关于这套逻辑如何迁移到实车或HIL的小经验如果你后续要做代码生成或者硬件在环测试这套Stateflow策略可以直接生成C代码但要注意几个工程化改动把SOC阈值和功率限幅做成参数而不是硬编码方便标定工程师不重新编译就调参把控制周期从10ms改成实际VCU的调度周期比如20ms或者50ms增程器模型里的MAP数据要处理成适合定点的查表格式。我个人认为先把这个透明化的MATLAB模型跑熟把亏电到满电过程理解透了再去碰官方参考模型或者实车标定会比直接抄一个大而全的模型轻松得多。