跳转至

电机控制系统

电机控制的核心思想:串级控制——电流环在最里面保证力矩,速度环在中间保证转速,位置环在最外面保证角度。


一、为什么需要串级控制

假设你要控制一个电机精确转到 90°。最直觉的做法是直接用 PID 控制位置:

\[ \text{PWM} = \text{PID}(90° - \theta_{\text{actual}}) \]

这能工作,但有两个严重问题:

  1. 电流不可控:位置突变时,PID 输出可能瞬间拉满,电流冲击可能烧毁电机或驱动器
  2. 动态性能差:一个 PID 要同时管位置精度和电流安全,参数很难调好

解决方案:把一个复杂问题拆成三个简单问题——

graph LR
    POS_REF["位置目标<br>90°"] --> POS_PID["位置环<br>PID"]
    POS_PID -->|速度指令| VEL_PID["速度环<br>PID"]
    VEL_PID -->|电流指令| CUR_PID["电流环<br>PID"]
    CUR_PID -->|PWM| MOTOR["电机"]
    MOTOR -->|电流反馈| CUR_PID
    MOTOR -->|速度反馈| VEL_PID
    MOTOR -->|位置反馈| POS_PID

每层只负责一件事,参数独立调节。


二、电流环(最内环)

2.1 电流环在干什么

电流控制到底是在控制什么?

电流 ∝ 力矩。控制电流就是控制电机输出的力矩。

根据电机方程 \(T = K_t \cdot I\),电流和力矩是线性关系。所以:

  • 控制电流 = 控制力矩
  • 电流环 = 力矩环

2.2 为什么需要电流环

  1. 保护:限制电流,防止电机过热或驱动器烧毁
  2. 力矩精度:在力控场景(如机器人抓取)中,需要精确控制输出力
  3. 动态性能:电流环响应最快(带宽最高),为外环提供快速的力矩响应

2.3 有刷 DC 电机的电流环

有刷电机只有一个电流回路,控制相对简单:

graph LR
    I_REF["电流<br>目标值"] --> SUM((+/-))
    SUM -->|误差| PID["电流 PID"]
    PID -->|PWM| HBRIDGE["H 桥<br>驱动"]
    HBRIDGE -->|电压| MOTOR["电机"]
    MOTOR --> SENSOR["电流<br>传感器"]
    SENSOR -->|实际电流| SUM

电流采样

方法 位置 优缺点
低侧采样 H 桥下管的接地端串电阻 简单便宜,但只能在特定 PWM 相位采样
高侧采样 电源到 H 桥之间串电阻 能采全部电流,但电压高需要差分放大
相电流采样 电机线上串电阻或用霍尔 最直接但线路复杂

电流环带宽:通常 1~10 kHz,远高于速度环和位置环。

有刷电机电流环代码框架

// 在定时器中断中执行(如 10kHz)
void TIM_IRQHandler(void) {
    float I_actual = read_current_sensor();  // ADC 采样
    float I_error = I_target - I_actual;
    float pwm = PID_Update(&current_pid, I_target, I_actual);
    set_hbridge_pwm(pwm);
}

2.4 三相电机的电流环(FOC 的核心)

BLDC/PMSM 是三相电机,有三个相电流 \(i_a, i_b, i_c\),它们之间相互耦合,直接用 PID 控制任何一相电流都不好使。

解决思路:把三相耦合的交流电流,变换成两个解耦的直流电流,然后分别用 PID 控制。

这就是 FOC(Field Oriented Control,磁场定向控制) 的核心思想。


三、FOC——磁场定向控制

3.1 FOC 的本质

FOC 的目标:把一个复杂的三相交流电机,等效成一个简单的直流电机来控制。

