电机驱动开发学习16. DQ双轴电流环闭环控制

电机驱动开发学习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 主循环)
  • 六、调试步骤与波形整定
  • 七、本章小结

一、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?

  1. 相电流ADC采样包含大量高频开关噪声,微分项D会放大毛刺,造成电压输出频繁抖动,逆变器震荡发热。
  2. 电流环的核心需求:快速响应 + 消除稳态静差。比例项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)

各项含义拆解:

  1. K p ⋅ e ( k ) K_p \cdot e(k) Kp⋅e(k):比例项。偏差越大,输出电压越大,决定响应快慢;P越大响应越快,过大则超调、震荡。
  2. K i ⋅ ∑ e ( n ) K_i \cdot \sum e(n) Ki⋅∑e(n):积分项。对历史误差持续累加,只要存在静差,积分就会不断累积输出,最终把稳态误差拉到0。
  3. 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代码完成前,本章采用过渡验证方案:

  1. 完整执行链路:三相电流 → Clark → Park → Id/Iq → 双PI → Vd/Vq → 电压限幅 → 反Park → V α 、 V β V_\alpha、V_\beta Vα、Vβ;
  2. 只提取电压矢量模长 ∣ V ∣ = V α 2 + V β 2 |V|=\sqrt{V_\alpha^2+V_\beta^2} ∣V∣=Vα2+Vβ2 ,线性映射为六步换相的PWM占空比;
  3. 可以在现有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双轴电流内环:

  1. 复用lesson15坐标变换模块 bsp_foc.c
  2. 编写带抗饱和的位置式PI,d轴、q轴相互独立;
  3. 给定设置: I d r e f = 0 Id_{ref}=0 Idref=0, I q r e f Iq_{ref} Iqref默认1500mA;
  4. FreeMASTER观测Id、Iq、Vd、Vq、电角度θ;VOFA+监视Iq给定、反馈、PWM占空比;
  5. 保留电流零偏校准、过流保护、堵转保护代码。

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 初始化顺序

  1. 系统时钟、LED、串口、ADC硬件初始化,执行电流零偏校准;
  2. 电机驱动初始化:TIM8生成PWM,TIM5捕获霍尔信号;
  3. DQ电流环初始化:配置PI上下限、默认Iq给定、默认关闭闭环;
  4. 上电等待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 分步实验流程

  1. 烧录程序,上电等待3s,输入pid确认零偏校准标志cal=1
  2. 发送s 0开环,Iq置0,再打开闭环s 1,观察Id、Iq基线;
  3. 设定c 1500,投入闭环,观测Iq阶跃响应;
  4. 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β

  1. 霍尔θ在60°区间内保持恒定,但转子一直在连续旋转,真实 θ \theta θ持续变化;
  2. 程序始终使用扇区固定中心角做Park运算,矩阵中的 cos ⁡ θ 、 sin ⁡ θ \cos\theta、\sin\theta cosθ、sinθ与真实角度不匹配;
  3. 坐标解耦失效,原本平直的直流Id/Iq被混入交流分量,形成周期性波纹。

再叠加执行端矛盾:

PI算出旋转坐标系直流电压Vd/Vq,反Park得到正弦电压矢量,最终却被强行压缩为六步方波电压,电压指令和实际输出波形不匹配,电流闭环自然无法稳住。

好坏判断标准

  1. 软件链路正常:ADC采样→Clark→Park→双PI→反Park整条链路数值连续刷新,电机可以平稳持续转动;
  2. 控制效果受限:受硬件条件约束,无法实现理想恒流;
  3. 不属于程序bug,属于当前传感器+调制方案带来的固有误差。

区分波纹与震荡

  1. 随转子转速周期性起伏 → 霍尔角度造成的固有纹波,属于正常现象;
  2. 电流无规则剧烈发散、频繁触发过流 → PI增益过大,立刻降低Kiq;
  3. 电流始终低于给定值、无大幅摆动 → 积分Ki不足,存在静差;
  4. 三相电流整体偏移 → ADC零偏没有校准,重新执行cal

本章范围内优化手段

  1. 把Iq给定降到800~1000mA,减轻PI积分饱和;
  2. 降低Kiq(80下调至40~60),抑制电流大幅度正负摆动;
  3. 适度提高Kid,尽可能把Id均值拉向0;
  4. 示波器拉长时基(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,两组参数不能通用

七、本章小结

  1. DQ双电流环数学架构:三相电流→Clark/Park解耦→Id/Iq直流反馈→双路PI计算Vd/Vq→电压矢量等比例限幅→反Park生成电压矢量。
  2. SPM表贴永磁电机默认采用 I d r e f = 0 Id_{ref}=0 Idref=0控制策略,依靠Iq精准控制输出转矩;闭环运行前必须完成ADC电流零偏校准。
  3. 6态霍尔只能提供阶梯式粗电角度,Park矩阵存在角度失配,再叠加六步方波驱动,必然造成Id/Iq周期性纹波,属于硬件架构限制,算法本身无错误。
  4. 电压限幅严格使用矢量模长比例缩放,保证电压矢量定向角度不变,不破坏磁场定向。
  5. 下一章在电流内环外层嵌套速度PI环,搭建速度-电流双闭环FOC系统

*参考:野火《电机应用开发实战指南》

源码: https://gitee.com/xundh/learn-motor-stm32