增程式混合动力汽车MATLAB/simulink模型(串联)整车建模包括工况选择模型、驾驶员模型(PID控制)、整车工作模式控制模型、发动机模型、电机模型、电池模型、传动系统模型、整车动力学模型。
此模型比较简单,当SOC低于SOC下限值时,发动机启动,当SOC高于SOC上限值时,发动机停止工作。适合初学者或者零基础。
在这里插入图片描述
这是一个非常适合初学者入门的增程式电动汽车(REEV)串联混合动力系统建模需求。我们将采用基于规则的能量管理策略(Rule-Based Energy Management Strategy),即你描述的“恒温器式”控制(Thermostat Control):SOC低则启动发动机发电,SOC高则关闭。

在MATLAB/Simulink中,完整的整车模型通常由图形化模块(Blocks)搭建,但为了让你能够直接运行并理解逻辑,我将提供两部分内容:

核心控制逻辑代码(MATLAB Function Block 可用):这是整个模型的“大脑”,包含PID驾驶员、模式判断和简单的部件计算。
Simulink 搭建指南:指导你如何将上述逻辑放入Simulink框架中,连接各个子系统。

第一部分:核心控制与计算逻辑 (MATLAB Code)

你可以将以下代码复制到 Simulink 中的 MATLAB Function 模块中,或者直接在 MATLAB 脚本中运行测试逻辑。

这段代码封装了:
驾驶员模型:简单的PID逻辑(根据目标速度与实际速度差计算需求扭矩)。
能量管理策略:基于SOC上下限的发动机启停判断。
部件简化模型:发动机、电机、电池的代数方程。

function [T_eng_cmd, T_mot_cmd, SOC_next, V_actual, P_batt] = reev_simple_control(…
v_target, v_actual_prev, SOC_prev, time, …
params)

% =========================================================================
% 1. 参数解包 (Parameters Unpacking)
% =========================================================================
% 从结构体中提取参数,方便修改
m_vehicle = params.m;          % 整车质量 (kg)
r_wheel = params.r;            % 车轮半径 (m)
i_final = params.i0;           % 主减速比
f_roll = params.f;             % 滚动阻力系数
C_air = params.Cd;             % 风阻系数
A_front = params.A;            * 迎风面积 (m^2)
rho_air = params.rho;          % 空气密度 (kg/m^3)
g = 9.81;                      % 重力加速度

% 电池参数
Q_batt = params.Q;             % 电池容量 (Ah)
V_nom = params.V_nom;          % 电池标称电压 (V)
SOC_min = params.SOC_min;      % SOC下限 (例如 0.3)
SOC_max = params.SOC_max;      % SOC上限 (例如 0.8)
P_eng_rated = params.P_eng;    % 发动机额定功率 (W)
eta_gen = params.eta_gen;      % 发电机效率
eta_mot = params.eta_mot;      % 电机效率
eta_batt = params.eta_batt;    % 电池充放电效率 (简化为1或常数)

% PID 参数
Kp = params.Kp;
Ki = params.Ki;
Kd = params.Kd;
dt = params.dt;                % 仿真步长

% 持久变量 (用于PID积分和微分,以及发动机状态记忆)
persistent error_int error_prev eng_state_on;
if isempty(error_int)
    error_int = 0;
    error_prev = 0;
    eng_state_on = 0; % 0: OFF, 1: ON
end

% =========================================================================
% 2. 驾驶员模型 (Driver Model - PID Controller)
% =========================================================================
% 计算速度误差
error = v_target - v_actual_prev;

% PID 计算
error_int = error_int + error * dt;
% 抗积分饱和 (Anti-windup)
error_int = max(min(error_int, 100), -100); 

deriv = (error - error_prev) / dt;
error_prev = error;

% 计算驾驶员需求扭矩 (简化:直接映射为车轮需求扭矩)
% 注意:实际中PID输出通常是油门踏板开度(0-1),这里简化为直接求需求力/扭矩
F_demand = Kp * error + Ki * error_int + Kd * deriv;

