☰
温控系统建模实战:基于阶跃响应与Matlab系统辨识工具箱
2026/10/5 1:08:39 网站建设 项目流程

做温控项目最头疼的环节,往往不是控制算法本身,而是你怎么把一坨真实的物理对象变成计算机能算的数学模型。我在实验室调过好几次温控系统,PWM占空比给下去,温度慢慢悠悠飘上来,看起来很简单,但真要写PID参数、做仿真,没有传递函数一切都是空谈。后来我用Matlab系统辨识工具箱直接把阶跃响应数据喂进去,几分钟出一条传递函数,再拿Simulink搭个闭环一验证,效果基本能对上。这篇就是用阶跃响应来做温控系统建模的全流程记录,从采数据、预处理、辨识到验证都给你写清楚,代码也会贴在对应章节,做温控、做过程控制、搞嵌入式控制算法验证的朋友都能直接抄作业。

1. 内容整体设计与思路拆解

1.1 为什么选择阶跃响应法做温控建模

温控系统是典型的惯性过程,加热功率改变后,温度不会立刻跟着变,而是要经历一个缓慢爬升的过程。这种特性用一阶惯性加纯滞后模型来描述非常合适,也就是常说的FOPDT(First Order Plus Dead Time)模型,数学形式是K除以(Ts+1)再乘以e的负Ls次方。整个建模思路就是:给系统加一个阶跃输入,记录输出响应曲线,从曲线上读出增益K、时间常数T和纯滞后时间L,然后得到一个初始的传递函数模型。

我最早也想过用机理建模,解热传导偏微分方程,搞了半天傅里叶级数都出来了,结果模型的边界条件稍微一变,仿真全对不上。因为温控对象往往有非线性、热容分布不均匀、环境散热干扰这些问题,纯机理模型很难覆盖。反过来,阶跃响应法不需要你理解系统内部的热力学结构,只需要输入输出数据,属于典型的黑箱或灰箱建模,特别适合工程现场快速落地。

用Matlab系统辨识工具箱而不是手算切线法,主要原因是手算切线法对响应曲线上的噪声太敏感了,不同的操作者画出来的切线可能差很多。系统辨识工具箱有完整的估计算法,比如最小二乘法、子空间法,它在处理含噪声数据时会更稳健,而且工具箱还能给出拟合优度,让你对模型质量心里有数。

1.2 系统辨识工具箱的核心能力与使用场景

Matlab的系统辨识工具箱(System Identification Toolbox)不是一个单一函数,而是一整套从数据预处理、模型结构选择、参数估计到模型验证的工作流。它的核心界面是System Identification App(在Matlab命令行输入systemIdentification就可以打开),里面可以导入时域数据、频域数据,然后让你选模型结构,比如传递函数模型(tf)、过程模型(process)、状态空间模型(ss)、ARX/ARMAX模型等等。

对于温控系统这种连续过程,我通常直接用procest函数来拟合一阶或二阶过程模型,因为procest可以估计K(增益)、Tp(时间常数)、Td(纯滞后)、Tz(零点时间常数)以及模型阶次。它的好处是参数物理意义非常清晰,你拿到K、Tp、Td之后,可以直接去工程上解释:K代表稳态增益,也就是温度最终升了多少;Tp代表惯性大小,决定温度爬升快慢;Td代表纯滞后,说明信号传递延迟。

还有一个实用场景是控制器设计。你有了传递函数之后,可以用pidtune或者sisotool来设计PID参数,也可以用Simulink做闭环仿真。辨识模型和真实系统的误差只要控制在一定范围内,控制器参数就能在仿真中先试出来,再移植到真实系统,大大减少现场调试的风险和次数。这也是我做这个项目的核心目的之一。

2. 核心细节解析与实操要点

2.1 阶跃响应实验的准备工作

做阶跃响应实验前,先想清楚几个关键问题,不然数据白采。

首先是工作点选择。温控系统通常有非线性,比如加热器在常温段和高温度段的散热条件不一样,所以在不同工作点做阶跃响应,得到的增益和时间常数会有差异。我的做法是先在目标工作点附近让系统稳定(比如让温度稳定在45度左右),然后再加阶跃。阶跃幅度不能太大,否则系统可能进入严重非线性区或者触发保护;也不能太小,否则响应幅度会被噪声淹没。一般来说,阶跃输入量是最大输入的10%到20%比较合适,比如PWM占空比最大是100,就加10到20的阶跃。

