简介:面向电气工程、电机控制方向的学生与工程师,这份永磁同步电机直接转矩控制改进版仿真资料可用于课程设计、科研复现与控制策略对比。模型围绕DTC直接控制定子磁链和电磁转矩的思路展开,包含PMSM电磁动态建模、转矩与磁链估算、滞环控制器、逆变器开关状态选择、转速电流反馈及负载与仿真参数设置,便于观察改进策略对动态响应和稳态性能的影响,也可对滞环宽度、磁链给定等关键参数开展调试。压缩包共2个文件,含1个Simulink模型文件和1个MATLAB脚本,大小约32KB;前者用于搭建和修改完整控制回路,后者可用于提取仿真数据并绘制转矩、磁链、转速与电流波形。已有478人学习,适合希望快速理解PMSM DTC实现细节、开展参数调试和改进前后效果对比的读者。
1. 从一段抖动的转矩波形说起
在 MATLAB/Simulink 里搭永磁同步电机直接转矩控制,第一次跑通往往是这样:转速给定 1000 r/min,空载启动顺利,转矩给定 5 N·m 之后,示波器上的电磁转矩在 4.2 到 5.8 之间来回跳,相电流波形毛刺很重,FFT 一算 THD 二十几个点。这不是模型搭错了,而是传统滞环直接转矩控制的固有脾气——开关频率不固定、转矩脉动跟着滞环带宽走。这份永磁同步电机直接转矩控制改进版仿真模型,要解决的就是这段让人挠头的波形:它在保留滞环控制器骨架的前提下,给出了几种改进路子,包括 SVM-DTC、占空比调制和带补偿的磁链观测器。适合手上已经有电机控制基础、打算把 DTC 从「能转」推到「能看」的人。
2. 模型全景:顶层 slx 的模块划分与信号流
拿到一份陌生的 Simulink 模型,很多人第一反应是双击进去乱点,点到第三个子系统就迷路了。我一般先退出来看文件夹,再看顶层。这套模型的组织方式是典型的教学与二次开发兼顾型:脚本和模型分开、被控对象和控制器分开、MATLAB Function 集中放在一个目录里,改动点比较集中。
2.1 工程目录与文件构成
常见做法是把所有可执行的.m脚本放在根目录,把被控对象封装成独立库,把控制器里逻辑复杂、不好用模块拼的部分写成 MATLAB Function。
PMSM_DTC_Improved/ ├─ init_params.m 参数初始化脚本,必须先跑 ├─ PMSM_DTC_Improved.slx 顶层模型(可直接双击运行) ├─ PMSM_Lib.slx 电机 + 逆变桥封装库 ├─ controllers/ │ ├─ torque_est.m 磁链幅值、磁链角、转矩估算 │ ├─ sector_detect.m 磁链角到 1~6 扇区的映射 │ ├─ dtc_switching.m 传统 DTC 开关表 │ ├─ svpwm_calc.m 参考电压到三相导通时间 │ ├─ duty_calc.m 占空比 DTC 的有效矢量占空比 │ └─ flux_observer.m 带幅值补偿的定子磁链观测器 ├─ scripts/ │ ├─ plot_steady.m 稳态波形与转矩脉动峰峰值统计 │ ├─ plot_dynamic.m 突加负载、转速阶跃的动态曲线 │ └─ thd_fft.m 相电流 FFT 与 THD 计算 └─ data/ └─ case_*.mat 跑完存下来的工况数据表里最关键的两行是init_params.m和PMSM_Lib.slx。前者决定模型里所有 Gain、Relay、MATLAB Function 的参数来源,后者决定你改电机参数时要不要动顶层。把电机库单独抽出来的好处是,想换成内置的Permanent Magnet Synchronous Machine模块、或者换成自己写的离散化状态方程,只动一个文件。
2.2 顶层信号流:从转速给定到门极信号
顶层的连线可以按「给定 → 调节 → 调制 → 主电路 → 反馈」五段来读,搞清楚这五段,模型就没有黑匣子了。
| 段落 | 主要模块 | 输入 | 输出 |
|---|---|---|---|
| 给定 | Step / Signal Builder | 无 | 转速给定 ω* |
| 转速环 | Discrete PID 或 MATLAB Function | ω*、实测 ω | 转矩给定 Te*,带限幅 |
| 调制 | Relay + 开关表 / SVPWM | Te*、ψ*、估算磁链转矩 | 六路门极信号 |
| 主电路 | 三相逆变桥 + PMSM | 门极信号、母线电压 | 三相电流、转速、转子角 |
| 反馈 | Clarke、观测器、估算 | ia/ib/ic、门极状态、Udc | iα/iβ、ψα/ψβ、Te、θs |
传统 DTC 和 SVM-DTC 在顶层上的差别只有「调制」这一段的替换:前者输出的是六个开关矢量编号,后者输出的是三相占空比再和三角载波比较。两条支路通常用两个 Manual Switch 或一个 Variant Subsystem 并联,方便对比波形。
反馈段有个细节值得单独说:定子电压 uα/uβ 怎么来。工程上有两种取法,一是用母线电压乘以开关状态重构(便宜,但受死区和管压降影响),二是直接从电机测量端引(干净,但真实系统里拿不到)。模型里一般是前者,这也正是后面磁链观测器会漂的原因,第 5 章会展开。
2.3 init_params.m:一次把参数喂给全模型
Simulink 模型最大的坑之一,是参数散落在几十个模块的对话框里,改一个电阻要翻八个子系统。所以这套模型把所有参数收到一个脚本里,用变量名引用。
%% init_params.m —— 打开 slx 之前先跑一次 Ts = 1e-4; % 控制与开关周期,10 kHz Tsim = 0.5; % 仿真时长 (s) Udc = 311; % 直流母线电压 (V) Rs = 2.875; % 定子电阻 (Ohm) Ld = 8.5e-3; % d 轴电感 (H) Lq = 8.5e-3; % q 轴电感 (H),表贴式取 Ld = Lq psi_f = 0.175; % 永磁体磁链 (Wb) p = 4; % 极对数 J = 8e-4; % 转动惯量 (kg·m^2) Bm = 1e-3; % 粘滞阻尼系数 psi_ref = psi_f; % 定子磁链参考,id=0 时约等于永磁磁链 Te_max = 8; % 转矩给定限幅 (N·m) h_psi = 0.01; % 磁链滞环带宽 (Wb) h_te = 0.2; % 转矩滞环带宽 (N·m) Kp_w = 0.05; % 转速环比例 Ki_w = 0.50; % 转速环积分 Kc_flux = 20; % 磁链观测器幅值补偿增益这段脚本里最容易被忽略的是psi_ref = psi_f这一行。异步电机的 DTC 里,定子磁链参考通常取额定值,很多人直接把那个习惯搬到永磁同步电机上,结果磁链圆画出来半径偏大,电流空载就比别人高一大截。表贴式永磁同步电机在 id=0 附近运行时,定子磁链幅值就等于永磁体磁链,参考值取psi_f才是对的;如果做弱磁,再按转速往上叠一个负的 id 分量把它压下来。
h_psi和h_te是滞环带宽,也是拿来做对比实验的两个旋钮。带宽减半,转矩脉动大概减半,但开关次数翻倍,逆变器损耗上去了——这个取舍在仿真里看不出来,在硬件上是要烧管子的,属于典型的仿真跑得欢、上板就翻车的点。
参数脚本的调用顺序也要注意:init_params.m必须在模型打开后、点运行前执行,而且模型要用Model Properties → Callbacks → InitFcn挂上,或者用Simulink.SimulationInput组织批量仿真。只靠手点一次,过两天再打开模型,变量全丢,报一堆Undefined variable。
3. 传统 DTC 主链路:滞环控制器、扇区判断与开关表
改进版的前提是原版,所以先把传统链路拆干净,后面才知道改哪儿、为什么改。这一章的四段代码是整套模型的地基:估算、滞环、扇区、开关表。每一段我都在自己的模型里跑过,能直接抄进 MATLAB Function 模块。
3.1 磁链与转矩的估算
直接转矩控制的核心思想就是不拆 dq,直接在 αβ 坐标系里控制定子磁链的幅值和电磁转矩。这两个量都不是测出来的,是算出来的。
function [Te, psi_amp, theta_s] = torque_est(psi_a, psi_b, ia, ib, p) % 输入: % psi_a, psi_b 定子磁链 αβ 分量 (Wb) % ia, ib 定子电流 αβ 分量 (A) % p 极对数 % 输出: % Te 电磁转矩 (N·m) % psi_amp 定子磁链幅值 (Wb) % theta_s 定子磁链角 (rad),用于扇区判断 psi_amp = sqrt(psi_a^2 + psi_b^2); theta_s = atan2(psi_b, psi_a); Te = 1.5 * p * (psi_a * ib - psi_b * ia); end公式本身很干净,Te = 1.5p(ψα·iβ − ψβ·iα),物理含义是定子磁链矢量叉乘定子电流矢量。1.5这个系数来自等幅值 Clarke 变换。这里有个特别容易踩的量纲坑:如果你的 Clarke 变换用的是等功率变换(系数 2/3 或 √(2/3)),转矩公式前面的系数就得跟着改。我见过一次波形幅值永远差 1.5 倍的现场,最后翻出来是前级 Clarke 模块照抄了别人家的系数,两边对不上。系数不一致是 DTC 里最隐蔽的量纲翻车点之一。
定子磁链本身由电压积分得到:
function [psi_a, psi_b] = flux_pure_integral(ua, ub, ia, ib, Rs, Ts) % 纯积分型磁链观测器,最朴素的做法,用来当改进方案的对照 persistent pa pb if isempty(pa) pa = 0; % 初值影响启动阶段的转矩冲击 pb = 0.175; % 一般把初值设成永磁磁链,减小启动瞬态 end pa = pa + Ts * (ua - Rs * ia); pb = pb + Ts * (ub - Rs * ib); psi_a = pa; psi_b = pb; endua和ub一般由母线电压和上一拍开关状态重构:ua = Udc/3 * (2*Sa - Sb - Sc),ub = Udc/sqrt(3) * (Sb - Sc)。用零阶保持的上一拍开关量,是为了避免代数环(同一采样周期内电压依赖开关、开关又依赖电压)。这个纯积分版本能用,但跑十几秒就会看到磁链圆慢慢偏心、中心不在原点——原因和治法放到第 4 章。
3.2 双滞环与扇区判断
传统 DTC 不设电流环、不设调制器,直接靠两个 Bang-Bang 控制器决定「该施加哪个矢量」。
磁链滞环比较psi_amp和psi_ref:超出上限输出 +1(需要增磁),低于下限输出 −1(需要弱磁),带内输出 0(保持)。转矩滞环比较Te和Te_ref,同理输出 +1 / 0 / −1。别小看中间那个「0」态,三阶滞环相比二阶,能让矢量选择更细腻,转矩脉动小一点,代价是控制逻辑稍复杂。
在 Simulink 里这两个东西我一般直接用 Relay 模块,因为调带宽时双击改数字就行,比改代码快:
| 参数 | 磁链滞环 Relay | 转矩滞环 Relay |
|---|---|---|
| Switch on point | h_psi | h_te |
| Switch off point | -h_psi | -h_te |
| Output when on | 1 | 1 |
| Output when off | -1 | -1 |
| Sample time | Ts | Ts |
如果写成 MATLAB Function,逻辑是out = (err > h) - (err < -h),一行搞定,好处是能做变带宽。带宽这个参数很玄学:太宽转矩脉动大、电流 THD 高;太窄开关频率飙升,仿真步长必须跟着减小,跑起来慢到怀疑人生。我一般先给h_te = 0.2 N·m、h_psi = 0.01 Wb,按额定转矩的 5%~10% 取,跑出来看波形再往回收。
扇区判断负责告诉控制器「定子磁链现在在哪个 60° 区间里」。
function sec = sector_detect(theta_s) % 扇区 1 以 -30° 为中心,区间 [-30°, 30°) % theta_s 为磁链角,弧度,范围 (-pi, pi] theta = mod(theta_s + pi/6, 2*pi); % 左移 30°,让扇区 1 从 0 开始 sec = floor(theta / (pi/3)) + 1; % 结果 1~6 endmod(..., 2*pi)这一步不能省,atan2输出在 (−π, π],负角度直接除以 π/3 取整会得到 0 或负数,开关表一索引就报错。扇区起点定在 −30° 还是 0°,不同教材不一样,这直接决定开关表长什么样,改的时候一定要两边一起改。
3.3 开关表:把滞环输出翻译成门极信号
两个滞环加一个扇区,一共 3×3×6 种组合,落到一张表里就是经典的 DTC 开关表。
function [Sa, Sb, Sc] = dtc_switching(sec, dpsi, dte) % 输入: % sec 1~6 扇区号 % dpsi +1 需要增磁, 0 保持, -1 需要弱磁 % dte +1 需要增转矩, 0 保持, -1 需要减转矩 % 输出: % Sa/Sb/Sc 三相上桥臂开关,1 导通 0 关断 persistent TBL if isempty(TBL) % 行顺序:(dpsi,dte) = (1,1) (1,-1) (-1,1) (-1,-1) % 列:扇区 1~6,电压矢量 V1~V6 分别位于各扇区中心 TBL = [ 2 3 4 5 6 1; % 增磁 + 增转矩 6 1 2 3 4 5; % 增磁 + 减转矩 3 4 5 6 1 2; % 弱磁 + 增转矩 5 6 1 2 3 4]; % 弱磁 + 减转矩 end if dte == 0 v = 0; % 转矩在带内,施加零矢量保持 else idx = (dpsi < 0)*2 + (dte < 0) + 1; v = TBL(idx, sec); end % 矢量编号到三相开关:V1(100) V2(110) V3(010) V4(011) V5(001) V6(101) SW = [0 0 0; 1 0 0; 1 1 0; 0 1 0; 0 1 1; 0 0 1; 1 0 1]; Sa = SW(v+1, 1); Sb = SW(v+1, 2); Sc = SW(v+1, 3); end逻辑说明:给定扇区 1、需要增磁增转矩时,选 V2(60° 方向),它相对当前磁链矢量超前,既拉长磁链又拉大转矩角,方向是对的;弱磁减转矩选 V5(240°),基本反向,磁链和转矩一起往下压。四行表覆盖四种非零组合,dte == 0时走零矢量(V0 或 V7),这就是「保持」的实现方式。
参数说明:TBL里存的是矢量编号而不是开关量,好处是改表直观,坏处是多一次映射。如果你的扇区定义是以 0° 为中心(即扇区 1 覆盖 [0°, 60°)),这张表的每一列都要整体右移一位。我见过最典型的翻车是扇区定义和开关表来自两份不同资料,拼在一起电机反转或者原地抖——现象是转速给定正转,实测转速在 0 附近来回。这种情况先别怀疑控制器参数,拿纸把 V1 到底对应 100 还是 001 画一遍,比调半小时参数管用。
3.4 传统链路的实测表现与瓶颈
把上面四段接起来,给定转速 1000 r/min、0.1 s 时突加 5 N·m 负载,能稳定运行,转速跌落后回到给定,说明主干逻辑没问题。但波形上的问题也很直观:稳态转矩在 4.2~5.8 N·m 之间高频抖动,峰峰值接近 0.6 N·m;相电流顶部有明显的锯齿;用thd_fft.m算出来 THD 在 20% 以上,而且开关频率不固定,频谱是一片散开的鼓包而不是集中在开关频率上。
这三条现象指向同一件事:滞环控制器本质上是一个带宽受限的 Bang-Bang,它只在误差撞到边界时才动作,动作时施加的是整个采样周期的大矢量,转矩过冲了再用反向量拉回来。开关频率由工况决定、不由你决定,滤波器设计就没法做,噪声和损耗都不好控。这就是改进版存在的理由。
4. 改进方案:SVM-DTC、占空比调制与磁链观测器
改进的落点就三个:把「整周期大矢量」改成「按需分配时间」,把「滞环」换成「连续调节」,把「纯积分」换成「带补偿的积分」。这套模型里三条都给了实现,可以单独开、也可以叠加。
4.1 为什么把滞环换成 PI + SVPWM
传统 DTC 的转矩误差是离散的 ±1,SVM-DTC 把这个误差送进 PI 调节器,输出的是连续的两相参考电压 uα*、uβ*,再由 SVPWM 合成。这样做的直接好处是开关频率被钉死在 10 kHz 上,电流频谱集中在开关频率及其边带,滤波器和 EMI 都好设计;间接好处是转矩脉动从「撞边界才动作」变成「按误差比例微调」,稳态抖动肉眼可见地小一圈。
代价是动态响应会软一点,因为 PI 有积分滞后。转速环 PI 输出转矩给定之后,转矩环 PI 的带宽要开得够高,一般取开关频率的 1/10 到 1/20,也就是 500~1000 Hz,再高就被采样和 PWM 延时拖住了。
顶层的改法很简单:把dtc_switching那一支换成两个 PI 加一个svpwm_calc,转矩反馈、磁链反馈原封不动。真正费时间的是调 PI 参数,我一般先把积分清零、只留比例,从小往大加,直到转矩阶跃响应出现一点点超调,再把积分补上。
4.2 SVPWM 作用时间计算
SVPWM 这段逻辑写错的概率很高,因为公式多、扇区多。我用的是「旋回扇区 I 再套公式」的写法,只有一套公式,六个扇区共用,出错面小。
function [Ta, Tb, Tc] = svpwm_calc(ua, ub, Udc, Ts) % 输入:ua/ub 参考电压 αβ 分量 (V),Udc 母线电压 (V),Ts 开关周期 (s) % 输出:Ta/Tb/Tc 三相上桥臂导通时间 (s),与三角载波比较得到门极信号 theta = atan2(ub, ua); if theta < 0 theta = theta + 2*pi; end sec = floor(theta / (pi/3)) + 1; % 1~6 ang = (sec - 1) * pi/3; % 旋转角,把参考矢量转回扇区 I ua_r = ua*cos(ang) + ub*sin(ang); ub_r = -ua*sin(ang) + ub*cos(ang); T2 = sqrt(3) * Ts * ub_r / Udc; % 后一个基本矢量的作用时间 T1 = 3 * Ts * ua_r / (2*Udc) - T2/2; % 前一个基本矢量的作用时间 if T1 + T2 > Ts % 过调制:等比压缩,防止波形畸变 k = Ts / (T1 + T2); T1 = T1 * k; T2 = T2 * k; end T0 = (Ts - T1 - T2) / 2; % 零矢量各占一半 switch sec % 七段式对称分配 case 1, Ta = T1+T2+T0; Tb = T2+T0; Tc = T0; case 2, Ta = T1+T0; Tb = T1+T2+T0; Tc = T0; case 3, Ta = T0; Tb = T1+T2+T0; Tc = T2+T0; case 4, Ta = T0; Tb = T1+T0; Tc = T1+T2+T0; case 5, Ta = T2+T0; Tb = T0; Tc = T1+T2+T0; case 6, Ta = T1+T2+T0; Tb = T0; Tc = T1+T0; end end逻辑说明:先把参考矢量按扇区号反向旋转(sec-1)*60°,落到扇区 I 的 0~60° 内,这样只需要一套 T1/T2 公式。扇区 I 的两个基本矢量是 V1(100) 和 V2(110),投影关系解出来就是上面两行。得到 T1、T2 之后,剩余时间Ts-T1-T2平均分给 V0(000) 和 V7(111),按七段式对称排布,每个开关周期每相只动作一次,开关损耗最低。
参数说明:Udc是母线电压,实际系统里会波动,做直流电压前馈时把它换成实测值;Ts必须和模型的离散采样时间一致,不一致会出现「计算出 8 kHz、实际跑 10 kHz」的错位。过调制那段等比压缩不能省,参考电压超过内切圆半径Udc/√3之后如果不处理,T1+T2 会大于 Ts,占空比直接溢出,波形削顶、转矩掉一块。
具体落地时,三相导通时间再除以Ts得到占空比,和三角载波比较,就得到六路门极信号;也可以直接把 Ta/Tb/Tc 送进PWM Generator (Three-phase)的现成模块。用代码实现的好处是过调制、死区补偿这些后面要加的东西有地方插。
4.3 占空比调制:不动滞环,只改一个周期的分配
如果不想大改结构,还有一条折中路线:滞环照旧负责选矢量方向,但不再让这个矢量占满整个 Ts,而是按转矩误差大小分配一个占空比 d,前 d·Ts 施加有效矢量,后 (1−d)·Ts 施加零矢量。
function [v_act, v_zero, duty] = duty_calc(sec, dte, Te_err, Te_base, kd) % sec 由开关表选出的有效矢量编号 1~6 % dte 转矩滞环方向 % Te_err 转矩误差 (N·m) % Te_base 基准转矩,一般取额定转矩 % kd 占空比系数,0.5~2 之间调 duty = kd * abs(Te_err) / Te_base; duty = min(max(duty, 0.1), 1.0); % 下限 10%,防止完全不施加有效矢量 v_act = sec; if dte > 0 v_zero = 0; % 增转矩时用 V0(000) 收尾 else v_zero = 7; % 减转矩时用 V7(111) 收尾 end end这段的逻辑是:误差小就少给有效矢量、多给零矢量,转矩自然就不过冲;误差大就满占空比冲一把,动态不损失。零矢量选 V0 还是 V7 有讲究——V0 让三相下管全开,V7 让上管全开,两者对共模电压和电流纹波的影响不同,习惯上按「换相次数最少」来选。
参数说明:kd是最值得调的旋钮,从 0.5 开始往上加,太小会导致转矩跟不上、稳态出现低频摆动,太大就退化成传统 DTC 了。Te_base一定要用额定转矩而不是实测峰值,否则占空比会一直贴在下限。
这条路的好处是不用调 PI,对已经调好传统 DTC 的模型是渐进式改造;缺点是开关频率仍然不固定,只是脉动小了,频谱还是散的。
4.4 带幅值补偿的磁链观测器
纯积分器的毛病在第 3 章埋下了:电流传感器的零点漂移、逆变器死区造成的电压重构误差,都是直流分量,积分之后变成一条斜坡,磁链圆中心越飘越远,最后转矩估算全错。通用的解法是给积分器加一条幅值反馈支路。
function [psi_a, psi_b] = flux_observer(ua, ub, ia, ib, Rs, psi_ref, Ts, Kc) % 带幅值补偿的定子磁链观测器 % Kc 补偿增益,一般 10~50,越大抑制漂移越快,但可能引入低频振荡 persistent pa pb if isempty(pa) pa = 0; pb = psi_ref; % 初值给到参考幅值,减小启动冲击 end % 纯积分项 pa = pa + Ts * (ua - Rs * ia); pb = pb + Ts * (ub - Rs * ib); % 幅值反馈补偿项:把磁链幅值往参考值上拉 amp = sqrt(pa^2 + pb^2) + 1e-6; err = psi_ref - amp; pa = pa + Kc * Ts * err * pa / amp; pb = pb + Kc * Ts * err * pb / amp; psi_a = pa; psi_b = pb; end逻辑说明:前两行是标准积分,问题在于误差会累积;后两行沿着磁链矢量的方向施加一个修正量,幅值偏低就往大拉,偏高就往小压,方向不变、只改长度。这样磁链圆的半径被钉在psi_ref附近,直流漂移被持续吃掉。
参数说明:Kc决定修正速度,取太小吃不掉漂移,取太大相当于给磁链加了个高通,低速时会看到幅值周期性摆动。我的经验值是 20 左右配 10 kHz 采样,转速低于 100 r/min 时漂移会重新变明显,这时候要么降Kc、要么换成滑模观测器或者高频注入。另外psi_ref传的是参考值,做弱磁时这个值随转速变化,接口要留出来,别写死。
更讲究的做法是用低通滤波器替代纯积分,再按运行频率做幅值和相位补偿,稳态精度更高,但需要知道电角速度,模型里要从转速乘极对数算出来。两种方案可以并联对比,用 Manual Switch 切换,方便看同一工况下的磁链圆轨迹。
5. 跑通与避坑:参数配置、求解器设置和 5 个高频翻车点
代码都对了,模型还是可能跑不起来、或者跑出来一片乱。Simulink 的坑大多不在算法,而在配置和数值。这一章是我自己踩过、也帮别人排查过的几类问题,按「现象 → 原因 → 解决」摆出来。
5.1 跑之前必须核对的参数与求解器
先把这几项过一遍,能省掉一半的调试时间。
| 项目 | 位置 | 建议值 |
|---|---|---|
| 求解器类型 | Model Settings → Solver | 定步长ode4(离散主导)或ode23tb |
| 固定步长 | Solver → Fixed-step size | 1e-6,别超过Ts/20 |
| 仿真时长 | Stop time | 0.5起步,稳态跑1 |
| 电机模块采样 | PMSM 模块 | 与Ts一致或更小 |
| 功率器件开关 | Universal Bridge | 理想开关,缓冲电路关掉 |
| 示波器数据 | Scope → History | 勾选Limit data points,别无限存 |
求解器设置是最容易被忽略的一环。开关周期 1e-4,控制周期也是 1e-4,如果固定步长设成 1e-5 甚至 1e-4,PWM 边沿就采不准,占空比量化误差直接体现成转矩抖动——你会以为是控制器不行,其实是数值分辨率不够。反过来,步长设成 1e-7、仿真跑 2 s,一步算下来几十分钟,效率低到没法迭代。我的习惯是 1e-6 配 0.5 s,先看动态够不够,做频谱分析再单独拉长稳态段。
5.2 波形验收:三个必看的观测点
跑完别只看转速曲线,它太宽容了,很多错误它都能稳。三个必看的信号是:
第一,定子磁链圆。把psi_a和psi_b送进 XY Graph,稳态应该是一个半径psi_ref的圆,圆心在原点。如果圆心偏移、或者半径随时间缓慢变化,去查观测器和电压重构,别去动转速环。
第二,电磁转矩。稳态峰峰值是多少,直接决定这套模型的水平。传统 DTC 一般在额定转矩的 10% 上下,SVM-DTC 能压到 3%~5%。用plot_steady.m里的max-min统计,比肉眼看准。
第三,相电流。看顶部有没有平顶、有没有过零畸变。平顶一般是过调制没处理或者电压不够;过零畸变多半是死区没补偿,仿真里如果用了理想开关就不会有,这也提醒你别把仿真结论直接搬到硬件上。
5.3 五个高频翻车点排查
现象一:转矩波形一团毛刺,峰峰值超过 1 N·m,转速却在给定值附近稳着。原因:这是传统滞环 DTC 的正常表现,不是 bug。滞环带宽给得宽(h_te接近额定转矩 20%)、采样周期大,加上开关频率不固定,转矩必然抖。 解决:先确认h_te是不是取到了 5%~10% 额定转矩,再把固定步长压到Ts/20以内;如果对脉动有硬要求,切到 SVM-DTC 支路,把转矩环 PI 带宽开到 500 Hz 以上。
现象二:磁链圆中心缓慢漂移,跑十几秒后转矩估算明显偏大或偏小,转速跟着往下掉。原因:纯积分器把电流零漂和逆变器死区造成的电压误差积了起来,这是结构性问题,调参调不好。 解决:换成 4.4 那个带幅值补偿的观测器,Kc从 10 试到 30;同时检查电压重构是不是用了上一拍的开关状态,用了当前拍会形成代数环,数值上也会引入误差。
现象三:一给转速阶跃,电流瞬间冲到几十安,模型直接发散。原因:转速环 PI 的输出没有限幅,转矩给定跑到几十 N·m,电流环(如果有)跟着饱和;或者转动惯量J填错了量级,比如把g·cm²当成了kg·m²。 解决:给转速环输出加 Saturation,上下限取 ±1.5~2 倍额定转矩;核对J的单位,1 kg·m² = 10000 kg·cm²,这个换算翻车率很高。另外积分项要做抗饱和,否则退饱和过程会拖很久。
现象四:模型报代数环错误,或者仿真速度突然变慢十倍。原因:观测器用当前拍的开关状态算电压、开关表又用当前拍的观测结果,形成一个闭环直馈;或者某个 MATLAB Function 里用了persistent但没给初值,每步都在重建。 解决:在电压重构
本文还有配套的精品资源,点击获取