简介:AN5327应用笔记聚焦汽车应用中的三相无传感器单分流电流感应PMSM矢量控制驱动,面向嵌入式电机控制开发者与汽车电子工程师,解决在MC9S12ZVM平台上以低成本硬件实现闭环速度控制、双向旋转及磁场与转矩独立控制的问题。正文从系统概念切入,依次讲解PMSM场定向控制原理、dq坐标系电机模型、单分流电阻相电流测量,以及基于扩展反电动势观测器的转子位置与速度估算,并给出MC9S12ZVML128关键模块、设备初始化和软件架构的实现思路。压缩包内含1个PDF文件,约2.58MB,目录与图表便于按章节查阅FOC算法、电流采样和调试工具相关内容,同时覆盖FreeMASTER界面与MCAT调校工具,可辅助理解参数整定、实时监控和性能优化流程。目前已有212人学习,适合参考NXP官方方案搭建PMSM驱动原型、理解无传感器控制与单分流采样的开发者。
1. 一块板子只留一颗采样电阻:这套方案把成本压到极限
拆开一套三相无传感器单分流电流采样的 PMSM 驱动,最刺眼的往往不是算法,而是 BOM:相电流采样只剩一颗 DC-Link 分流电阻,位置传感器直接消失,整机成本被压到只剩 MCU 加六个管子。这份 AN5327 讲的就是这么一套跑在 MC9S12ZVM 上的方案,用 FOC 做速度闭环、用单电阻重构三相电流、用扩展反电动势观测器估转子位置,再配 FreeMASTER 和 MCAT 两个上位机工具做在线调参。它适合正在做车用小功率泵、风机、执行器一类项目的人,也适合想把单电阻采样这条路走通、又不想在低速段翻车的工程师。嵌入式编程的难点从来不在写公式,而在于采样窗口、时序和观测器增益这些必须对齐的细节,下面按能复现的顺序一层层拆。
2. FOC 与 dq 轴模型:先把被控对象算明白再写代码
2.1 三相到 dq 的变换顺序与系数选择
矢量控制的骨架是两次坐标变换。第一次 Clarke 把三相静止坐标系压成两相静止 αβ,第二次 Park 把 αβ 旋到跟转子同步的 dq 上。AN5327 用的是等幅值变换,不是等功率变换,这一点在写代码时必须先定死,否则后面 PI 增益算出来的数值会差一个 √(3/2) 的系数,电流环看着能跑,实际带宽全错。
等幅值形式下,Clarke 写成 iα = ia、iβ = (ia + 2ib)/√3,反变换是 ia = iα、ib = (-iα + √3 iβ)/2、ic = -ia - ib。Park 变换是 id = iα cosθ + iβ sinθ、iq = -iα sinθ + iβ cosθ。很多实现图省事写成 iβ = (ib - ic)/√3,两种写法在纯三相无中线系统里等价,但前者在单相缺省时更稳,我一般按前者落地。
顺序上有两个细节容易埋雷。第一,Park 用的 θ 必须是电角度,机械角要乘极对数 pp,观测器输出、编码器输出、开环斜坡输出这三种角度源在切换时要把单位和零点统一,否则一切闭环就往反方向跑。第二,反 Park 输出的是 uα、uβ,后面接的是 SVPWM,SVPWM 内部还会自己算一次扇区,这时候如果 θ 的零点和 SVPWM 的扇区定义对不上,输出波形会出现固定 60° 的偏移,表现为电流畸变而不是直接失控。
离线阶段我习惯先用一段脚本把整条链路跑一遍,确认变换、反变换能还原,再往 C 里搬。下面这段把一组三相电流正着变过去、反着变回来:
import math def clarke_park(ia, ib, ic, theta_e): # 等幅值 Clarke:三相静止 -> 两相静止 alpha/beta i_alpha = ia i_beta = (ia + 2.0 * ib) / math.sqrt(3.0) # Park:两相静止 -> 同步旋转 dq c, s = math.cos(theta_e), math.sin(theta_e) i_d = i_alpha * c + i_beta * s i_q = -i_alpha * s + i_beta * c return i_alpha, i_beta, i_d, i_q def inv_park(i_d, i_q, theta_e): # 反 Park:dq -> alpha/beta c, s = math.cos(theta_e), math.sin(theta_e) i_alpha = i_d * c - i_q * s i_beta = i_d * s + i_q * c return i_alpha, i_beta def inv_clarke(i_alpha, i_beta): # 反 Clarke:alpha/beta -> 三相,利用 ia+ib+ic=0 ia = i_alpha ib = (-i_alpha + math.sqrt(3.0) * i_beta) / 2.0 ic = -ia - ib return ia, ib, ic theta = 0.7 ia, ib, ic = 2.0, -1.1, -0.9 a, b, d, q = clarke_park(ia, ib, ic, theta) a2, b2 = inv_park(d, q, theta) print(inv_clarke(a2, b2)) # 应还原为 (2.0, -1.1, -0.9)参数说明只有一条最要紧:theta 传的是电角度,弧度制,范围无所谓,三角函数本身能处理超出 ±π 的值,但观测器输出的角度通常被 atan2 限制在 (-π, π],跨零时如果做角度差分求速度,必须补 2π 的回绕判断,不然速度环会周期性出现一个巨大的尖峰。
2.2 dq 轴电压方程与交叉耦合前馈
dq 坐标系下的电压方程是整套控制的核心:ud = Rs·id + Ld·did/dt - ωe·Lq·iq,uq = Rs·iq + Lq·diq/dt + ωe·Ld·id + ωe·ψPM。把它改写成 ud' = ud + ωe·Lq·iq、uq' = uq - ωe·Ld·id - ωe·ψPM 之后,两个轴就退化成结构完全相同的 RL 一阶对象,区别只在 Ld 和 Lq 的数值,这也是为什么 d 轴和 q 轴可以用同一套 PI 调参流程,只是增益不同。
交叉耦合项必须补偿,而且是按当前实际电流算,不是按给定值算。按给定值算在稳态没差别,动态一加速就露馅:q 轴电流阶跃时,ωe·Lq·iq 这一项用给定值会在实际电流追上之前就超调,表现为 d 轴电流被拽出一个凹陷,母线电流跟着抖。我的习惯是用测量值做前馈,代价是引入一点噪声,加一个截止频率在电流环带宽 3 到 5 倍的一阶低通就够。
ψPM 那一段是反电动势前馈,它的作用是让 PI 在高速段不用单独扛掉整个反电动势,否则转速一高,积分项被顶到饱和,退出饱和需要好几毫秒,那段时间电流完全失控。低速段这一项数值很小,补不补差别不大,但代码里最好统一开着,避免高速才出问题、还查不到原因。
参数误差对这套前馈的影响需要心里有数。Rs 随温度漂 30% 到 50% 是常态,Ld、Lq 在饱和区能掉 20% 以上,ψPM 随温度下降。前馈项用标称值算,误差就变成了电流环的一个扰动,由积分项吸收,所以稳态电流精度一般没问题,受影响的是动态。要做高温工况,Rs 最好带温度补偿,或者干脆把电流环带宽留够余量。
2.3 极点配置算 PI 增益:Kp、Ki 和离散化
AN5327 给的整定方法是极点配置法。闭环被控对象是 1/(Ls + R),配一个标准二阶系统,阻尼比 ξ、自然频率 ω0,推出来的比例和积分增益是 Kp = 2ξω0L - R、Ki = ω0²L。和常见的「零极点对消」写法相比,这个形式把 R 显式扣掉了,低速大电流时电阻压降占比高,扣不扣这一项差别能到 10% 以上。
带宽怎么选是新手最容易翻车的地方。ω0 取得太大,离散化误差和采样延迟会把相位裕度吃掉,实际响应出现振铃甚至发散;取得太小,抗扰动能力差,负载一跳转速就掉。经验约束是 ω0 ≤ 2π·fs/10,fs 是电流环执行频率。16 kHz 电流环对应带宽上限 1.6 kHz,工程上一般取 600 到 1000 Hz,兼顾动态和稳定。
下面这段按一台常见的小功率车用泵电机算一遍,参数只是示例,换成自己电机的铭牌值重跑即可:
import math Rs = 0.20 # 定子相电阻,欧姆 Ld = 0.15e-3 # d 轴电感,亨利 Lq = 0.25e-3 # q 轴电感,亨利 psi = 0.008 # 永磁体磁链,韦伯 fs = 16000.0 # 电流环频率,Hz fc = 800.0 # 目标电流环带宽,Hz xi = 0.707 # 阻尼比 w0 = 2.0 * math.pi * fc assert fc <= fs / 10.0, "带宽超过采样频率的 1/10,离散化会失稳" for name, L in (("d", Ld), ("q", Lq)): Kp = 2.0 * xi * w0 * L - Rs Ki = w0 * w0 * L # 后向欧拉离散:积分项按 Ki*Ts 累加 Ts = 1.0 / fs print(f"{name} 轴: Kp={Kp:.4f} V/A, Ki={Ki:.2f} V/(A*s), Ki_d={Ki*Ts:.5f}") print(f"反电动势常数 Ke = {psi*60/(2*math.pi):.5f} V/(rad/s) 折算")代码里断言那句不是摆设,我见过把 fc 直接设成 2 kHz、fs 还是 10 kHz 的配置,空载能转,一加负载电流环就开始 5 kHz 左右的等幅振荡,示波器上看母线电流是一条粗带子,很多人第一反应是采样噪声,其实是相位裕度已经负了。
离散化统一用后向欧拉,积分项写成 ki_d * err 累加,不要用双线性变换再自己推一遍,容易在系数上多一个 2。另外积分器一定要做抗饱和:输出限幅按当前母线电压和 SVPWM 能输出的最大幅值算,不是固定一个常数,母线跌落时固定限幅会让积分器持续饱和,退出时反向超调。
MCAT 工具里电流环那一页填的就是这两个增益加一个带宽,工具会帮你算,但知道背后怎么来的,出问题时才改得动。
3. 单分流电流重构:一个采样窗口决定成败
3.1 八个开关矢量与母线电流的对应关系
单电阻采样的物理基础很直接:三相逆变器任一时刻只有一个确定的开关组合,直流母线电流等于某一相电流(或者它的相反数),取决于当前是哪个非零矢量。六个非零矢量各对应一相,两个零矢量 000 和 111 下母线电流为零,采不到任何信息。对应关系必须背下来,代码里也是按这张表查的:
| 矢量 | 开关状态 (A/B/C) | 母线电流 | 可测相 |
|---|---|---|---|
| V1 | 100 | +ia | A |
| V2 | 110 | -ic | C |
| V3 | 010 | +ib | B |
| V4 | 011 | -ia | A |
| V5 | 001 | +ic | C |
| V6 | 101 | -ib | B |
| V0 | 000 | 0 | 无 |
| V7 | 111 | 0 | 无 |
有了这张表,一个 PWM 周期里只要抓到两个不同矢量的母线电流,就能用 ia + ib + ic = 0 解出第三相。SVPWM 在一个周期内本来就是两个相邻非零矢量加零矢量拼出来的,所以理论上天然存在两次采样机会。
问题出在「足够时间」四个字上。中心对齐 PWM 的波形是对称的,两个非零矢量分别位于周期的两侧,各占 t1/2 和 t2/2。当参考电压矢量靠近扇区边界时,其中一个占空比趋近于 0 或 1,对应的矢量作用时间被压缩到几百纳秒,运放还没建立、ADC 采样保持电容还没充完,采到的就是垃圾值。AN5327 里把这叫电流信息「消失」,波形上表现为相电流在过零点附近出现平台或尖刺。
3.2 采样窗口预算:死区、建立时间、ADC 采样
最小可测窗口不是一个拍脑袋的数,它由四段串起来:开关管关断延迟加死区时间、母线电流振铃衰减时间、运放和 RC 滤波的建立时间、ADC 采样保持时间。逐项估一下,20 kHz 的 MOS 管桥臂死区常在 0.5 到 1 μs,振铃 0.5 μs 左右,运放建立到 0.1% 大约 1 到 2 μs,12 位 ADC 采样保持约 1 μs,加起来 3 到 5 μs 是常态。
拿这个数去对 PWM 周期。16 kHz 对应 62.5 μs,一个周期里两个非零矢量总时间等于调制比乘以周期,最坏情况出现在扇区边界,其中一个几乎为零。也就是说在每一圈电周期里,总有那么几个角度区间是采不到的,占空比越低区间越宽。低速小占空比时这个问题会被放大:调制比 10% 时,两个矢量总时间只有 6 μs,还不够一次建立。
我一般先算清楚自己板子的窗口预算,再决定策略。下面这段在给定占空比和扇区的前提下,判断当前周期能不能正常采样:
/* 三相占空比已算好,duty[3] 范围 0.0 ~ 1.0,中心对齐 PWM */ #define T_PWM_US 62.5f /* 16 kHz */ #define T_MIN_US 4.0f /* 实测最小可测窗口 */ typedef enum { SAMPLE_OK = 0, SAMPLE_SHIFT_NEEDED } sample_state_t; /* 返回需要移相的量(单位:PWM 计数比例的微秒),0 表示不用动 */ float check_sample_window(const float duty[3]) { float dmax = duty[0], dmin = duty[0]; for (int i = 1; i < 3; i++) { if (duty[i] > dmax) dmax = duty[i]; if (duty[i] < dmin) dmin = duty[i]; } /* 中间矢量持续时间为 (dmid - dmin),两侧各一半 */ float dmid = duty[0] + duty[1] + duty[2] - dmax - dmin; float t_mid_us = (dmid - dmin) * T_PWM_US; /* 中间矢量总时间 */ float t_min_us = dmin * T_PWM_US; /* 最小矢量总时间 */ /* 两个矢量都要能采,取较差的那个 */ float worst = (t_mid_us < t_min_us) ? t_mid_us : t_min_us; if (worst >= T_MIN_US) { return 0.0f; /* 窗口够,正常采 */ } /* 缺口时间,稍后由移相逻辑补上,留 20% 余量 */ return (T_MIN_US - worst) * 1.2f; }这段代码只做判断,不做动作,是故意的。判断和补偿分开写,调试时可以只观察返回值不执行移相,用 FreeMASTER 的 recorder 把返回值和一个电周期内的角度一起录下来,就能直接看到盲区分布在哪些角度区间、宽度多少。这一步做完再谈补偿,比一上来就改 PWM 靠谱得多。
3.3 扇区边界盲区的两种处理:移相与最小窗口强制
补偿有两条路,选哪条取决于应用对电流纹波和共模噪声的容忍度。
第一条是移相法,也就是常说的 PWM 相移。当检测到某个矢量窗口不足时,把三相占空比的中心平移一个量,人为把两个边沿拉开,让短的那个矢量至少撑到 T_MIN。平移量一般限制在半个周期的百分之几以内,平移过多会明显加大电流纹波,也会让共模电压跳变,对 EMC 不友好。优点是电流波形连续、不引入额外谐波;缺点是实现复杂,移相量与扇区、当前占空比都相关,写错了会出现周期性转矩脉动。
第二条是最小窗口强制加法。窗口不足时直接把这个矢量的作用时间钳到 T_MIN,用剩下的时间补偿另一个矢量,保证伏秒积不变。代价是输出电压矢量方向有偏差,低速时表现为轻微的角度误差,但实现简单、行为可预测。AN5327 这套参考设计里两种思路都有体现,实际项目里我倾向于在调制比高于 30% 时用移相,低于 30% 时切到最小窗口强制,再低就直接限制最低调制比,靠提高母线电压或者降低载频把窗口撑出来。
还有一条容易被忽略:采样时刻的位置。中心对齐 PWM 下,采样点要放在计数器过零或过峰的那一侧,且必须落在矢量稳定段的中间,不能贴着边沿。差个几百纳秒,采到的就是开关瞬间的振铃。这条在代码里体现为 ADC 触发时刻的偏移寄存器,改起来就一个数,但它决定了整个电流重构的信噪比。
4. 无传感器观测器与启动:角度从哪来
4.1 扩展反电动势观测器的状态方程与增益
没有位置传感器,角度只能从反电动势里抠。AN5327 用的是扩展反电动势观测器,把反电动势当成额外状态,跟电流一起估。αβ 静止坐标系下,电机方程是 di/dt = (-Rs/L)·i + (1/L)(u - e),反电动势满足 de/dt = ωe·J·e,其中 J 是 90° 旋转矩阵。观测器在电流方程上加一个基于电流误差的修正项,反电动势方程上也加一个,两个增益由极点配置给出来。
离散化用后向欧拉,写成 C 就是几行乘加,跑在电流环中断里完全来得及:
/* alpha/beta 扩展反电动势观测器,后向欧拉离散,Ts 为电流环周期 */ typedef struct { float i_hat_a, i_hat_b; /* 估计电流 */ float e_hat_a, e_hat_b; /* 估计反电动势 */ float k1; /* 电流误差增益,约 2*w0 */ float k2; /* 反电动势误差增益,约 w0*w0*L */ } bemf_obs_t; void bemf_observer_step(bemf_obs_t *o, float u_a, float u_b, float i_a, float i_b, float we, float Ts, float Rs, float L) { /* 电流误差 */ float err_a = i_a - o->i_hat_a; float err_b = i_b - o->i_hat_b; /* 反电动势估计更新:交叉耦合 + 误差修正 */ float de_a = -we * o->e_hat_b + o->k2 * err_a; float de_b = we * o->e_hat_a + o->k2 * err_b; o->e_hat_a += de_a * Ts; o->e_hat_b += de_b * Ts; /* 电流估计更新:电压 - 反电动势 - 电阻压降 + 误差修正 */ float di_a = (u_a - o->e_hat_a - Rs * o->i_hat_a) / L + o->k1 * err_a; float di_b = (u_b - o->e_hat_b - Rs * o->i_hat_b) / L + o->k1 * err_b; o->i_hat_a += di_a * Ts; o->i_hat_b += di_b * Ts; }k1、k2 的取值按 ω0 配,但这里 ω0 是观测器极点,不是电流环带宽。经验上观测器收敛速度要比电流环慢 3 到 5 倍,太快会把采样噪声放大成角度抖动,太慢则在加速时角度滞后。另一个必须处理的是 we 这一项的符号和范围:正反转时符号要翻转,低速时 we 接近零,观测器退化成两个独立的一阶系统,此时它本来就估不准,这属于物理限制,不是参数没调好。
参数 L 用哪个值也是个坑。dq 轴电感差的电机(凸极率高的)在 αβ 系下严格来说没有单一 L,只能用平均值近似,这台参考设计里的电机凸极率不高,用 (Ld+Lq)/2 就够,凸极率超过 1.5 的得换方案。
4.2 角度与速度提取:atan2 与 PLL 的取舍
反电动势估计出来之后,角度直接 atan2 就行:θ = atan2(-eα, eβ),前提是 eα、eβ 满足 eα = -ωe·ψPM·sinθ、eβ = ωe·ψPM·cosθ 这个定义。符号写反了最典型的症状是电机能转但方向反、或者起动就堵转,先核对符号再怀疑别的。
atan2 出来的是 (-π, π] 的锯齿波,做速度反馈不能直接差分。两种做法:一是差分后做回绕补偿再低通,二是用锁相环把角度和速度一起锁出来。我一般用锁相环,原因是它对噪声更友好,而且天然输出连续的速度,不用再单独处理回绕。锁相环的结构是角度误差 e = sin(θ_obs - θ_est),乘一个增益累加成速度,再积分成角度,环路带宽取电流环的 1/10 到 1/20。
低速的问题是根本性的。反电动势幅值和转速成正比,1% 额定转速下 e 只有几毫伏,淹没在运放失调和 ADC 噪声里,再怎么调增益也出不来角度。所以低速段必须靠开环撑过去,这是所有无感方案共同的短板,宣称能零速跑的无感 FOC,要么是靠高频注入,要么是在低速段偷偷用了别的信息源,跟纯反电动势观测器不是一回事。
4.3 启动三段式:对齐、开环加速、切闭环
启动流程必须严格分三段,中间任何一段切换时机不对都会失败。
第一段是对齐。给 d 轴一个恒定电流(通常额定电流的 30% 到 50%),θ 固定为 0,让转子被定子磁场吸到确定位置。时间要够,一般 200 到 500 ms,转子摆动能看出来的就说明还没停稳。电流给太大会发热,给太小对不齐,尤其是带负载启动的场合。
第二段是开环加速。θ 按设定的加速度斜坡往上走,同时给 q 轴电流产生转矩。斜坡太陡会失步(转子跟不上磁场),太缓则启动时间长、发热多。这个加速度值跟负载惯量强相关,第一次调先给个保守值,跑通了再往上加。
第三段是切换。当开环转速超过观测器可信的下限(经验值是额定转速的 5% 到 10%)之后,把角度源从开环斜坡切到观测器。切换的瞬间要做两件事:把观测器的角度预置到当前开环角度,避免跳变;把速度环的积分器清掉或者限幅,避免切换瞬间速度给定突变。AN5327 里用的是「对齐启动」策略,没有做高频注入,所以低速下限是真实存在的,别指望它零速闭环。
切早了观测器还没收敛,表现为转速剧烈抖动然后失步;切晚了开环电流大、效率低、发热明显。我的做法是在 recorder 里同时录开环角度和观测器角度,先不切,纯开环跑,看两条曲线在什么转速下开始贴合,那个转速就是这台电机实际的可切换点,比按额定值估准得多。
5. 避坑与排查:五个真实会翻车的现场
5.1 电流波形撕裂与低速噪声
现象:电机能转,但示波器上看相电流在过零点附近有明显平台,母线电流纹波大,用 FreeMASTER 录重构出来的三相电流,波形在特定角度区间出现尖刺,转速越低越明显。
原因:单电阻采样的盲区在低调制比下变宽。当参考矢量靠近扇区边界,两个非零矢量中有一个的作用时间小于最小可测窗口,采到的是运放未建立的值,重构出来的那相电流完全错误,而另外两相是对的,三相不满足 ia+ib+ic=0,误差被带进 Clarke 变换。
解决:先把最小窗口时间和实际采样点位置量出来,用示波器同时看 PWM 驱动信号和 ADC 触发脉冲,确认采样点落在矢量稳定段内。然后按第 3 章的判断逻辑把盲区角度录下来,实施移相或最小窗口强制。实在调不动,退一步降低载频到 10 kHz,周期拉长 60%,窗口自然就够了,代价是电流纹波变大、开关损耗上升。还有一招是提高母线电压、降低调制比需求,但会牵动整个硬件设计。
5.2 切闭环就反转或失步
现象:开环加速正常,一切闭环电机立刻抖动、反转,或者直接停转报故障,复位再试还是同样位置失败。
原因:三种可能混在一起。观测器的角度定义和电流环的 dq 定义符号不一致,atan2 参数顺序写反;观测器增益太大,把采样噪声放大成角度抖动;切换时观测器角度没有预置,直接跳了一个相位,电流环瞬间输出错误矢量。
解决:先断掉切换逻辑,纯开环跑,用 recorder 同时录开环 θ 和观测器 θ,看两条曲线的斜率和零点对不对。零点差一个固定值就改 atan2 的参数顺序或者加偏置,斜率不对就是极对数或者符号写错。两条曲线在低速段抖动剧烈,先把观测器 k1、k2 各降一半再看。预置这一步最容易漏,切换函数里加一句直接把 θ_est 赋成 θ_open_loop,问题能解决一大半。
5.3 电流零漂导致稳态转矩脉动
现象:空载电流波形看着还行,带载之后 q 轴电流有稳态误差,转速稳定但电机有周期性的嗡嗡声,用电流钳看三相幅值不完全对称。
原因:单电阻方案对 ADC 零点和运放失调极其敏感。三相电流都是从同一路 ADC 上分时采出来的,任何一点偏置误差会同时加到两相上,第三相靠 ia+ib+ic=0 算出来,误差被直接继承。温漂之后更明显。
解决:上电做一次零点标定,在桥臂全关、母线不带电的状态下采一批 ADC 值取平均,存成 offset,运行中所有采样减去它。有些方案会在每个 PWM 周期的零矢量段再采一次零点做实时跟踪,效果更好但要注意零矢量持续时间也得够。标定之后如果还有残余误差,检查采样电阻的精度和运放电路的共模抑制,1% 精度的电阻配 12 位 ADC,理论误差就有 1%,靠软件补不回来。
5.4 死区引起的角度抖动
现象:低速轻载时转速不稳,观测器估计的角度在电流过零点附近有明显抖动,电机有轻微的咯咯声。
原因:死区导致实际输出电压和给定电压有偏差,偏差方向跟电流方向有关,在电流过零时符号翻转,形成一个周期性扰动。这个扰动直接进观测器的电压输入,被积分成角度误差。
解决:做死区补偿,按相电流方向给占空比加一个补偿量,符号跟电流方向一致,幅值等于死区时间除以 PWM 周期。补偿量不要给死区理论值的 100%,给 80% 到 90%,宁可欠补也不要过补,过补会在过零点造成双倍扰动。补偿之后再给观测器的输入电压加一个一阶低通,截止频率放在电流环带宽的 5 倍左右,滤掉开关噪声但保留基波。
5.5 上位机连上后行为异常
现象:不连 FreeMASTER 一切正常,连上之后电机偶尔抽一下,或者 MCAT 里改了参数下发,电机直接失控。
原因:通信占用中断带宽。FreeMASTER 走串口或者 CAN,它的接收中断优先级如果高于电流环,长帧传输时会挤掉电流环的执行,采样节拍被打乱,单电阻方案对时序特别敏感,节拍一乱重构就错。另一种情况是参数下发时电流环还在跑,两套参数同时生效,增益瞬间不匹配。
解决:把电流环中断优先级设到最高,通信中断只做数据搬运,解析和参数生效放到慢环里做。参数下发必须走停机状态,MCAT 里改完先停电机再写,写完之后重新初始化一遍 PI 积分器。recorder 的采样率也要控制,别在一个慢环里塞几十个通道,超过通信带宽就会丢帧,看起来像波形错了,其实是没采到。
6. 用阶跃响应验证电流环与观测器:我每次上电都会走的流程
参数算完、代码跑通,不代表这套系统在边界上没问题。我习惯在整机上做两组验证,做完才敢往下调速度环。
第一组是电流环阶跃。让电机在空载、固定母线电压下堵转或者低速稳定运行,通过 MCAT 给 iq 一个从 0 到 30% 额定的阶跃,用 recorder 以至少 10 倍于电流环的频率录 iq 实际值。判据有三条:上升时间对应带宽,800 Hz 带宽对应大约 0.5 ms 到 0.6 ms 到 90%;超调量控制在 10% 以内;调节时间之后不能有持续的高频振荡。如果超调大,先降 ω0;如果稳态有偏差,查积分限幅和 ADC 零漂;如果响应里叠着明显的高频纹波,那不是环路问题,回去查采样窗口。
第二组是观测器收敛性。开环拖动电机,从 2% 额定转速慢慢升到 20%,同时录开环角度和观测器角度,看两条曲线的相位差。相位差随转速单调减小并趋于一个小的常数,说明观测器工作正常;如果相位差在某个转速附近突然跳变,说明那一带的电压或电流采样有问题;如果在低速段角度抖动幅度超过几度电角度,那就老老实实把切换转速往上提,别硬压。
这两个测试做完,转速环的 PI 才有意义,否则速度环调出来的参数全是在补偿底层的缺陷,换个工况就崩。MCAT 的速度环那一页我一般只改带宽和限幅,输出限幅要跟电流环的最大能力对齐,别让速度环积分到电流环给不出的值上去。
还有个小习惯:每次改完参数,都先把母线电压拉到最低工作值和最高工作值各跑一遍,再做一次突加突卸负载。单电阻方案对母线电压特别敏感,电压低的时候调制比高、采样窗口反而够,电压高的时候调制比低、盲区变宽,问题往往在高母线电压轻载那一侧才暴露。这套流程走下来,一台新电机从零到稳定运行,通常两三个小时能跑完。
从那以后,我每次拿到一套新的单电阻方案,不管文档写得多完整,都强制先把最小采样窗口量和观测器切换转速这两个数实测出来再动参数,这两个数定不下来,后面调什么都是玄学。希望帮到你。
本文还有配套的精品资源,点击获取