其次是采样周期和数据长度。采样周期要足够快,至少比系统的时间常数小10倍以上,才能捕捉到瞬态过程的细节。但采样太密也会导致数据文件过大,计算量增加,而且容易受到高频噪声干扰。对于时间常数几十秒的温控系统,采样周期设0.5秒到1秒就够用了。数据长度至少要覆盖响应达到稳态的1.5倍时长,也就是如果系统大概120秒到达稳态,那至少要记录180秒的数据。

我这次实验的平台是一个小型的加热铝块,通过PWM控制加热膜功率,温度传感器是NTC热敏电阻,单片机采集温度后通过串口发到电脑。整个实验流程是:先把系统稳住,给一个恒定的PWM占空比(比如30%),温度稳定后记录基准温度,然后在某个时刻把PWM跳变到50%,持续记录温度数据直到新稳态出现。

2.2 数据预处理:去趋势、去野值、平滑滤波

采集回来的原始数据不能直接送去辨识,必须先做预处理。这里说的预处理主要包括三个步骤。

第一步是去趋势(detrend)。如果你只关心系统相对于工作点的动态响应,就需要把稳态基准值减掉,让信号的初始值归零。在Matlab里可以用detrend函数,或者手动减去采集数据前一段的均值。比如我采集到的初始温度是45.2度,我就把整条温度曲线都减去45.2,这样辨识出来的模型就是交流分量模型,后面做仿真时再加上基准值就可以。

第二步是去野值。串口通信偶尔会有丢帧或乱码,导致数据中突然出现一个异常大的跳变尖刺。这类野值如果不处理,辨识算法会被严重带偏。我一般用中值滤波把明显超出局部分布的点滤掉,或者干脆用rmoutliers函数自动检测。但是要注意,不要过度平滑,因为温控系统的响应本身是平滑的,如果滤波参数太强,会把真实的动态特征也给吃掉,导致辨识出来的时间常数偏大。

第三步是重采样,让时间轴均匀化。串口数据到达电脑的时间间隔可能不是完全均匀的,特别是当缓冲区满或者系统调度抖动时,相邻两个点的时间间隔会有几十毫秒的偏差。做辨识前需要把数据插值到等间隔的时间轴上,Matlab里用resample或者interp1都可以。我用的是interp1,插值成0.5秒间隔的等间隔序列,这样后面用iddata创建数据对象时不会因为时间轴不均匀而出问题。

2.3 选择模型结构的讲究

系统辨识工具箱支持很多模型结构,选错结构等于白算。对于温控系统这种惯性对象,我通常从低阶开始试,因为低阶模型更容易解释,控制器设计也更有把握。最常见的是从一阶惯性加纯滞后开始试,也就是模型形式是K/(Ts+1)乘以e^(−Ls)。

如果有证据表明系统有更复杂的动态,比如响应曲线出现明显的S形拐弯或者响应速度先慢后快,再考虑二阶或者三阶过程模型。用procest的时候,有一个P1D、P2D、P1、P2之类的选项,分别代表一阶加滞后、二阶加滞后、纯一阶、纯二阶等。我一般会同时拟合一阶和二阶,然后比较拟合优度。如果二阶比一阶的拟合度提升非常有限(比如从92%提升到92.5%),那宁可选择一阶,因为一阶模型结构简单、参数少、更稳健,适合做控制。

还有一个容易被忽略的点:是否需要在模型中考虑零点。温控系统通常没有明显的零点,但某些特殊的传感器安装位置会造成响应初期有一个反向的暂态,这时候可能要加入零点项。procest里的P1DZ或P2DZ选项就是带零点的模型。我的经验是,除非数据明确表明需要零点,否则不要加,加了会过拟合。

3. 实操过程与核心环节实现

3.1 数据采集与导入:从串口到Matlab

实际中的数据采集我一般分成两种方式:一种是在线实时采,直接在Matlab里打开串口,把数据读进来;另一种是先由单片机把数据存成CSV文件,然后再用Matlab的readtable导入。离线导入的方式更稳妥,因为在线采集容易受到Matlab界面的干扰,而且数据不好回放。实测下来,我用的是单片机定时发送逗号分隔的数据行,格式是"时间,温度",然后Matlab读取整个文件。

% 读取CSV格式的阶跃响应数据 % 文件格式:时间(s),温度(℃) data = readtable('step_response.csv'); t_raw = data.Time; T_raw = data.Temperature;

这里有个小坑是CSV文件的换行符或者编码格式可能不一致,中文版的Excel另存的CSV有时候是GBK编码,Matlab读进来会乱码,所以建议在单片机里直接输出纯英文表头,或者用Notepad++转成UTF-8 without BOM再读取。我后来直接在单片机里只输出两列裸数据,不带表头,这样最不容易出问题。

3.2 创建iddata对象与数据裁剪

