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(数组),这样最方便后续用代码处理。




相关推荐
oscar9991 小时前
当 AI 学会“动手”:DeepSeek-TUI 是如何用终端颠覆编程工作的?
人工智能·deepseek-tui
MY_TEUCK1 小时前
【MY_TRUCK - AI 应用】RAG 与 LangChain 入门:检索增强生成、向量检索与链式编排
人工智能·机器学习·langchain
theaiera1 小时前
用 Tauri 写一个 AI Chat:3MB 的桌面应用干翻 Electron 100MB
人工智能
scglwsj1 小时前
Spec:让 AI 在实现前真正理解问题
人工智能
狐狐生风1 小时前
LangGraph 核心概念全解笔记
人工智能·python·langchain·prompt·langgraph
EAIReport1 小时前
深度拆解WorkBuddy技术实现:腾讯云全场景AI智能体的架构设计与核心逻辑
人工智能·云计算·腾讯云
美狐美颜SDK开放平台1 小时前
什么是美颜SDK?高并发场景下的企业级美颜SDK如何开发?
android·人工智能·ios·美颜sdk·第三方美颜sdk·视频美颜sdk
Westward-sun.1 小时前
Claude Code 接入 DeepSeek V4 Pro:从 npm 安装到 CC Switch 配置完整记录
网络·人工智能
项目題供诗1 小时前
STM32-对射式红外传感器计次&旋转编码器计次(九)
人工智能·stm32·嵌入式硬件