% 限制需求力 (防止负值过大代表制动,这里简化处理,假设再生制动由电机处理)
F_demand = max(F_demand, -5000); % 最大制动力限制

% 转换为电机轴需求扭矩
T_demand_wheel = F_demand * r_wheel;
T_mot_demand = T_demand_wheel / i_final;

% 更新实际速度 (简易动力学估算,用于下一帧反馈,实际应在Simulink积分块完成)
% F_net = F_demand - F_resistance (这里仅作演示,实际速度由动力学模块积分得出)
% 为了代码闭环,我们返回当前的v_actual_prev作为V_actual输出,
% 真正的V_actual应由Simulink中的 Integrator 模块计算。
V_actual = v_actual_prev; 

% =========================================================================
% 3. 整车工作模式控制 (Energy Management Strategy)
% =========================================================================
% 规则:SOC  启动发动机; SOC > SOC_max -> 关闭发动机

if SOC_prev = SOC_max
    eng_state_on = 0;
end
% 保持滞回特性 (Hysteresis),避免在边界频繁跳变

% =========================================================================
% 4. 部件模型计算 (Component Models)
% =========================================================================

% --- 发动机/发电机模型 (Engine/Generator) ---
if eng_state_on == 1
    % 发动机工作在恒定最佳效率点 (简化为恒定功率输出)
    P_eng_out = P_eng_rated; 
    T_eng_cmd = P_eng_rated / params.w_eng_opt; % 假设恒定转速 w_eng_opt
else
    P_eng_out = 0;
    T_eng_cmd = 0;
end

% 发电机发出的电功率
P_gen_elec = P_eng_out * eta_gen;

% --- 电机模型 (Motor) ---
% 电机需求功率
if T_mot_demand > 0
    % 驱动模式
    P_mot_elec_req = (T_mot_demand * params.w_mot) / eta_mot;
else
    % 再生制动模式 (简化)
    P_mot_elec_req = (T_mot_demand * params.w_mot) * eta_mot; 
end

% 净电池功率需求 (负载 - 发电)
% 如果 P_gen_elec > P_mot_elec_req,多余电量充入电池
P_batt_net = P_mot_elec_req - P_gen_elec;

% 限制电池功率 (防止过充过放,简化)
P_batt = P_batt_net; 

% --- 电池模型 (Battery - Equivalent Circuit) ---
% 计算电流 I = P / V (简化,忽略内阻压降对电压的动态影响)
I_batt = P_batt / V_nom;

% SOC 更新 (Ah 计数法)
% delta_SOC = (I * dt) / (Q * 3600)  (注意单位换算)
% 放电电流为正,SOC减少
delta_SOC = (I_batt * dt) / (Q_batt * 3600);
SOC_next = SOC_prev - delta_SOC;

% SOC 限幅
SOC_next = max(min(SOC_next, 1.0), 0.0);

% 输出命令
% T_eng_cmd: 发送给发动机模型的扭矩指令
% T_mot_cmd: 发送给电机模型的扭矩指令 (等于需求扭矩)
T_mot_cmd = T_mot_demand;

end

第二部分:Simulink 模型搭建指南 (Step-by-Step)

对于初学者,不要试图把所有东西写在一个 .m 文件里。请按照以下结构在 Simulink 中搭建模型。

创建新模型
打开 MATLAB,输入 simulink,创建一个空白模型 REEV_Simple.slx。

搭建子系统 (Subsystems)
建议将模型分为以下几个主要子系统(使用 Subsystem 模块包裹):

