Simulink 发动机闭环控制仿真实战:从底层搭建、Scope 调试到论文级 MAP 图输出

我们刚刚在 Simulink 中搭建的,在汽车工程界被称为 平均值发动机模型 (Mean Value Engine Model, MVEM)

要理解它的原理,首先要明白"平均值"三个字的含义。真实的四冲程发动机(进气、压缩、做功、排气)在微观上是非常暴躁、断续的,每个气缸的压力都在剧烈波动。但 MVEM 模型忽略了这种曲轴转角级别的毫秒级波动,将发动机视为一个连续运转的"黑盒" ,只计算几个发动机周期内的平均物理量

这使得模型既能准确反映发动机的动态迟滞,又不会因为计算量太大而卡死,是做 ECU 控制算法(比如你刚做的怠速启停)最完美的模型。

它的核心原理建立在三大经典物理定律之上,正好对应你搭建的三个子系统:

1. 进气歧管动态:质量守恒定律 (流体力学)

进气歧管(节气门之后、气缸之前的管道)就像一个带有进气口和出气口的弹性气球

  • 流入(节气门): 当你踩下油门开大节气门时,空气并不是瞬间冲进气缸的,而是先进入进气歧管。
  • 流出(气缸抽气): 发动机的活塞像水泵一样,不断从这个歧管里把空气抽走。
  • 原理: 歧管内部的压力变化率,完全取决于"进气速度"和"抽气速度"的差值。如果进气比抽气快,歧管压力就上升;反之则下降。这就是为什么你在这个子系统里必须用一个 积分器 (Integrator)

物理方程:

dPmandt=R⋅TmanVman(m˙in−m˙out)\frac{dP_{man}}{dt} = \frac{R \cdot T_{man}}{V_{man}} (\dot{m}{in} - \dot{m}{out})dtdPman=VmanR⋅Tman(m˙in−m˙out)

(这就是为什么你踩下油门后,发动机动力总是会"慢半拍"的核心原因------歧管需要时间来"充气"建立压力。)

2. 燃烧扭矩:热力学映射与做功迟滞

发动机产生扭矩的大小,本质上取决于气缸里吸进了多少空气(由前面的歧管压力决定),以及当前的转速。

  • 查表法 (MAP): 我们没有在模型里写复杂的化学燃烧方程,而是使用了台架测试标定好的 二维查表 (2-D Lookup Table)。这相当于直接告诉模型:"在某压力、某转速下,你能爆发出多少力气"。
  • 物理延迟: 空气进入气缸后,还要经过压缩冲程才能点火做功。四缸机大约有半圈(180度)曲轴转角的延迟。所以你在模型中加了一个变传输延迟 (Variable Transport Delay) 模块,延迟时间 τ=30N\tau = \frac{30}{N}τ=N30。转速越慢,延迟越长。

3. 曲轴动力学:牛顿第二定律 (刚体转动)

这是初中物理 F=maF = maF=ma 的旋转版本。

  • 原理: 发动机燃烧产生的"净扭矩"(已经扣除了自身摩擦),与测功机或车轮施加的"外部阻力扭矩"进行拔河。
  • 如果 净扭矩 > 阻力扭矩,曲轴就会加速旋转。
  • 如果 净扭矩 < 阻力扭矩,曲轴就会减速。
  • 你在这个模块用的 积分器,就是将角加速度积分成了最终的发动机转速 (RPM)。

物理方程:

dNdt=30π⋅J(Tnet−Tload)\frac{dN}{dt} = \frac{30}{\pi \cdot J} (T_{net} - T_{load})dtdN=π⋅J30(Tnet−Tload)

(其中 JJJ 就是转动惯量,它决定了转速上升和下降的"平滑程度"。重飞轮的发动机,转速变化就很迟钝。)


请打开一个空的 Simulink 模型文件 (Blank Model),我们分四个核心子系统进行搭建。


第一部分:进气歧管压力子系统 (Intake Manifold)

这个子系统的目标是计算实时的进气歧管绝对压力 (PmanP_{man}Pman)。为了模型稳定且易于搭建,我们使用二维查表法来代替复杂的流体力学公式。

