电机驱动开发学习16. DQ双轴电流环闭环控制
- [一、DQ 双轴电流环是什么](#一、DQ 双轴电流环是什么)
-
- [1.1 电流环只选用PI调节器的原因 + 公式详解](#1.1 电流环只选用PI调节器的原因 + 公式详解)
- [1.2 电压矢量限幅公式(模长等比例限幅)](#1.2 电压矢量限幅公式(模长等比例限幅))
- [1.3 本章硬件执行方式说明](#1.3 本章硬件执行方式说明)
- [1.4 传感器与执行端的现实限制](#1.4 传感器与执行端的现实限制)
- 二、实验简介
-
- [2.1 本章目标](#2.1 本章目标)
- [2.2 硬件平台](#2.2 硬件平台)
- 三、程序设计
-
- [3.1 目录结构](#3.1 目录结构)
- [3.2 数据流](#3.2 数据流)
- [3.3 核心代码与公式配套讲解](#3.3 核心代码与公式配套讲解)
-
- [3.3.1 PI结构体 + 带积分限幅的位置式PI实现](#3.3.1 PI结构体 + 带积分限幅的位置式PI实现)
- [3.3.2 DQ电流环主体函数](#3.3.2 DQ电流环主体函数)
- [3.3.3 霍尔6扇区电角度计算公式](#3.3.3 霍尔6扇区电角度计算公式)
- [3.4 PI参数整定初值(量纲:V/A)](#3.4 PI参数整定初值(量纲:V/A))
- [四、FreeMASTER 与串口](#四、FreeMASTER 与串口)
-
- [4.1 FreeMASTER观测变量](#4.1 FreeMASTER观测变量)
- [4.2 VOFA+配置](#4.2 VOFA+配置)
- [4.3 串口调试命令](#4.3 串口调试命令)
- 五、主程序流程
-
- [5.1 初始化顺序](#5.1 初始化顺序)
- [5.2 主循环](#5.2 主循环)
- 六、调试步骤与波形整定
-
- [6.1 分步实验流程](#6.1 分步实验流程)
- [6.2 波形现象深度解读(对应角度缺陷)](#6.2 波形现象深度解读(对应角度缺陷))
- [6.3 故障现象与对策](#6.3 故障现象与对策)
- [6.4 两代电流环横向对比](#6.4 两代电流环横向对比)
- 七、本章小结

一、DQ 双轴电流环是什么
lesson15 已通过 Clark / Park 变换 把三相交流电流解耦为旋转坐标系下的直流分量 I d I_d Id、 I q I_q Iq。本章在此基础上,给d轴、q轴分别配置独立的PI调节器,构成FOC控制系统最内层闭环------DQ双轴电流环,也叫转矩内环。
| 轴 | 物理含义(SPM表贴式永磁同步电机) | 本章控制目标 |
|---|---|---|
| d轴(直轴) | 电机励磁分量,影响磁场强弱 | I d _ r e f = 0 I_{d\_ref}=0 Id_ref=0,弱磁模式除外,防止额外铜耗发热与永磁体退磁 |
| q轴(交轴) | 电磁转矩分量,直接决定输出力矩 | I q _ r e f I_{q\_ref} Iq_ref 由上层环给定,转矩和Iq成正比 |
控制链路:

与 lesson13 的本质区别 :
lesson13 直接采集三相相电流做单环PID;本章反馈是经过Park解耦后的直流Id、Iq,调节器输出为旋转坐标系电压 V d 、 V q V_d、V_q Vd、Vq,再经过反Park变换生成两相静止坐标系电压矢量,最终转换成PWM。这是工业标准FOC电流内环架构。
1.1 电流环只选用PI调节器的原因 + 公式详解
为什么不用PID?
- 相电流ADC采样包含大量高频开关噪声,微分项D会放大毛刺,造成电压输出频繁抖动,逆变器震荡发热。
- 电流环的核心需求:快速响应 + 消除稳态静差。比例项P保证动态响应速度,积分项I可以彻底消除稳态误差,PI已经完全够用。
离散位置式PI公式(带抗积分饱和)
误差定义:
e ( k ) = I r e f ( k ) − I a c t ( k ) e(k) = I_{ref}(k) - I_{act}(k) e(k)=Iref(k)−Iact(k)
- I r e f ( k ) I_{ref}(k) Iref(k):第k次采样的电流给定值
- I a c t ( k ) I_{act}(k) Iact(k):第k次采样的实际反馈电流
位置式PI输出表达式:
V ( k ) = K p ⋅ e ( k ) + K i ⋅ ∑ n = 0 k e ( n ) V(k) = K_p \cdot e(k) + K_i \cdot \sum_{n=0}^{k} e(n) V(k)=Kp⋅e(k)+Ki⋅n=0∑ke(n)
各项含义拆解:
- K p ⋅ e ( k ) K_p \cdot e(k) Kp⋅e(k):比例项。偏差越大,输出电压越大,决定响应快慢;P越大响应越快,过大则超调、震荡。
- K i ⋅ ∑ e ( n ) K_i \cdot \sum e(n) Ki⋅∑e(n):积分项。对历史误差持续累加,只要存在静差,积分就会不断累积输出,最终把稳态误差拉到0。
- V ( k ) V(k) V(k):本次PI输出电压 V d V_d Vd 或者 V q V_q Vq。
离散系数关系:
K i = K p ⋅ T s T i K_i = K_p \cdot \frac{T_s}{T_i} Ki=Kp⋅TiTs
T s T_s Ts为控制周期, T i T_i Ti为积分时间常数。代码里直接使用合并后的 K i K_i Ki,不需要再拆分时间。
积分饱和问题说明
当电机堵转、电流达到上限时,误差会长时间保持正值,积分值会无限制持续累加。当退出饱和工况后,积分值过大,会造成电压长时间居高不下,电流出现巨大超调。
另外,直流母线电压 V b u s V_{bus} Vbus 是电源极限。对于三相逆变器能够合成的最大基波电压矢量幅值:
V m a x = V b u s 3 V_{max}=\frac{V_{bus}}{\sqrt{3}} Vmax=3 Vbus
PI调节器输出的 V d 、 V q V_d、V_q Vd、Vq 合成矢量一旦超过这个值,硬件根本输出不出来,电压指令会被强行削顶。
当电压迟迟降不下来 ,会引起电流严重超调、剧烈震荡、电机尖叫,技术通过电压限幅解决这几个问题。
1.2 电压矢量限幅公式(模长等比例限幅)
母线直流电压为 V b u s V_{bus} Vbus,两相静止坐标系下最大合成电压矢量幅值为:
V m a x = V b u s 3 V_{max} = \frac{V_{bus}}{\sqrt{3}} Vmax=3 Vbus
旋转坐标系下 V d 、 V q V_d、V_q Vd、Vq合成矢量模长:
∣ V ∣ = V d 2 + V q 2 |V| = \sqrt{V_d^2 + V_q^2} ∣V∣=Vd2+Vq2
限幅逻辑:
- 如果 ∣ V ∣ ≤ V m a x |V| \le V_{max} ∣V∣≤Vmax:电压保持原值,不需要处理;
- 如果 ∣ V ∣ > V m a x |V| > V_{max} ∣V∣>Vmax:按相同比例缩放 V d 、 V q V_d、V_q Vd、Vq,保证矢量方向不变,只压缩幅值。
缩放系数:
k s c a l e = V m a x V d 2 + V q 2 k_{scale} = \frac{V_{max}}{\sqrt{V_d^2 + V_q^2}} kscale=Vd2+Vq2 Vmax
限幅后电压:
{ V d ′ = V d ⋅ k s c a l e V q ′ = V q ⋅ k s c a l e \begin{cases} V_d' = V_d \cdot k_{scale} \\ V_q' = V_q \cdot k_{scale} \end{cases} {Vd′=Vd⋅kscaleVq′=Vq⋅kscale
优点:只压缩电压幅值,不改变电压矢量角度,保证磁场定向角度不变,不会破坏FOC定向。
1.3 本章硬件执行方式说明
完整FOC依靠SVPWM将 V α 、 V β V_\alpha、V_\beta Vα、Vβ调制为三相正弦PWM(lesson18内容)。在SVPWM代码完成前,本章采用过渡验证方案:
- 完整执行链路:三相电流 → Clark → Park → Id/Iq → 双PI → Vd/Vq → 电压限幅 → 反Park → V α 、 V β V_\alpha、V_\beta Vα、Vβ;
- 只提取电压矢量模长 ∣ V ∣ = V α 2 + V β 2 |V|=\sqrt{V_\alpha^2+V_\beta^2} ∣V∣=Vα2+Vβ2 ,线性映射为六步换相的PWM占空比;
- 可以在现有BLDC驱动板上完整验证坐标变换、双PI闭环逻辑,提前整定Id/Iq调节器参数。
1.4 传感器与执行端的现实限制
Park变换对电角度 θ \theta θ极度敏感。只有转子电角度连续平滑变化,交流电流才能被完全解耦成平直直流Id、Iq,PI才能稳定锁电流。
| 环节 | 理想FOC条件 | 本章野火BLDC霍尔方案 |
|---|---|---|
| 角度传感器 | 增量编码器、旋转变压器,电角度连续输出 | 仅3路霍尔,只划分6个扇区,每扇区60°电角度, θ \theta θ阶梯式跳变 |
| 角度精度 | 电角度误差≤1° | 即便取扇区中心值,仍然存在±30°的角度误差 |
| 电压执行波形 | SVPWM正弦电压矢量 | 六步方波导通,两相持续通电,第三相悬空 |
| 电流环波形 | Id≈0,Iq平直跟随给定,纹波极小 | Id、Iq出现大幅度周期性交流纹波,无法稳定恒流 |
关键结论:
软件上Clark/Park、双PI、反Park整套数学链路完全正确;Scope观测到Id/Iq大幅度来回摆动,根源是霍尔角度分辨率过低+方波驱动不匹配FOC矢量控制。
后续章节逐层补齐短板:
- 引入SVPWM正弦调制,让逆变器输出匹配电压矢量;
- 霍尔角度细分/增加编码器,提升 θ \theta θ分辨率,Id/Iq纹波会大幅减小。
二、实验简介
2.1 本章目标
在lesson13工程基础上升级为DQ双轴电流内环:
- 复用lesson15坐标变换模块
bsp_foc.c; - 编写带抗饱和的位置式PI,d轴、q轴相互独立;
- 给定设置: I d r e f = 0 Id_{ref}=0 Idref=0, I q r e f Iq_{ref} Iqref默认1500mA;
- FreeMASTER观测Id、Iq、Vd、Vq、电角度θ;VOFA+监视Iq给定、反馈、PWM占空比;
- 保留电流零偏校准、过流保护、堵转保护代码。
2.2 硬件平台
野火骄阳STM32F407 + BLDC无刷驱动板 + 霍尔式永磁无刷电机,使用2号电机排线接口。
三、程序设计
3.1 目录结构
User/
├── foc/
│ └── bsp_foc.c/h # Clark / Park / InvPark / 电压限幅 / 电角度计算
├── pid/
│ ├── bsp_pi.c/h # 抗饱和位置式PI(电流环专用)
│ └── bsp_pid_app.c/h # DQ电流环业务逻辑 + 串口交互 + FreeMASTER变量
├── freemaster/
│ └── bsp_fm_vars.h # g_fm_id_actual、g_fm_pi_iq 观测变量
└── main.c
3.2 数据流
#mermaid-svg-P9qqq79tYP2uYuwT{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-P9qqq79tYP2uYuwT .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-P9qqq79tYP2uYuwT .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-P9qqq79tYP2uYuwT .error-icon{fill:#552222;}#mermaid-svg-P9qqq79tYP2uYuwT .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-P9qqq79tYP2uYuwT .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-P9qqq79tYP2uYuwT .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-P9qqq79tYP2uYuwT .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-P9qqq79tYP2uYuwT .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-P9qqq79tYP2uYuwT .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-P9qqq79tYP2uYuwT .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-P9qqq79tYP2uYuwT .marker{fill:#333333;stroke:#333333;}#mermaid-svg-P9qqq79tYP2uYuwT .marker.cross{stroke:#333333;}#mermaid-svg-P9qqq79tYP2uYuwT svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-P9qqq79tYP2uYuwT p{margin:0;}#mermaid-svg-P9qqq79tYP2uYuwT .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-P9qqq79tYP2uYuwT .cluster-label text{fill:#333;}#mermaid-svg-P9qqq79tYP2uYuwT .cluster-label span{color:#333;}#mermaid-svg-P9qqq79tYP2uYuwT .cluster-label span p{background-color:transparent;}#mermaid-svg-P9qqq79tYP2uYuwT .label text,#mermaid-svg-P9qqq79tYP2uYuwT span{fill:#333;color:#333;}#mermaid-svg-P9qqq79tYP2uYuwT .node rect,#mermaid-svg-P9qqq79tYP2uYuwT .node circle,#mermaid-svg-P9qqq79tYP2uYuwT .node ellipse,#mermaid-svg-P9qqq79tYP2uYuwT .node polygon,#mermaid-svg-P9qqq79tYP2uYuwT .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-P9qqq79tYP2uYuwT .rough-node .label text,#mermaid-svg-P9qqq79tYP2uYuwT .node .label text,#mermaid-svg-P9qqq79tYP2uYuwT .image-shape .label,#mermaid-svg-P9qqq79tYP2uYuwT .icon-shape .label{text-anchor:middle;}#mermaid-svg-P9qqq79tYP2uYuwT .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-P9qqq79tYP2uYuwT .rough-node .label,#mermaid-svg-P9qqq79tYP2uYuwT .node .label,#mermaid-svg-P9qqq79tYP2uYuwT .image-shape .label,#mermaid-svg-P9qqq79tYP2uYuwT .icon-shape .label{text-align:center;}#mermaid-svg-P9qqq79tYP2uYuwT .node.clickable{cursor:pointer;}#mermaid-svg-P9qqq79tYP2uYuwT .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-P9qqq79tYP2uYuwT .arrowheadPath{fill:#333333;}#mermaid-svg-P9qqq79tYP2uYuwT .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-P9qqq79tYP2uYuwT .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-P9qqq79tYP2uYuwT .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-P9qqq79tYP2uYuwT .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-P9qqq79tYP2uYuwT .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-P9qqq79tYP2uYuwT .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-P9qqq79tYP2uYuwT .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-P9qqq79tYP2uYuwT .cluster text{fill:#333;}#mermaid-svg-P9qqq79tYP2uYuwT .cluster span{color:#333;}#mermaid-svg-P9qqq79tYP2uYuwT div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-P9qqq79tYP2uYuwT .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-P9qqq79tYP2uYuwT rect.text{fill:none;stroke-width:0;}#mermaid-svg-P9qqq79tYP2uYuwT .icon-shape,#mermaid-svg-P9qqq79tYP2uYuwT .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-P9qqq79tYP2uYuwT .icon-shape p,#mermaid-svg-P9qqq79tYP2uYuwT .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-P9qqq79tYP2uYuwT .icon-shape .label rect,#mermaid-svg-P9qqq79tYP2uYuwT .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-P9qqq79tYP2uYuwT .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-P9qqq79tYP2uYuwT .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-P9qqq79tYP2uYuwT :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 三相电流 mA
Clark两相变换
霍尔电角度 θ
Park旋转变换
Id / Iq 直流反馈
Iq给定 g_fm_target_iq
PI_Iq调节器
Id给定固定=0
PI_Id调节器
输出Vq
输出Vd
电压矢量模长限幅
反Park变换
电压模长→占空比→六步换相输出
3.3 核心代码与公式配套讲解
3.3.1 PI结构体 + 带积分限幅的位置式PI实现
对应上面位置式离散PI方程,增加积分抗饱和:
c
typedef struct {
float Kp; // 比例系数
float Ki; // 合并后的积分系数
float Error; // 当前偏差 e(k)
float Integral; // 误差累加项 ∑e(k)
float Out; // PI输出电压 V(k)
float MaxOut; // 输出上限
float MinOut; // 输出下限
float IntegralMax; // 积分累加上限
float IntegralMin; // 积分累加下限
} pi_controller_t;
float pi_cal(pi_controller_t *pi, float target, float actual)
{
// 1. 计算当前误差 e(k) = 给定 - 反馈
pi->Error = target - actual;
// 2. 积分项累加 Ki * ∑e(k)
pi->Integral += pi->Ki * pi->Error;
// 积分抗饱和:限制积分累加值,防止深度饱和
if(pi->Integral > pi->IntegralMax)
pi->Integral = pi->IntegralMax;
if(pi->Integral < pi->IntegralMin)
pi->Integral = pi->IntegralMin;
// 3. 位置式PI完整输出公式
pi->Out = pi->Kp * pi->Error + pi->Integral;
// 输出电压限幅
if(pi->Out > pi->MaxOut)
pi->Out = pi->MaxOut;
if(pi->Out < pi->MinOut)
pi->Out = pi->MinOut;
return pi->Out;
}
严格对应公式:
V ( k ) = K p ⋅ e ( k ) + K i ∑ e ( k ) V(k)=K_p\cdot e(k)+K_i\sum e(k) V(k)=Kp⋅e(k)+Ki∑e(k)
3.3.2 DQ电流环主体函数
c
static void dq_current_loop_control(void)
{
/* 1. 采集三相电流,单位mA转A,执行坐标变换 */
g_foc_ctrl.Ia = g_fm_iu_ma / 1000.0f;
g_foc_ctrl.Ib = g_fm_iv_ma / 1000.0f;
g_foc_ctrl.theta = foc_get_electrical_theta(); // 获取电角度θ
foc_clark(&g_foc_ctrl); // 三相→两相静止坐标系 Iα,Iβ
foc_park(&g_foc_ctrl); // 两相静止→两相旋转坐标系 Id,Iq
/* 2. 双轴PI闭环运算 */
float id_target = 0.0f; // d轴给定始终为0
float iq_target = g_fm_target_iq / 1000.0f; // Iq给定 mA→A
// 执行PI公式,得到Vd、Vq
float vd = pi_cal(&g_fm_pi_id, id_target, g_foc_ctrl.Id);
float vq = pi_cal(&g_fm_pi_iq, iq_target, g_foc_ctrl.Iq);
/* 3. 电压矢量模长等比例限幅,对应缩放公式 */
float vbus = get_vbus_val();
float Vmax = vbus / sqrt(3.0f);
foc_voltage_limit(&vd, &vq, Vmax);
/* 4. 反Park变换,旋转坐标系→静止坐标系 Vα,Vβ */
g_foc_ctrl.Vd = vd;
g_foc_ctrl.Vq = vq;
foc_inv_park(&g_foc_ctrl);
/* 5. 电压矢量模长映射PWM占空比 */
float Vamp = sqrt(g_foc_ctrl.Valpha*g_foc_ctrl.Valpha + g_foc_ctrl.Vbeta*g_foc_ctrl.Vbeta);
uint16_t duty = (uint16_t)(Vamp / vbus * MOTOR_PWM_MAX);
set_bldcm_speed(duty);
}
限幅函数内部实现(对应缩放公式)
c
void foc_voltage_limit(float *Vd, float *Vq, float Vmax)
{
float Vmod = sqrt((*Vd)*(*Vd) + (*Vq)*(*Vq));
if(Vmod > Vmax)
{
float scale = Vmax / Vmod;
*Vd = *Vd * scale;
*Vq = *Vq * scale;
}
}
完全对应:
k s c a l e = V m a x V d 2 + V q 2 k_{scale}=\frac{V_{max}}{\sqrt{V_d^2+V_q^2}} kscale=Vd2+Vq2 Vmax
3.3.3 霍尔6扇区电角度计算公式
霍尔只有6个状态,每个扇区占据60°电角度。为减小角度误差,取扇区几何中心作为当前θ:
扇区号 hall = 1~6
角度计算公式(弧度制):
θ = ( ( h a l l − 1 ) + 0.5 ) ⋅ π 3 \theta = \big((hall-1)+0.5\big)\cdot \frac{\pi}{3} θ=((hall−1)+0.5)⋅3π
代码实现:
c
float foc_get_electrical_theta(void)
{
uint8_t hall = read_hall_sector();
float theta = ((hall - 1) + 0.5f) * (PI / 3.0f);
return theta;
}
每一扇区中心点相比扇区边界,平均角度误差从±60°缩小到±30°,已是霍尔6态能做到的最优值。
3.4 PI参数整定初值(量纲:V/A)
| 参数 | 初始值 | 说明 |
|---|---|---|
| d轴:Kpd / Kid | 0.5 / 80 | 用于把Id稳定钳位到0 |
| q轴:Kpq / Kiq | 0.5 / 80 | 跟踪Iq电流给定,控制转矩 |
| 电压输出限幅 | V b u s / 3 V_{bus}/\sqrt{3} Vbus/3 | 跟随母线电压实时计算 |
| Iq初始给定 | 800 ~ 1500 mA | 空载起步,最大不要超过6A,防止过流 |
| 控制周期 Ts | 25 ms | 和lesson13保持一致,方便前后对比试验 |
重要提醒:lesson13单环PID参数不能直接照搬。旧PID是相电流环,量纲为占空比/mA;DQ电流环PI输出是电压,量纲V/A,必须重新整定。
四、FreeMASTER 与串口
4.1 FreeMASTER观测变量
| 变量名 | 物理含义 |
|---|---|
g_fm_target_iq |
Iq电流给定(mA) |
g_fm_id_actual / g_fm_iq_actual |
d、q轴实际反馈电流(mA) |
g_fm_vd / g_fm_vq |
PI输出直轴、交轴电压(V) |
g_fm_theta_deg |
电角度(角度制) |
g_fm_pi_id / g_fm_pi_iq |
PI结构体,可在线修改Kp、Ki |
g_fm_curr_loop_en |
闭环使能:1.0开启DQ电流环,0开环 |
g_fm_iu_ma / iv_ma / iw_ma |
三相原始采样电流 |
motor_rpm |
霍尔计算转速 |
示波器推荐观测组合:Iq给定、Iq实际、Id实际,直观查看双轴跟随效果。
4.2 VOFA+配置
波特率115200,FireWater协议,3通道:
- ch0:Iq给定值
- ch1:Iq实际反馈值
- ch2:PWM输出占空比
本章仅用来观测波形,不用上位机下发控制指令。
4.3 串口调试命令
| 命令 | 功能 | 示例 |
|---|---|---|
c [mA] |
设置Iq电流给定 | c 1500 |
kpq / kiq |
修改q轴PI参数 | kiq 60 |
kpd / kid |
修改d轴PI参数 | kid 90 |
kp / ki |
d、q轴同步修改增益 | kp 0.4 |
s 1 / s 0 |
开启/关闭DQ电流闭环 | s 1 |
pid |
打印Id、Iq、Vd、Vq、电角度 | pid |
r |
清空PI积分累加值,退出饱和 | r |
cal |
电流ADC零偏校准(必须先关闭闭环 s 0) | cal |
| `v [pwm] / d [0 | 1]` | 六步开环测试模式 |
闭环运行时,按键K3/K4可以步进增减Iq给定,每次±200mA。
五、主程序流程
5.1 初始化顺序
- 系统时钟、LED、串口、ADC硬件初始化,执行电流零偏校准;
- 电机驱动初始化:TIM8生成PWM,TIM5捕获霍尔信号;
- DQ电流环初始化:配置PI上下限、默认Iq给定、默认关闭闭环;
- 上电等待2s,确认零偏校准完成,三相空载电流接近0mA。
5.2 主循环
text
while (1) {
deal_dq_curr_serial_data(); // 解析串口命令
deal_key_input(); // 按键处理
motor_protect_sync(); // 故障保护同步
dq_curr_poll(); // 25ms周期执行DQ电流闭环运算
motor_stall_poll(); // 堵转检测
motor_overcurrent_poll(); // 过流保护
dq_curr_vofa_poll(); // 上传VOFA波形数据
}
六、调试步骤与波形整定
安全操作:首次投入闭环务必空载,Iq先设置为800~1000mA;一旦出现电流飙升、异响,立刻发送
s 0切断闭环。
6.1 分步实验流程
- 烧录程序,上电等待3s,输入
pid确认零偏校准标志cal=1; - 发送
s 0开环,Iq置0,再打开闭环s 1,观察Id、Iq基线; - 设定
c 1500,投入闭环,观测Iq阶跃响应; - FreeMASTER同步观测Vd/Vq输出电压、PWM占空比、实时转速。
6.2 波形现象深度解读(对应角度缺陷)
现象
Iq实际值无法稳定在1500mA,在正负几百毫安来回周期性波动;Id无法锁零,持续大幅度摆动。
数学根源(公式层面解释)
Park变换矩阵严格依赖瞬时电角度 θ \theta θ:
I d I q \] = \[ cos θ sin θ − sin θ cos θ \] \[ I α I β \] \\begin{bmatrix}I_d\\\\I_q\\end{bmatrix}=\\begin{bmatrix}\\cos\\theta \& \\sin\\theta \\\\ -\\sin\\theta \& \\cos\\theta\\end{bmatrix}\\begin{bmatrix}I_\\alpha\\\\I_\\beta\\end{bmatrix} \[IdIq\]=\[cosθ−sinθsinθcosθ\]\[IαIβ
- 霍尔θ在60°区间内保持恒定,但转子一直在连续旋转,真实 θ \theta θ持续变化;
- 程序始终使用扇区固定中心角做Park运算,矩阵中的 cos θ 、 sin θ \cos\theta、\sin\theta cosθ、sinθ与真实角度不匹配;
- 坐标解耦失效,原本平直的直流Id/Iq被混入交流分量,形成周期性波纹。
再叠加执行端矛盾:
PI算出旋转坐标系直流电压Vd/Vq,反Park得到正弦电压矢量,最终却被强行压缩为六步方波电压,电压指令和实际输出波形不匹配,电流闭环自然无法稳住。
好坏判断标准
- 软件链路正常:ADC采样→Clark→Park→双PI→反Park整条链路数值连续刷新,电机可以平稳持续转动;
- 控制效果受限:受硬件条件约束,无法实现理想恒流;
- 不属于程序bug,属于当前传感器+调制方案带来的固有误差。
区分波纹与震荡
- 随转子转速周期性起伏 → 霍尔角度造成的固有纹波,属于正常现象;
- 电流无规则剧烈发散、频繁触发过流 → PI增益过大,立刻降低Kiq;
- 电流始终低于给定值、无大幅摆动 → 积分Ki不足,存在静差;
- 三相电流整体偏移 → ADC零偏没有校准,重新执行
cal。
本章范围内优化手段
- 把Iq给定降到800~1000mA,减轻PI积分饱和;
- 降低
Kiq(80下调至40~60),抑制电流大幅度正负摆动; - 适度提高
Kid,尽可能把Id均值拉向0; - 示波器拉长时基(2~5s),只观察Iq平均值是否跟随给定,不要纠结瞬时波纹。
想要得到教科书上平直的Id/Iq直流曲线,必须同时满足两点:
① 连续高精度电角度;
② SVPWM正弦电压输出,放在后续章节实现。
6.3 故障现象与对策
| 故障现象 | 诱因 | 处理方案 |
|---|---|---|
| Iq上升极其缓慢 | P、I增益偏小 | 小幅上调Kpq、Kiq |
| 电流来回剧烈震荡 | PI增益过高 | 降低Kp,减小Ki |
| 存在稳态静差,始终追不上给定 | 积分项不足 | 适当增大Ki |
| Id始终偏离0轴 | d轴积分不足 + 角度误差 | 提高Kid;检查霍尔接线 |
6.4 两代电流环横向对比
| 对比项 | lesson13 相电流单环PID | lesson16 DQ双轴电流环 |
|---|---|---|
| 反馈量 | 最大相电流 | Park解耦后的Id、Iq直流分量 |
| 调节器 | 单路PID | 两路独立PI |
| 输出量 | 直接输出PWM占空比 | 输出Vd/Vq电压矢量,再反Park变换 |
| 控制目标 | 限制相电流幅值 | Id=0励磁定向,Iq精准控制转矩 |
| 参数量纲 | 占空比/mA | V/A,两组参数不能通用 |
七、本章小结
- DQ双电流环数学架构:三相电流→Clark/Park解耦→Id/Iq直流反馈→双路PI计算Vd/Vq→电压矢量等比例限幅→反Park生成电压矢量。
- SPM表贴永磁电机默认采用 I d r e f = 0 Id_{ref}=0 Idref=0控制策略,依靠Iq精准控制输出转矩;闭环运行前必须完成ADC电流零偏校准。
- 6态霍尔只能提供阶梯式粗电角度,Park矩阵存在角度失配,再叠加六步方波驱动,必然造成Id/Iq周期性纹波,属于硬件架构限制,算法本身无错误。
- 电压限幅严格使用矢量模长比例缩放,保证电压矢量定向角度不变,不破坏磁场定向。
- 下一章在电流内环外层嵌套速度PI环,搭建速度-电流双闭环FOC系统。
*参考:野火《电机应用开发实战指南》