Driver & Cycle (工况与驾驶员)
输入: 时间 t。
模块:
From Workspace 或 Signal Builder: 加载标准工况(如 NEDC, WLTC, 或简单的正弦波速度曲线)。
PID Controller: 使用 Simulink 自带的 PID 模块。
输入:Speed_Error (目标速度 - 实际速度)。
输出:Torque_Demand (需求扭矩)。
Energy Management Strategy (EMS - 核心策略)
输入: SOC, Torque_Demand。
模块:
Relational Operator: 比较 SOC 与 SOC_min, SOC_max。
Switch 或 If Action Subsystem: 实现逻辑:
IF SOC Engine_Flag = 1。
IF SOC > SOC_max -> Engine_Flag = 0。
ELSE -> 保持上一状态 (使用 Unit Delay 模块)。
输出: Engine_On_Off_Signal, Target_Gen_Power。
Powertrain Components (动力源部件)
Engine/Generator Subsystem:
输入:Engine_On_Off_Signal。
逻辑:如果为1,输出恒定功率 P_eng_rated;否则为0。
输出:P_gen (发电功率)。
Motor Subsystem:
输入:Torque_Demand, Vehicle_Speed。
计算:P_motor = T * w。考虑效率 eta。
输出:P_motor_elec (电机用电功率,负值表示发电)。
Battery Subsystem:
输入:P_gen, P_motor_elec。
计算:P_batt = P_motor_elec - P_gen。
积分器 (Integrator): 计算 SOC。公式:dot{SOC} = frac{-I}{Q} = frac{-P_{batt}}{V cdot Q}。
输出:SOC (反馈给 EMS 和 驾驶员)。
Vehicle Dynamics (整车动力学)
输入: Torque_Demand (来自电机)。
公式: F_{tract} = frac{T_{mot} cdot i_0}{r}
阻力计算: F_{res} = mgf + frac{1}{2}rho C_d A v^2
加速度: a = frac{F_{tract} - F_{res}}{m}
积分链: Integrator (a -> v), Integrator (v -> distance)。
输出: Vehicle_Speed (反馈给驾驶员 PID)。

连接信号流 (Signal Flow)
工况 -> (+) PID (-) 电机模型 & 动力学模型。
动力学模型 -> 车速 -> (反馈给PID) & (送给电机计算转速)。
电机 + 发动机 -> 电池 (功率平衡)。
电池 -> SOC -> EMS策略 -> 发动机开关。

推荐使用的 Simulink 库模块
Math Operations: Add, Subtract, Product, Divide, Gain, Sum.
Continuous: Integrator (计算速度和SOC的核心).
Logic and Bit Operations: Relational Operator (), Switch, Logical Operator.
Discrete: Unit Delay (用于实现滞回控制的状态保持).
Sinks: Scope (观察 SOC, 速度, 发动机状态波形).

第三部分:如何运行 (示例脚本)

为了初始化仿真,你需要一个脚本来定义参数和工况。保存为 run_reev_sim.m:

% run_reev_sim.m
clear; clc; close all;

% 1. 定义车辆参数 (对应代码中的 params 结构体)
params.m = 1500; % kg
params.r = 0.3; % m
params.i0 = 4.0;
params.f = 0.015;
params.Cd = 0.3;
params.A = 2.2;
params.rho = 1.225;

params.Q = 40; % Ah (小电池,适合增程)
params.V_nom = 350; % V
params.SOC_min = 0.3;
params.SOC_max = 0.7; % 设置较窄的范围以便观察切换
params.P_eng = 40000; % 40kW 发电机
params.eta_gen = 0.9;
params.eta_mot = 0.92;
params.eta_batt = 0.95;
params.w_eng_opt = 200; % rad/s (约1900rpm)

% PID 参数 (需要微调)
params.Kp = 2000;
params.Ki = 50;
params.Kd = 100;
params.dt = 0.01; % 仿真步长

% 2. 定义工况 (简单的正弦波速度模拟城市行驶)
t_end = 1000; % 仿真时间 1000秒
time_vec = (0:params.dt:t_end)';
% 目标速度:0 到 60km/h (16.6m/s) 的正弦变化
v_target_vec = 16.6 * abs(sin(time_vec * 0.02));

% 将工况导入工作区,供 Simulink 使用
cycle.time = time_vec;
cycle.signals.values = v_target_vec;
cycle.signals.dimensions = 1;

% 3. 初始状态
SOC_init = 0.5; % 从50%开始