1. 拖拽以下模块到画布:
  • Inport (2个):在库浏览器中搜 Inport
  • 2-D Lookup Table (2个):搜 2-D Lookup Table
  • Sum (1个):搜 Sum
  • Gain (1个):搜 Gain
  • Integrator (1个):搜 Integrator
  • Outport (1个):搜 Outport
2. 双击模块设置参数:
  • Inport 1 :双击,将 Block name 改为 Throttle_Cmd (%)

  • Inport 2 :双击,将 Block name 改为 RPM_Feedback

  • 第一个 2-D Lookup Table (流入质量 m˙in\dot{m}_{in}m˙in)

  • 双击,改名为 m_dot_in_Table

  • Breakpoints 1 (节气门开度): [0 10 30 60 100]

  • Breakpoints 2 (歧管压力Pa): [20000 40000 60000 80000 101300]

  • Table data (流入流量 kg/s): [0 0 0 0 0; 0.005 0.004 0.003 0.001 0; 0.015 0.012 0.009 0.003 0; 0.04 0.035 0.025 0.01 0; 0.06 0.05 0.04 0.015 0]

  • 第二个 2-D Lookup Table (流出质量 m˙out\dot{m}_{out}m˙out)

  • 双击,改名为 m_dot_out_Table

  • Breakpoints 1 (转速RPM): [800 2000 4000 6000]

  • Breakpoints 2 (歧管压力Pa): [20000 50000 80000 100000]

  • Table data (流出流量 kg/s): [0.002 0.005 0.008 0.01; 0.006 0.015 0.025 0.03; 0.015 0.035 0.06 0.075; 0.02 0.05 0.08 0.1]

  • Sum :双击,将 List of signs 改为 |+-

  • Gain :双击,将 Gain 设为 43050000。(这是物理常数 R⋅TVman=287⋅3000.002\frac{R \cdot T}{V_{man}} = \frac{287 \cdot 300}{0.002}VmanR⋅T=0.002287⋅300 计算得来的)。

  • Integrator :双击,将 Initial condition 设为 35000 (代表怠速歧管压力 35kPa,千万不能是 0 ,否则查表报错)。勾选 Limit outputLower limit 设为 10000Upper limit 设为 105000

  • Outport :双击,改名为 P_man

3. 连线方式 (Wiring):
  1. Inport 1 (Throttle_Cmd) 连到 m_dot_in_Table 的第一个输入端。
  2. Integrator 的输出端拉出一条反馈线,连到 m_dot_in_Table 的第二个输入端。
  3. Inport 2 (RPM_Feedback) 连到 m_dot_out_Table 的第一个输入端。
  4. Integrator 的输出端再拉出一条反馈线,连到 m_dot_out_Table 的第二个输入端。
  5. m_dot_in_Table 的输出连到 Sum+ 端。
  6. m_dot_out_Table 的输出连到 Sum- 端。
  7. Sum 的输出连到 Gain 的输入。
  8. Gain 的输出连到 Integrator 的输入。
  9. Integrator 的输出连到 Outport (P_man)

需要做的具体修改步骤:

  1. 断开连线: 删除目前 Gain 模块输出端到 P_man 端口之间的连线。
  2. 移动模块: 将左侧那个悬空的 积分器 (1/s) 拖拽移动到右边,放在 GainP_man 之间。
  3. 重新连接主线:Gain 的输出端连接到 积分器 的输入端;然后再将 积分器 的输出端连接到 P_man 端口。
  4. 重新连接反馈线:积分器的输出端 (也就是它和 P_man 之间的那根线上)引出节点,像你现在画的那样,分别连接给上下两个 2-D Table 的 u2 输入端。

修改后的主干信号流向应该是这样的直线串联:
Sum 输出 →\rightarrow→ Gain →\rightarrow→ Integrator →\rightarrow→ Outport (P_man)

然后从 Integrator 的后面取信号反馈给前面。按照这个逻辑调整后,第一部分的物理意义和模型结构就完全正确了。


第二部分:扭矩生成与做功延迟子系统 (Torque Production)