graph TB
    subgraph "三相世界(复杂)"
        IA["i_a (交流)"]
        IB["i_b (交流)"]
        IC["i_c (交流)"]
    end
    subgraph "两相旋转世界(简单)"
        ID["i_d (直流) → 控制磁场"]
        IQ["i_q (直流) → 控制力矩"]
    end
    IA --> CLARK["Clarke<br>变换"]
    IB --> CLARK
    IC --> CLARK
    CLARK --> PARK["Park<br>变换"]
    PARK --> ID
    PARK --> IQ

3.2 坐标变换

Clarke 变换(3 相 → 2 相静止)

将三相 \((i_a, i_b, i_c)\) 变换为两相静止坐标 \((\alpha, \beta)\)

\[ \begin{bmatrix} i_\alpha \\ i_\beta \end{bmatrix} = \frac{2}{3} \begin{bmatrix} 1 & -\frac{1}{2} & -\frac{1}{2} \\ 0 & \frac{\sqrt{3}}{2} & -\frac{\sqrt{3}}{2} \end{bmatrix} \begin{bmatrix} i_a \\ i_b \\ i_c \end{bmatrix} \]

直觉理解

三相电流分布在空间上互差 120°,但三者之和为零(\(i_a + i_b + i_c = 0\)),所以实际只有 2 个自由度。Clarke 变换就是把 3 个冗余变量降到 2 个独立变量。

Park 变换(静止 → 旋转)

\((\alpha, \beta)\) 变换到与转子同步旋转的 \((d, q)\) 坐标系:

\[ \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} \]

其中 \(\theta\) 是转子的电角度(由编码器或观测器提供)。

变换后的物理意义

分量 物理意义 控制目标
\(i_d\) 励磁电流(与转子磁场方向一致) 通常设为 0(不额外加磁)
\(i_q\) 力矩电流(与转子磁场垂直) 直接控制输出力矩 \(T = \frac{3}{2} p \lambda_m i_q\)

\(i_d = 0\) 控制策略:让所有电流都用来产生力矩,效率最高。这就是为什么 FOC 比六步换向效率更高。

3.3 FOC 完整控制框图

graph TB
    IQ_REF["i_q* (力矩指令)"] --> SUM_Q((+/-))
    ID_REF["i_d* = 0"] --> SUM_D((+/-))

    SUM_Q -->|误差| PID_Q["q 轴 PID"]
    SUM_D -->|误差| PID_D["d 轴 PID"]

    PID_Q --> VQ["V_q"]
    PID_D --> VD["V_d"]

    VQ --> INV_PARK["反 Park<br>变换"]
    VD --> INV_PARK

    INV_PARK --> VA["V_α"]
    INV_PARK --> VB["V_β"]

    VA --> SVPWM["SVPWM"]
    VB --> SVPWM

    SVPWM -->|PWM_A,B,C| INVERTER["三相<br>逆变器"]
    INVERTER --> MOTOR["PMSM/BLDC"]

    MOTOR --> CS["电流<br>采样"]
    CS --> CLARKE["Clarke"]
    CLARKE --> PARK["Park"]
    PARK -->|i_d| SUM_D
    PARK -->|i_q| SUM_Q

    MOTOR --> ENC["编码器"]
    ENC -->|θ| PARK
    ENC -->|θ| INV_PARK

3.4 SVPWM(空间矢量脉宽调制)

得到目标电压 \((V_\alpha, V_\beta)\) 后,需要把它变成三相逆变器的实际 PWM 信号。SVPWM 是最常用的方法。

原理:三相逆变器有 8 种基本开关状态(\(2^3 = 8\),其中 2 种是零矢量),在一个 PWM 周期内交替使用相邻的两个有效矢量和零矢量,"合成"出目标矢量。