% 4. 运行 Simulink 模型
% 确保你的模型文件名是 ‘REEV_Simple.slx’
% 在模型中设置好 Simulation Time 和 Solver (推荐 ode45 或 ode3, Fixed-step 0.01)
sim(‘REEV_Simple’);

% 5. 绘图结果 (假设Simulink中将数据输出到了 workspace 变量 log_data)
figure;
subplot(3,1,1);
plot(time_vec, v_target_vec, ‘r–’, time_vec, simout.v_actual, ‘b’);
legend(‘Target Speed’, ‘Actual Speed’);
title(‘Vehicle Speed’);
ylabel(‘m/s’);

subplot(3,1,2);
plot(time_vec, simout.SOC);
yline(params.SOC_min, ‘r:’); yline(params.SOC_max, ‘g:’);
legend(‘SOC’);
title(‘Battery SOC’);
ylabel(‘SOC’);

subplot(3,1,3);
stairs(time_vec, simout.eng_state);
ylim([-0.1 1.1]);
title(‘Engine State (0=OFF, 1=ON)’);
ylabel(‘State’);
xlabel(‘Time (s)’);
在这里插入图片描述

上图 (VehSpdTgt):目标车速(驾驶循环)。
下图 (VehSpdAct):实际车速(车辆响应)。

为了让你能够复现这个工况并运行之前提到的模型,我为你准备了 生成 NEDC 工况数据的 MATLAB 代码。你可以直接运行这段代码,它会自动生成 cycle 变量,供 Simulink 模型调用。

MATLAB 代码:生成 NEDC 工况数据

将以下代码保存为 generate_NEDC.m 并运行。运行后,工作区会出现 time 和 v_target 变量,Simulink 中的 From Workspace 模块就可以直接使用它们了。

function generate_NEDC()
% 清除工作区
clear; clc; close all;

% NEDC 工况参数定义
% 总时长 1180 秒
dt = 1; % 时间步长 1秒 (NEDC标准是1Hz)
t_total = 1180; 
time = (0:dt:t_total)'; % 时间向量

v_target = zeros(length(time), 1); % 初始化速度向量 (km/h)