这个子系统将压力和转速转化为发动机产生的扭矩。

1. 拖拽以下模块到画布:
  • Inport (2个)。
  • 2-D Lookup Table (1个)。
  • 1-D Lookup Table (1个)。
  • Math Function (1个):在 Math Operations 库下。
  • Gain (1个)。
  • Variable Transport Delay (1个):在 Continuous 库下。
  • Sum (1个)。
  • Outport (1个)。
2. 双击模块设置参数:
  • Inport 1 :改名为 P_man_Input

  • Inport 2 :改名为 RPM_Input

  • 2-D Lookup Table (指示扭矩)

  • 改名为 Indicated_Torque_Map

  • Breakpoints 1 (RPM): [800 2000 4000 6000]

  • Breakpoints 2 (Pressure): [30000 50000 80000 100000]

  • Table data (Nm): [15 35 60 75; 30 70 120 145; 40 90 160 190; 35 85 140 165]

  • Math Function :双击,Function 选择 reciprocal (取倒数),用于计算延迟时间 1RPM\frac{1}{RPM}RPM1。

  • Gain :设为 30。(时间延迟公式 τ=30RPM\tau = \frac{30}{RPM}τ=RPM30)。

  • Variable Transport Delay :双击,Maximum delay 设为 0.2Initial output 设为 15

  • 1-D Lookup Table (摩擦扭矩)

  • 改名为 Friction_Torque

  • Breakpoints 1: [0 800 2000 4000 6000]

  • Table data: [5 12 18 28 42]

  • Sum :将 List of signs 改为 |+-

3. 连线方式 (Wiring):
  1. Inport 2 (RPM) 连到 Indicated_Torque_Map 的第一个输入;将 Inport 1 (P_man) 连到第二个输入。
  2. Inport 2 (RPM) 分支引出,连到 Math Function (reciprocal)
  3. Math Function 连到 Gain (30)
  4. Indicated_Torque_Map 的输出连到 Variable Transport Delay 的第一个输入端 (数据端口)。
  5. Gain (30) 的输出连到 Variable Transport Delay 的第二个输入端 (时间延迟控制端口 *td)。
  6. Inport 2 (RPM) 再次分支引出,连到 1-D Lookup Table (Friction_Torque)
  7. Variable Transport Delay 的输出连到 Sum+ 端。
  8. Friction_Torque 的输出连到 Sum- 端。
  9. Sum 的输出连到 Outport ,改名为 Net_Torque

第三部分:曲轴转速计算子系统 (Crankshaft Dynamics)

利用净扭矩和外部负载计算转速。

1. 拖拽与设置:
  • Inport 1 :命名为 Net_Torque
  • Inport 2 :命名为 Load_Torque (测功机阻力)。
  • SumList of signs 设为 |+-
  • Gain :设为 47.74。 (这是 30π⋅J\frac{30}{\pi \cdot J}π⋅J30 的结果,假设惯量 J=0.2 kg⋅m2J = 0.2 \text{ kg}\cdot\text{m}^2J=0.2 kg⋅m2)。
  • IntegratorInitial condition 设为 0。勾选 Limit outputLower limit 设为 0Upper limit 设为 7000
  • Outport :命名为 Engine_RPM
2. 连线方式 (Wiring):
  1. Inport 1 (Net_Torque) 连到 Sum+ 端。
  2. Inport 2 (Load_Torque) 连到 Sum- 端。
  3. Sum 连到 Gain (47.74)
  4. Gain 连到 Integrator
  5. Integrator 连到 Outport (Engine_RPM)

(注意:将第一、二、三部分的 Outport 和 Inport 对应连接起来,形成一个闭环,你的物理被控对象就搭建完成了。进气管的 RPM Feedback 必须连到曲轴模块输出的 Engine_RPM 上。)


第四部分:启停与怠速控制系统 (Controller)

这部分负责输出节气门指令 (Throttle_Cmd)。