iddata是系统辨识工具箱中最核心的数据容器,它同时保存输入信号、输出信号和采样时间。创建方式非常简单。

% 去掉最开始稳定阶段的数据(前100秒) startIdx = find(t_raw >= 100, 1, 'first'); t = t_raw(startIdx:end); T = T_raw(startIdx:end); % 截取到响应进入新稳态后再加50秒 steadyIdx = find(t >= t_raw(end) - 50, 1, 'first'); t = t(1:steadyIdx); T = T(1:steadyIdx); % 减去初始稳态值 T0 = mean(T(1:30)); % 前30个点的均值作为初始稳态 u_step = 20; % PWM占空比阶跃幅度:从30%跳变到50% u = zeros(size(t)); u(t >= 100) = u_step; % 阶跃发生在t=100秒(相对于起始时间) % 创建iddata对象:输出T-T0,输入u data_id = iddata(T - T0, u, 0.5); data_id.Name = '温控系统阶跃响应数据'; data_id.InputName = 'PWM占空比增量(%)'; data_id.OutputName = '温度增量(℃)'; data_id.InputUnit = '%'; data_id.OutputUnit = '℃';

注意,阶跃时刻之前的时间轴要保留一段,这段的输入为0、输出为0,这样辨识算法才能准确估计出纯滞后L的大小。如果数据是从阶跃瞬间开始记录的,那么滞后时间就会被模型完全吸收到时间常数里,辨识结果就不准了。

这里补充一个细节:输入信号我用的是增量u,而不是真实的PWM占空比绝对值。因为系统在当前工作点左右的小范围内可以近似线性化,增量模型和绝对值模型在数学上是等价的,但增量模型在数值上更稳定,避免处理大数运算。

3.3 一阶与二阶过程模型辨识:procest实战

数据准备完毕,下面进入正题,用procest做模型估计。工具箱的图形界面可以手动点,但命令行模式更适合复现和批量对比。

% 拟合一阶惯性加纯滞后模型 P1D:K/(1+Tp*s)*exp(-Td*s) opt1 = procestOptions('Display', 'on'); sys1 = procest(data_id, 'P1D', opt1); % 拟合二阶惯性加纯滞后模型 P2D:K/((1+Tp1*s)*(1+Tp2*s))*exp(-Td*s) sys2 = procest(data_id, 'P2D', opt1);

运行完以后,命令行会输出模型的各项参数和拟合优度(Fit percent)。一阶模型的输出通常像下面这样(这里给出一个代表性的示意输出):

Process model with transfer function: K G(s) = ---------------- * exp(-Td*s) 1 + Tp1*s K = 0.91272 Tp1 = 43.715 Td = 3.1296

什么意思?K等于0.91,代表输入阶跃20%时,温度的最终增益大约是0.91摄氏度每百分比PWM。也就是说,20%的阶跃最终会让温度上升大概18.2度,这个值和我实际观察到的稳态温升18.5度非常接近。Tp1约43.7秒,这表明系统的时间常数大约是44秒,意味着温度在阶跃之后大约3倍时间常数(约131秒)才会接近稳态的95%。Td约3.1秒,表示传感器和热量传递路径带来的纯滞后约3秒。

二阶模型的输出会多一个极点Tp2,如果Tp2和Tp1数值接近,说明系统可以用真正的一阶模型表达;如果Tp2明显比Tp1小很多,说明系统还有一个快动态存在。把两个模型画出来比较一下拟合优度,我用compare函数来完成。

% 模型验证:用原始数据对比模型输出 compare(data_id, sys1, sys2);

从结果图上看,如果一阶模型已经能跟上曲线的趋势,只是在起始段有一点偏差,那么二阶模型可能提升有限。就我这个实验而言,一阶模型的拟合优度是93.4%,二阶模型是94.1%,提升不到1个百分点。所以我就选了结构更简单的一阶模型作为最终结果,不加额外的零点。

3.4 模型验证:残差分析与预测效果

辨识出来一个模型不能直接交付,必须做验证。系统辨识的本质是寻找一个能解释观测数据的数学模型,但模型好不好,要看它在新数据上的预测能力。我通常做两层验证。

第一层是直接用同一份数据做compare,看拟合优度。第二层是另做一组独立的阶跃响应实验,用新数据来检验模型。比如我用20%的阶跃辨识出模型,然后用30%的阶跃做验证,看看模型在新输入幅度下是否仍然准确。如果能拟合得不错,说明模型在工作点附近有一定的泛化能力。