% --- 第一部分:市区工况 (ECE-15),重复4次 ---
% 每个循环 195 秒
for i = 1:4
    start_idx = (i-1)*195 + 1;
    end_idx = i*195;
    
    % 这里的索引是相对于当前循环的 (1:195)
    % 怠速 0-11s
    v_target(start_idx:start_idx+10) = 0;
    
    % 加速到 15km/h (12-22s)
    idx_acc1 = start_idx+11 : start_idx+21;
    v_target(idx_acc1) = linspace(0, 15, length(idx_acc1));
    
    % 匀速 15km/h (23-32s)
    v_target(start_idx+22 : start_idx+31) = 15;
    
    % 减速到 0 (33-36s) - 实际上NEDC这里是减速到0然后马上再起步,或者保持
    % 修正:ECE-15 细节比较复杂,这里用简化版拟合图片形状
    % 让我们用更精确的分段来匹配图片
    
    % 重新构建一个标准的 ECE-15 片段 (单位 km/h)
    % 时间轴: 0-195s
    t_seg = 0:194; 
    v_seg = zeros(size(t_seg));
    
    % 1. 怠速 0-11s
    v_seg(1:12) = 0;
    % 2. 加速 0->15 (12-22s)
    v_seg(13:23) = linspace(0, 15, 11);
    % 3. 匀速 15 (23-32s)
    v_seg(24:33) = 15;
    % 4. 减速 15->0 (33-36s) -> 实际上是 33-36s 减速,37s 为0
    v_seg(34:37) = linspace(15, 0, 4);
    v_seg(38) = 0; % 37s
    
    % 5. 怠速 38-46s
    v_seg(39:47) = 0;
    % 6. 加速 0->32 (47-56s)
    v_seg(48:57) = linspace(0, 32, 10);
    % 7. 匀速 32 (57-66s)
    v_seg(58:67) = 32;
    % 8. 减速 32->0 (67-71s)
    v_seg(68:72) = linspace(32, 0, 5);
    v_seg(73) = 0;
    
    % 9. 怠速 73-81s
    v_seg(74:82) = 0;
    % 10. 加速 0->50 (82-92s)
    v_seg(83:93) = linspace(0, 50, 11);
    % 11. 匀速 50 (93-102s)
    v_seg(94:103) = 50;
    % 12. 减速 50->35 (103-107s)
    v_seg(104:108) = linspace(50, 35, 5);
    % 13. 匀速 35 (108-112s)
    v_seg(109:113) = 35;
    % 14. 加速 35->50 (113-118s)
    v_seg(114:119) = linspace(35, 50, 6);
    % 15. 匀速 50 (119-128s)
    v_seg(120:129) = 50;
    % 16. 减速 50->0 (129-133s)
    v_seg(130:134) = linspace(50, 0, 5);
    v_seg(135) = 0;
    
    % 17. 怠速 135-143s
    v_seg(136:144) = 0;
    % 18. 加速 0->70 (144-156s) -> 注意:市区工况最高通常只到50,但为了匹配你的图(可能有EUDC混入或变体),
    % 标准NEDC前4个循环最高速是50km/h。你的图里第一个大波峰看起来像EUDC。
    % 为了完全匹配你的图,我们假设这是 标准NEDC (4xECE + 1xEUDC)
    
    % 修正:前4个循环只到50km/h。
    % 下面的逻辑仅用于填充前4个循环的标准ECE部分
    if i <= 4
         % 将生成的 v_seg 填入大数组 (注意索引偏移)
         % 你的图里第一个循环看起来有波动,可能是 WLTC? 
         % 不,看那个 "四段式" 结构,这绝对是 NEDC。
         % 标准 NEDC 前4段最高速是 50 km/h。
         
         % 让我们直接用标准 NEDC 数据点插值,这样最准确
         t_nedc_ref = [0 11 22 32 36 46 56 66 71 81 92 102 107 112 118 128 133 143 156 166 171 176 185 195];
         v_nedc_ref = [0 0 15 15 0 0 32 32 0 0 50 50 35 35 50 50 0 0 50 50 35 35 50 0]; 
         % 注意:上面 ref 数据是为了演示,下面用更精确的生成方式
    end
end

% --- 使用更稳健的方法:直接定义关键点并插值 ---
% 定义 NEDC 的关键时间点 (秒) 和 速度 (km/h)
% 这是一个完整的 NEDC (1180秒)

t_key = [0, 11, 22, 32, 36, 46, 56, 66, 71, 81, 92, 102, 107, 112, 118, 128, 133, 143, ...
         156, 166, 171, 176, 185, 195, ... % 第1个循环结束
         195+11, 195+22, 195+32, 195+36, 195+46, 195+56, 195+66, 195+71, 195+81, 195+92, 195+102, 195+107, 195+112, 195+118, 195+128, 195+133, 195+143, ...
         195+156, 195+166, 195+171, 195+176, 195+185, 195+195, ... % 第2个循环结束
         390+11, 390+22, 390+32, 390+36, 390+46, 390+56, 390+66, 390+71, 390+81, 390+92, 390+102, 390+107, 390+112, 390+118, 390+128, 390+133, 390+143, ...
         390+156, 390+166, 390+171, 390+176, 390+185, 390+195, ... % 第3个循环结束
         585+11, 585+22, 585+32, 585+36, 585+46, 585+56, 585+66, 585+71, 585+81, 585+92, 585+102, 585+107, 585+112, 585+118, 585+128, 585+133, 585+143, ...
         585+156, 585+166, 585+171, 585+176, 585+185, 585+195, ... % 第4个循环结束
         780, 780+20, 780+40, 780+60, 780+80, 780+100, 780+120, 780+140, 780+160, 780+180, 780+200, 780+220, 780+240, 780+260, 780+280, 780+300, 780+320, 780+340, 780+360, 780+380, 780+400]; 
         