1. 拖拽与设置:
  • Discrete PID Controller

  • 双击,ControllerPID

  • Time domainDiscrete-time

  • Proportional (P) 设为 0.2

  • Integral (I) 设为 0.05

  • 点开 PID Advanced 选项卡,勾选 Limit outputUpper limit 设为 20Lower limit 设为 0 (怠速时节气门最多开20%)。

  • Constant 1 :设为 800 (怠速目标转速)。

  • SumList of signs 设为 |+-

  • Switch :双击,Criteria for passing first inputu2 >= ThresholdThreshold 设为 0.5

2. 连线方式 (Wiring):
  1. Constant (800) 连到 Sum+ 端。
  2. 将全局实际转速 Engine_RPM 连到 Sum- 端。
  3. Sum 连到 Discrete PID Controller
  4. Discrete PID Controller 的输出连到 Switch 的第一个输入端 (端口 1)。
  5. 创建一个新的 Inport 命名为 Accel_Pedal (油门踏板,0-100),将其连到 Switch 的第三个输入端 (端口 3)。
  6. 创建一个 Constant ,值为 10,连到 Switch 的中间控制端 (端口 2)。
  • 手动测试说明:当 Constant 为 0 时,Switch 导通踏板信号 (动态加速);当 Constant 为 1 时,Switch 导通 PID 信号 (闭环怠速)。
  1. Switch 的输出连到 第一部分 (进气系统) 的 Throttle_Cmd 输入端。

按照上述具体的数值和连接口一一对应搭建,点击 Run 仿真,你应该能看到模型在 800 转附近平稳收敛,并且在改变负载 (Load_Torque) 时,PID 会自动调节节气门将转速拉回 800。

下面我为你详细指出需要调整的唯一地方------顶层连线(Top-Level Wiring)

内部审查反馈(做得非常好的地方)

  1. 图3(进气歧管内部): 积分器、反馈线、加减法方向完全正确。
  2. 图4(扭矩生成内部): 延迟模块的转速倒数时间控制、查表映射完全正确。
  3. 图5(转速与控制器内部): 动力学积分、PID 反馈闭环、Switch 切换逻辑完美实现。
  • 小建议:图5最右侧输出给 Switch 的 Outport 2,建议双击改名为 Throttle_Out,这样在顶层看的时候更清晰。

需要修改的地方:打通全局闭环(针对图1/图2)

请在顶层视图执行以下"连连看"操作:

  1. 连接节气门指令(连接控制与进气):
    将右下角方块(Subsystem2)的第二个输出端口(即你内部连着 Switch 的那个端口),直接连到左侧方块(P_man进气子系统)的 throttle_cmd 输入端口上。
  2. 连接歧管压力(连接进气与扭矩):
    将左侧方块(P_man)的输出端口,直接连到上方中间方块(Net_Torque1)的 P_man_Input 端口上。
  3. 连接净扭矩(连接扭矩与动力学):
    将上方中间方块(Net_Torque1)的输出端口,直接连到右下角方块(Subsystem2)的 Net_Torque 输入端口上。
  4. 连接转速全局反馈(最关键的一步):
    右下角方块(Subsystem2)输出的 Engine_RPM(端口1)是全局的核心信号。你需要从这个端口拉出一条长线,分成两路
  • 一路连回左侧方块的 RPM_Feedback 端口。
  • 另一路连回上方中间方块的 RPM_Input 端口。
  1. 添加外部激励信号:
    在空白处拖入两个 Constant(常数)模块:
  • 第一个命名为 外部负载,连到右下角方块的 Load_Torque 输入端(设定为如 20 Nm)。
  • 第二个命名为 油门踏板,连到右下角方块的 Accel_Pedal 输入端(设定为 0)。

完成这些连线后,你的屏幕上应该只剩下三个相互连接的方形子系统和两个常数输入。点击 Run,你的发动机模型就能真正运转起来并稳定在 800 转了!

为了最直观地评估你的模型,我建议你添加 3个核心 Scope。你可以直接在顶层视图(Top-Level)的那些连线上引出分支来接 Scope,这样最清晰。

核心观测点 1:全局转速 (Engine Speed) ------ 这是最终结果