此外还要看残差。系统辨识工具箱里有resid函数,用来计算和绘制模型输出的残差(即真实输出与模型输出的差)的自相关函数,以及残差与输入信号的互相关函数。如果模型与数据匹配良好,残差应该表现为白噪声,也就是说自相关函数在零滞后处有一个峰值,其他滞后处都在置信区间内;互相关函数也应该基本落在置信区间内。如果残差中存在明显的周期性或者相关性,说明系统中有未被模型捕捉到的动态,比如非线性、噪声的周期性扰动或者外部干扰。

% 残差分析 resid(data_id, sys1);

我遇到过一种情况,数据里有非常明显的高频噪声,比如电源纹波引起的温度波动,而模型是低通特性的大惯性系统,天然滤掉高频。此时残差里会残留很多高频分量,自相关图也会显示在零附近很尖锐的峰值,但这种残差不代表模型结构错误,只是说明系统有高频测量噪声,不影响控制用途。

3.5 从传递函数到Simulink闭环仿真

有了传递函数之后,下一步我建议直接扔到Simulink里做闭环仿真,把PID控制器参数试出来,再做真实系统实验。这样既能验证模型,也为后续控制调参提供起点。

在Simulink里,我们可以直接使用Transfer Fcn模块,分子和分母系数填写上一步得到的一阶传递函数参数。同时用Transport Delay模块模拟纯滞后Td。整个闭环结构可以这样搭:阶跃参考信号作为设定值,经过PID控制器,连接到传递函数模型,再与反馈比较。需要注意的是,如果辨识模型输入是PWM占空比增量,输出是温度增量,那么在仿真中的参考信号也应该是相对于工作点的增量信号,最后仿真结束后再加上工作点偏移量,才是实际的温度。或者也可以直接把系统非线性做一个查表偏置处理。

我之前在Simulink里加了PID参数自动整定,用的是pidtune函数,对传递函数模型直接设计PID。对于一阶惯性加滞后模型,pidtune通常会给出一个比例加积分的方案,比例项用于加速响应,积分项消除稳态误差,微分项一般不建议加,因为测量噪声会通过微分项被放大,而温控系统本身惯性大,微分作用帮助有限。

% 用pidtune设计PID控制器 [C, info] = pidtune(sys1, 'PID', 0.05); % 目标带宽0.05 rad/s C

pidtune里面的目标带宽要反复试。带宽取得太大,控制器增益过大,容易造成系统振荡;取得太小,响应太慢,温度半天到不了设定值。我的经验是先按系统的截止频率(约1/Tp,也就是0.023 rad/s)的两到三倍来设置,然后根据仿真响应微调。

4. 常见问题与排查技巧实录

4.1 辨识结果K值总是偏大或偏小怎么办

K值也就是稳态增益,如果辨识出来明显偏离实测的温升比例,问题大概率出在数据没到稳态就截断了。尤其是惯性很大的温控系统,你看着温度在慢慢涨,就以为差不多了,其实离稳态还差10%。这会导致辨识算法低估时间常数,同时为了弥补这个差距,K值就会被上调。

解决办法是加长实验记录时间,让系统在新输入下至少稳定到最终稳态附近。判断标准很简单:连续两分钟的温升小于0.1度,就可以认定为基本稳态。如果实验条件不允许等那么久,可以试试在辨识时给数据加权,把稳态部分的数据权重提高,让算法更重视尾段。但在procest里直接做权重比较麻烦,最稳妥的还是补做一次完整的实验。

还有一种情况是K偏小,这通常是输入阶跃幅度给的太小,响应幅度和噪声差不多,辨识器把一部分真实响应当成噪声滤掉了。所以阶跃幅度要在系统安全范围内尽量大一点,让信噪比足够高。

4.2 拟合优度很低,模型完全对不上,如何排查

拟合优度低,首先要检查数据是否出了前缀错误。比如阶跃时刻标注错了,输入信号和输出信号时间对不上,算法就会把整个响应视为噪声,拟合优度肯定很低。再检查一下数据里是否存在野值,我之前用中值滤波保护了数据,但如果野值在滤波后仍然残留,辨识时就会被当成真实信号。

还要注意模型的初始条件。procest默认假设系统初始状态为零。如果你的数据是从非零稳态开始的,而你没有减去初始值,那么模型的输出会带着直流偏置,拟合优度会被严重拉低。处理方式就是前面说的去趋势,要把初始稳态减掉。

如果这些都没问题,那就要考虑系统是否真的是线性时不变系统。比如加热器是继电器通断控制的,那么系统的动态特性和PWM控制方式会不一样,输出会有明显的纹波,这时候一阶模型肯定不够用。可以考虑用更高阶的模型,或者改用ARX模型来捕捉更复杂的动态。