相比 SPWM SVPWM 优势
电压利用率 高 15.47%(\(\frac{2}{\sqrt{3}} \approx 1.155\)
谐波 更低
开关损耗 更低

四、速度环(中间环)

4.1 速度环做什么

速度环接收速度指令,输出电流指令(即力矩指令),交给内层电流环执行。

\[ i_q^* = \text{PID}_{\text{vel}}(\omega^* - \omega_{\text{actual}}) \]

4.2 速度反馈

方法 原理 精度
增量式编码器 计数脉冲,\(\omega = \frac{\Delta \theta}{\Delta t}\) 取决于编码器线数和采样频率
绝对值编码器 直接读取角度,差分求速度 高精度但可能有噪声
反电动势估算 从电压方程反推 \(\omega = \frac{V - RI}{K_e}\) 中低精度,无传感器方案

4.3 速度环调参

速度环带宽通常为电流环的 1/5 ~ 1/10

速度环调参经验

  • 先确保电流环已调好(响应快、无振荡)
  • \(K_p\):从小到大,直到出现轻微超调
  • \(K_i\):慢慢加,消除稳态速度误差
  • \(K_d\):速度环一般不用 D 项(编码器噪声会被放大),用 PI 控制器即可

五、位置环(最外环)

5.1 位置环做什么

位置环接收位置指令(如目标角度),输出速度指令,交给速度环。

\[ \omega^* = \text{PID}_{\text{pos}}(\theta^* - \theta_{\text{actual}}) \]

5.2 位置环特点

  • 带宽最低:通常为速度环的 1/3 ~ 1/5
  • 精度要求最高:最终的定位精度取决于这一环
  • 常用 P 或 PD 控制:位置环积分项容易引起振荡,很多场景只用 P 控制

位置环为什么经常不加 I?

位置环的稳态误差通常已经被速度环的积分项消除了。如果位置有小的稳态偏差,速度环会产生一个微小的持续速度指令,通过积分效应把位置拉到目标。再在位置环加 I 反而可能过度校正,引起低频振荡。

5.3 轨迹规划与位置环

直接给位置环一个阶跃指令(如从 0° 跳到 90°)会导致:速度指令瞬间很大 → 电流冲击 → 机械冲击。

解决方案:用轨迹规划器生成平滑的位置-速度-加速度曲线:

速度
 ^
 |    /‾‾‾‾‾‾\
 |   /        \
 |  /          \
 | /            \
 └──────────────→ 时间
   加速  匀速  减速
三段式:恒加速 → 匀速 → 恒减速。简单,但加速度不连续。

速度
 ^
 |    ╭──────╮
 |   ╱        ╲
 |  ╱          ╲
 | ╱            ╲
 └──────────────→ 时间
七段式:加速度连续变化,更平滑,减少机械冲击。


六、三环串级控制总结

带宽关系

位置环: ~50-200 Hz
    └── 速度环: ~200-1000 Hz
            └── 电流环: ~1-10 kHz

外环带宽必须低于内环,否则外环的指令变化比内环的响应还快,系统会不稳定。

经验法则:外环带宽 ≤ 内环带宽的 1/3 ~ 1/5

调参顺序

串级控制的调参铁律:从内到外

  1. 先调电流环:断开速度环,直接给电流指令,调到响应快且无振荡
  2. 再调速度环:断开位置环,直接给速度指令,调到跟踪好
  3. 最后调位置环:给位置指令,调到定位准确

绝对不要反过来调! 如果内环没调好就调外环,外环的任何参数变化都会引起内环的问题,永远调不好。

各环参数对比

电流环 速度环 位置环
控制量 PWM(电压) 电流指令 速度指令
反馈量 电流传感器 编码器(微分) 编码器
带宽 1~10 kHz 200~1000 Hz 50~200 Hz
控制器 PI PI P 或 PD
执行频率 10~20 kHz 1~5 kHz 0.5~1 kHz

七、不同电机的控制架构

有刷 DC 电机

位置环(P/PD) → 速度环(PI) → 电流环(PI) → H桥PWM → 电机
                             电流传感器

最简单的三环控制,所有计算在一维空间完成。

步进电机

位置指令 → 轨迹规划器 → 脉冲发生器 → 步进驱动器 → 电机

通常是开环控制,不需要三环结构。如果加编码器做闭环,则类似伺服电机。

BLDC(六步换向)

速度环(PI) → 电流环(PI) → 六步换向逻辑 → 三相逆变器 → 电机
                          霍尔传感器

PMSM(FOC)

位置环(P) → 速度环(PI) → FOC电流环(d/q轴双PI) → SVPWM → 三相逆变器 → 电机
                              ↑                              ↑
                         Clarke+Park变换              编码器(电角度)
                         电流采样(2相)

八、实战:STM32 上的电机控制

硬件资源分配

功能 外设 说明
PWM 输出 TIM1(高级定时器) 3 路互补 PWM + 死区
电流采样 ADC1 + ADC2 双 ADC 同步采样两相电流
编码器 TIM3(编码器模式) 正交解码
控制循环 TIM1 更新中断 PWM 频率即控制频率

典型控制循环

// TIM1 更新中断 —— 每个 PWM 周期执行一次(如 20kHz)
void TIM1_UP_IRQHandler(void) {
    // 1. 采样电流(ADC 注入通道,由 TIM1 触发)
    float Ia = adc_to_current(ADC1->JDR1);
    float Ib = adc_to_current(ADC2->JDR1);

    // 2. 读取编码器角度
    float theta_e = encoder_get_electrical_angle();

    // 3. Clarke 变换
    float I_alpha = Ia;
    float I_beta = (Ia + 2 * Ib) / SQRT3;

    // 4. Park 变换
    float Id =  I_alpha * cosf(theta_e) + I_beta * sinf(theta_e);
    float Iq = -I_alpha * sinf(theta_e) + I_beta * cosf(theta_e);

    // 5. 电流环 PI 控制
    float Vd = PID_Update(&pid_id, 0.0f, Id);    // id* = 0
    float Vq = PID_Update(&pid_iq, iq_ref, Iq);  // iq* 来自速度环

    // 6. 反 Park 变换
    float V_alpha =  Vd * cosf(theta_e) - Vq * sinf(theta_e);
    float V_beta  =  Vd * sinf(theta_e) + Vq * cosf(theta_e);

    // 7. SVPWM 生成 PWM
    svpwm_set_voltage(V_alpha, V_beta);
}

// 速度环 —— 较低频率执行(如 1kHz)
void velocity_loop(void) {
    float omega = encoder_get_speed();
    iq_ref = PID_Update(&pid_vel, omega_ref, omega);
}

// 位置环 —— 最低频率执行(如 500Hz)
void position_loop(void) {
    float theta = encoder_get_position();
    omega_ref = PID_Update(&pid_pos, theta_ref, theta);
}

九、进阶话题

无传感器控制(Sensorless)

不使用编码器,通过电压和电流信息估算转子位置和速度。

方法 原理 适用范围
BEMF 过零检测 检测反电动势过零点 中高速 BLDC
滑模观测器 基于电机模型估算 BEMF 中高速 PMSM
高频注入 注入高频信号,利用磁阻不对称 低速/零速 PMSM
扩展卡尔曼滤波 状态估计理论 全速域

弱磁控制(Flux Weakening)

当电机转速很高时,反电动势接近供电电压,电流环"饱和"了。此时通过注入负的 \(i_d\)\(i_d < 0\)),主动削弱磁场,换取更高的转速。

\[ V_s = \sqrt{V_d^2 + V_q^2} \leq V_{\max} \]

\(\omega\) 增大到 \(K_e \omega \approx V_{\max}\) 时,必须开始弱磁。

模型预测控制(MPC)

不用 PID,而是在每个控制周期:

  1. 基于电机模型,预测所有可能的开关状态下,下一时刻的电流
  2. 选择使预测电流最接近目标的开关状态

优势:天然处理约束(电流限制、电压限制),多目标优化。 劣势:计算量大,需要精确模型。