这是衡量你模型是否成功的最关键指标。

  • 位置: 在右下角方块输出的 Engine_RPM 那根长线上,拉出一个分支,接上一个 Scope
  • 双击 Scope 命名为: RPM_Scope
  • 你应该看到的波形: 点击运行后,转速应该从 0 开始迅速上升,稍微越过 800(超调),然后在一两秒内平滑地稳定在一条 800 RPM 的水平直线上。

核心观测点 2:进气歧管压力 (Intake Manifold Pressure) ------ 这是动态过程

发动机的"迟滞"主要来源于这里。

  • 位置: 在左侧方块输出的 P_man 那根线上拉出一个分支,接上第二个 Scope
  • 命名为: MAP_Scope (Manifold Absolute Pressure)
  • 你应该看到的波形: 启动瞬间,压力会有一个大的波动,稳定怠速后,绝对压力应该停留在 30,000 ~ 40,000 Pa (30-40 kPa) 左右。如果你把节气门突然开大,压力不会瞬间跳跃,而是呈现一条有平滑弧度的上升曲线(一阶惯性环节)。

核心观测点 3:控制器动作与外部负载 ------ 这是因果关系

我们要看 PID 是如何与外部负载"搏斗"的。这里建议把两个信号放进同一个 Scope 里对比。

  • 操作方法: 1. 拖出一个新的 Scope
  1. 双击打开它,点击顶部的齿轮图标(设置),找到 Number of input ports(输入端口数),改为 2
  2. 或者去图库里搜一个 Mux 模块,把两个信号绑成一根线接给 Scope。
  • 位置: * 端口 1 接到 PID 输给进气系统的 throttle_cmd 线路上。

  • 端口 2 接到你的 外部负载 常数块的线路上。

  • 命名为: Control_vs_Load

  • 你应该看到的波形: 稳定在 800 转时,节气门开度可能在一个很小的值(比如 5%)。如果你在仿真中途(比如第 5 秒)让 外部负载 突然从 0 跳变到 20 Nm,你会看到转速瞬间掉下来一点,紧接着这个 Scope 里的 throttle_cmd 会迅速爬升,把节气门顶开,从而把转速重新拉回 800。


我们之前聊过要在 MATLAB 里画高大上的论文 MAP 图。Scope 只是用来看的,要画图必须把数据送回 MATLAB 的工作区(Workspace)。

在确认波形没问题后,你可以把上面这几个位置的 Scope 替换成(或者并联上)To Workspace 模块:

  1. To Workspace 拖进来。
  2. 双击它,把 Variable name 分别改为 sim_rpm, sim_pman, sim_throttle
  3. Save format(保存格式)改为 Array(数组),这样最方便后续用代码处理。




相关推荐
数智化管理手记29 分钟前
手工统计指标误差大、效率低?指标管理系统如何告别人工算数痛点?
大数据·运维·数据库·人工智能·云计算
fthux4 小时前
RenoPit 能为普通业主做什么?看懂图纸、审查合同,提前发现装修坑
javascript·人工智能·ai·开源·github·chrome扩展·open source·edge扩展·firefox扩展
火山引擎开发者社区6 小时前
火山引擎混合云 veStack 智算平台 Day0 适配 Kimi K3
人工智能
RSABLOCKCHAIN7 小时前
AI Agents in LangGraph-2
人工智能·python
cd_949217217 小时前
哪些AI工具适合生成游戏开发用的3D道具模型?从道具草稿到引擎测试的选择方法
人工智能·3d
FII工业富联科技服务7 小时前
工业设备运维如何Agentic化?拆解Factory Brain的设备运维架构
大数据·运维·人工智能·架构·制造
糖果店的幽灵7 小时前
人已经用 WorkBuddy 找工作拿了面试,你还在一份份手工改简历
人工智能·面试·职场和发展·langgraph
qq29538 小时前
2026 财搭子决策模拟器:多智能体投研架构能力拆解
大数据·人工智能·架构
满怀冰雪9 小时前
12-PaddlePaddle, 飞桨, 分类模型, 训练循环, 损失函数, 优化器, cross_entropy, Adam
人工智能·深度学习·分类·paddlepaddle
冬奇Lab9 小时前
AI 评测系列(08):评测 CI/CD——持续质量门控
人工智能