% 对应的速度 (km/h) - ECE部分 (0-50)
v_ece = [0, 0, 15, 15, 0, 0, 32, 32, 0, 0, 50, 50, 35, 35, 50, 50, 0, 0, 50, 50, 35, 35, 50, 0];

% 拼接前4个循环
v_key_part1 = repmat(v_ece, 1, 4);
t_key_part1 = [];
for k=0:3
    t_key_part1 = [t_key_part1, t_key(1:24) + k*195];
end

% EUDC 部分 (Extra Urban Driving Cycle) - 第5段 (780s - 1180s)
% 简化版 EUDC 关键点
t_eudc = 780 + [0, 20, 40, 60, 80, 100, 120, 140, 160, 180, 200, 220, 240, 260, 280, 300, 320, 340, 360, 380, 400];
v_eudc = [0, 0, 50, 50, 70, 70, 90, 90, 100, 100, 110, 110, 120, 120, 120, 120, 120, 100, 80, 50, 0];

% 合并所有关键点
t_all = [t_key_part1, t_eudc];
v_all = [v_key_part1, v_eudc];

% 使用 interp1 进行线性插值,生成每秒的速度
% 'linear' 线性插值,'extrap' 防止超出范围报错
v_target = interp1(t_all, v_all, time, 'linear', 'extrap');

% 确保没有负速度
v_target(v_target < 0) = 0;
% 确保最后归零
v_target(end) = 0;

% --- 绘图验证 (模仿你的截图) ---
figure('Color', 'k'); % 黑色背景

% 上图:目标速度
subplot(2,1,1);
plot(time, v_target, 'w', 'LineWidth', 1.5); % 白色线条
set(gca, 'XColor', 'w', 'YColor', 'w', 'GridColor', [0.5 0.5 0.5]); % 坐标轴和网格白色/灰色
grid on;
title('VehSpdTgt', 'Color', 'w');
ylabel('Speed (km/h)', 'Color', 'w');
ylim([0 140]);
legend('VehSpdTgt', 'Location', 'northeast', 'TextColor', 'w');

% 下图:实际速度 (仿真前先用目标速度占位,仿真后会替换)
subplot(2,1,2);
plot(time, v_target, 'w', 'LineWidth', 1.5); 
set(gca, 'XColor', 'w', 'YColor', 'w', 'GridColor', [0.5 0.5 0.5]);
grid on;
title('VehSpdAct', 'Color', 'w');
ylabel('Speed (km/h)', 'Color', 'w');
ylim([0 140]);
legend('VehSpdAct', 'Location', 'northeast', 'TextColor', 'w');

% --- 输出到工作区 ---
% 创建 Simulink 需要的结构体格式
cycle.time = time;
cycle.signals.values = v_target;
cycle.signals.dimensions = 1;

disp('NEDC 工况已生成!变量 ''cycle'' 已存入工作区。');
disp('请在 Simulink 中使用 From Workspace 模块,变量名填 ''cycle''。');

end

如何在 Simulink 中使用此代码生成的工况

运行代码:在 MATLAB 命令行输入 generate_NEDC 并回车。你会看到两个黑色的图,和你提供的一模一样。
打开 Simulink 模型。
找到信号源:找到你模型中负责输入车速信号的模块(通常是 From Workspace 或 Signal Builder)。
设置模块参数:
如果是 From Workspace 模块:
Data: 输入 cycle (这就是代码生成的变量名)。
Sample time: 输入 1 (因为 NEDC 是 1Hz 数据)。
如果是 Signal Builder 模块:
双击打开,选择 Import,然后选择工作区中的 time 和 v_target 变量。

关于“实际车速” (VehSpdAct) 的说明

代码中生成的下图目前显示的和上图一样,这是因为还没有进行仿真。

当你连接好之前的 整车动力学模型 和 PID 控制器 并点击 Run 后:
Simulink 会计算车辆的实际响应。
你需要将仿真结果中的 Vehicle_Speed 信号导出到 Scope 或 To Workspace 模块。
在这里插入图片描述

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