4.3 残差明显相关,说明模型结构需要调整

残差分析如果显示自相关图超出置信区间,说明残差里还有模型没解释掉的动态成分。一种常见情况是系统有显著的二阶振铃特性,也就是输出在爬升过程中有过冲回摆的现象,这时候一阶模型无能为力,应该换成二阶模型。还有一种情况是系统有积分特性,比如温控对象漏热很小,热量持续累积导致输出不趋向稳态而是一直上升,这时候应该用带积分项的过程模型,比如P1I或P2I。

不过要特别提醒的是,温控系统经常会有环境温度缓慢漂移带来的干扰,比如白天阳光照射、空调启停等,这些外部干扰造成的低频相关残差,不一定代表系统模型本身有误。遇到这种情况,我习惯把实验安排在环境温度相对稳定的时间段进行,或者加锡纸保温来减少环境干扰。

4.4 sys1的时间和真实系统的时间总是对不上的坑

很多人在Simulink仿真中用传递函数模型非常顺手,但转到真实系统上就对不上。时间对不上最主要的原因,是参与了纯滞后Td。procest辨识出来的Td单位是秒,而你在Simulink里用Transport Delay模块时也要用秒。但如果你的采样周期不是整数秒,或者数据经过了重采样,时间轴可能发生了细微偏移,导致Td看起来偏大或偏小。

我踩过一次坑:因为串口发送时间间隔不稳定,我用interp1重采样到0.5秒间隔,但是重采样的起始时间没对齐,导致时间轴整体偏了一个采样周期。这样辨识出来的Td会多出或者少掉0.5秒,看着问题不大,在PID比例积分控制下也能工作,但对要求高的温控对象,比如半导体激光器温控,这种误差就不可接受。所以做重采样时,一定要指定原始时间轴的起始点和结束点,确保对齐。

另一个大坑是执行器饱和。真实系统里PWM占空比有上下限0到100%,而仿真里的PID输出是不受限的。如果你的控制器设计让PID输出频繁超过100%,真实系统会限幅,实际控制效果和仿真就会差很多。我在仿真中会增加一个Saturation模块,限幅在0到100,并且把PID输出也记录在工作区里,和真实PWM命令做对比。

4.5 快速排查清单

下面这个表是我每次做阶跃响应辨识时必查的项目,也给你参考。

检查项常见问题处理方式
数据时长记录太短,没到稳态延长记录时间到稳态后至少50秒
阶跃时刻时间标注错误用差分信号找突变点确认
初始状态未减初始稳态值手动或detrend去除直流分量
野值串口丢帧导致异常跳变中值滤波或rmoutliers清理
采样间隔时间轴不均匀interp1重采样到等间隔
模型阶次一次模型不够用尝试P2D或更高阶模型
外部干扰环境温度漂移保温、避开空调/阳光直射
执行器饱和仿真和实际控制量限幅不同Simulink中加Saturation模块

5. 扩展思考:从一阶温控模型到系统辨识工作流

用阶跃响应对温控系统建模只是系统辨识工具箱的一个应用入口。做完这个项目之后,我最大的感受是:这套方法的本质,是用数据说话,把那些机理上说不清、纯靠试错调参的麻烦,转换成了一条通顺的流水线。虽然这个案例只用了温控系统一种场景,但同样的流程完全适用于电机转速控制、液位控制、压力控制、气流温度控制等几乎所有过程控制对象。

具体来讲,只要你能制造一个激发信号(阶跃、正弦扫频、PRBS),并且能同步记录输入和输出,你就可以用系统辨识工具箱提取出系统的数学模型。这套流程的价值在于它把工程师从无穷无尽的现场试错中解放出来——以前我调温控PID可能要反复凑参数好几天,现在先在仿真里用辨识出的模型整定好,再上真实系统微调一两个参数就能用。省下来的时间,非常可观。

另外,Matlab系统辨识工具箱里关于模型验证的一些思想,比如残差分析、交叉验证、拟合优度评估,不仅适用于Matlab,也适用于Python的sysidentpy、R的dsm等工具。核心是验证思维和建模流程,而不是某个特定软件。所以我建议初学者不要只盯着工具箱的按钮点来点去,一定要理解每一步背后的信号处理和系统辨识原理,否则换一个平台又不会用了。

我个人在实际操作中的体会是,建模这件事,贪多嚼不烂。你先拿一阶惯性加纯滞后模型把一个温控系统吃透,能把K、Tp、Td这三个参数解释得明明白白,就已经超越了绝大多数只会调PID但不知道系统长什么样的人。之后再往二阶、状态空间、非线性去扩展,就是水到渠成的事。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询