motor-foc-control

GitHub 作者 LeoYeAI/openclaw-master-skills v2.1.0

FOC磁场定向控制深度指南 | 深入讲解FOC原理、SVPWM、MTPA、弱磁控制、龙贝格观测器,配合实测案例、C代码和PI整定脚本

安装 / 下载方式

TotalClaw CLI推荐
totalclaw install github:LeoYeAI~openclaw-master-skills~motor-foc-control
cURL直接下载,无需登录
curl -fsSL https://skills.taituai.com/api/skills/github%3ALeoYeAI~openclaw-master-skills~motor-foc-control/file -o motor-foc-control.md
# FOC 磁场定向控制深度指南 v2.1

面向电机工程实践,系统讲解 FOC 磁场定向控制的原理、实现、调参要点。
**新增:PI自动整定脚本、弱磁深度控制、故障诊断完整流程。**

## 目录

1. [FOC 基本原理](#foc-基本原理)
2. [SVPWM 原理与实现](#svpwm-原理与实现)
3. [MTPA(最大转矩电流比)控制](#mtpa最大转矩电流比控制)
4. [弱磁控制](#弱磁控制)
5. [磁链观测器](#磁链观测器)
6. [PI 参数整定指南](#pi-参数整定指南)
7. [工程参数速查](#工程参数速查)
8. [常见问题排查](#常见问题排查)
9. [参考资源](#参考资源)

---

## FOC 基本原理

### 坐标变换

```
三相静止坐标系 (ABC)
        ↓ Clarke 变换
两相静止坐标系 (α, β)
        ↓ Park 变换  
两相旋转坐标系 (d, q)

关键公式:
Clarke:  Iα = Ia
         Iβ = (Ia + 2Ib)/√3

Park:    Id = Iα·cos(θ) + Iβ·sin(θ)
         Iq = -Iα·sin(θ) + Iβ·cos(θ)

逆变换:
Iα = Id·cos(θ) - Iq·sin(θ)
Iβ = Id·sin(θ) + Iq·cos(θ)

三相重构:
Ia = Iα
Ib = -Iα/2 + Iβ·√3/2
Ic = -Iα/2 - Iβ·√3/2
```

### FOC 控制框图

```
        ┌──────────────────────────────────────────┐
        │                                          │
Iq_ref ──→ ┌────┐    ┌────┐    ┌────┐    ┌─────┐ │
           │ PI │───→│ SVPWM │──→│ 逆变器 │──→│ 电机 │ │
           └────┘    └────┘    └─────┘    │     │ │
           ↑ PI      ↑            ↑             │     │
Id_ref ───→┌────┐    │            │             ↓     ↓
           │ PI │────┘            │        ┌────────┐ │
           └────┘                 │        │ 三相输出 │ │
           ↑                      │        └────────┘ │
        0 ───→┌────┐             │             ↑       │
           ┌─→│ −ωLqIq │←───────┘             │       │
           │  └────┘                          │       │
      ┌────┐│                                 │       │
 θe ←│ PLL│←─────────────────────────────────┘       │
      └────┘                                          │
      (磁链观测器)                                      │
                                                     │
     ←←←←←← 转速环 ←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←←
```

---

## SVPWM 原理与实现

### 空间矢量定义

```c
// 8个基本空间矢量(6个非零 + 2个零矢量)
// U0(000): 000, U1(100): 100, U2(110): 110, ...
// U3(010): 010, U4(011): 011, U5(001): 001
// U6(101): 101, U7(111): 111

typedef struct {
    float alpha;
    float beta;
} SpaceVector;

// 合成任意方向电压矢量
SpaceVector sv_ref = {
    .alpha = Uref * cos(theta_e),
    .beta  = Uref * sin(theta_e)
};
```

### SVPWM 扇区判断

```c
// 判断参考电压矢量所在扇区
int sv_sector(SpaceVector *sv) {
    float a = sv->beta;
    float b = sv->alpha * 0.866 - sv->beta * 0.5;
    float c = -sv->alpha * 0.866 - sv->beta * 0.5;

    int N = 0;
    if (a > 0) N |= 1;
    if (b > 0) N |= 2;
    if (c > 0) N |= 4;

    // N → 扇区号 (1~6)
    const int sector_table[8] = {0, 2, 6, 1, 4, 3, 5, 0};
    return sector_table[N];
}
```

### SVPWM 时间计算

```c
// 在扇区 k 中,计算相邻矢量作用时间
// T0 = (T - Ta - Tb) / 2
// Ta, Tb 根据扇区查表

typedef struct {
    float Ualpha;
    float Ubeta;
    float T;        // PWM周期
    float Udc;      // 母线电压
} SVPWM_Handle;

void svpwm_calc(SVPWM_Handle *h, float *Ta, float *Tb) {
    float X = h->Ubeta;
    float Y = h->Ualpha * 0.866 + h->Ubeta * 0.5;
    float Z = -h->Ualpha * 0.866 + h->Ubeta * 0.5;

    int sector = sv_sector((SpaceVector*)h);

    switch(sector) {
        case 1: *Ta = Z; *Tb = Y; break;
        case 2: *Ta = Y; *Tb = -X; break;
        case 3: *Ta = -Z; *Tb = X; break;
        case 4: *Ta = -X; *Tb = Z; break;
        case 5: *Ta = X; *Tb = -Y; break;
        case 6: *Ta = -Y; *Tb = -Z; break;
    }

    // 过调制处理
    float T_sum = *Ta + *Tb;
    if (T_sum > h->T) {
        *Ta = *Ta * h->T / T_sum;
        *Tb = *Tb * h->T / T_sum;
    }

    // 零矢量分配(7段式对称PWM)
    float T0 = (h->T - *Ta - *Tb) / 2;
    float T7 = T0;

    // 计算三相占空比
    // DPA, DPB, DPC 存入比较寄存器
}
```

### 占空比计算(7段式对称SVPWM)

```c
// 各扇区占空比计算
// Tcm1, Tcm2, Tcm3 → 对应 ABC 三相比较值

void svpwm_duty(SVPWM_Handle *h, float *Tcm) {
    float Ta, Tb;
    svpwm_calc(h, &Ta, &Tb);
    float T0 = (h->T - Ta - Tb) / 2;

    int sector = sv_sector((SpaceVector*)h);

    switch(sector) {
        case 1:  // U4(100), U6(110), U0(000)
            Tcm[0] = (h->T + Ta + Tb) / 2;  // A: 先断后通
            Tcm[1] = (h->T - Ta + Tb) / 2;  // B
            Tcm[2] = (h->T - Ta - Tb) / 2;  // C
            break;
        case 2:  // U6(110), U2(010), U0(000)
            Tcm[0] = (h->T - Ta + Tb) / 2;
            Tcm[1] = (h->T + Ta + Tb) / 2;
            Tcm[2] = (h->T - Ta - Tb) / 2;
            break;
        case 3:  // U2(010), U3(011), U0(000)
            Tcm[0] = (h->T - Ta - Tb) / 2;
            Tcm[1] = (h->T + Ta + Tb) / 2;
            Tcm[2] = (h->T + Ta - Tb) / 2;
            break;
        case 4:  // U3(011), U1(001), U0(000)
            Tcm[0] = (h->T - Ta - Tb) / 2;
            Tcm[1] = (h->T - Ta + Tb) / 2;
            Tcm[2] = (h->T + Ta + Tb) / 2;
            break;
        case 5:  // U1(001), U5(101), U0(000)
            Tcm[0] = (h->T + Ta - Tb) / 2;
            Tcm[1] = (h->T - Ta - Tb) / 2;
            Tcm[2] = (h->T + Ta + Tb) / 2;
            break;
        case 6:  // U5(101), U4(100), U0(000)
            Tcm[0] = (h->T + Ta + Tb) / 2;
            Tcm[1] = (h->T - Ta - Tb) / 2;
            Tcm[2] = (h->T + Ta - Tb) / 2;
            break;
    }
}
```

---

## MTPA(最大转矩电流比)控制

### 原理

对于内嵌式 PMSM(IPMSM),存在 d轴磁阻转矩,利用 MTPA 可在相同电流下获得更大转矩。

```
电磁转矩方程:
T = 1.5 × np × [Ψm × Iq + (Ld - Lq) × Id × Iq]

定义电流幅值:
|I| = √(Id² + Iq²)

MTPA 轨迹:固定 |I|,寻找使 T 最大的 (Id, Iq) 组合
```

### MTPA 数学推导

```
令 ∂T/∂Id = 0,约束条件 |I| = constant

拉格朗日函数:L = T - λ(√(Id²+Iq²) - I_ref)

∂L/∂Id = 1.5×np×[(Ld-Lq)×Iq] - λ×Id/|I| = 0
∂L/∂Iq = 1.5×np×[Ψm + (Ld-Lq)×Id] - λ×Iq/|I| = 0

联立求解(化简后):

Id_MTPA = -(Ψm / (2×ΔL)) + √[(Ψm/(2ΔL))² + Iq²]

其中 ΔL = Lq - Ld > 0

当 ΔL 很小时(表贴式),Id_MTPA ≈ 0 → 退化为 Id=0 控制
```

### MTPA 实现

```c
// MTPA 查表法(实时性最好)
// 预计算 MTPA 曲线,运行时查表 + 线性插值

static const float mtpa_table_Iq[] = {
    0.0, 2.0, 4.0, 6.0, 8.0, 10.0, 12.0, 15.0, 18.0, 20.0
};
static const float mtpa_table_Id[] = {
    0.0, -0.5, -1.1, -1.8, -2.5, -3.2, -4.0, -5.3, -6.6, -7.8
};

float mtpa_interpolate(float Iq) {
    int n = sizeof(mtpa_table_Iq) / sizeof(mtpa_table_Iq[0]);
    // 边界
    if (Iq <= mtpa_table_Iq[0]) return mtpa_table_Id[0];
    if (Iq >= mtpa_table_Iq[n-1]) return mtpa_table_Id[n-1];
    // 查表
    for (int i = 0; i < n-1; i++) {
        if (Iq >= mtpa_table_Iq[i] && Iq < mtpa_table_Iq[i+1]) {
            float t = (Iq - mtpa_table_Iq[i]) /
                       (mtpa_table_Iq[i+1] - mtpa_table_Iq[i]);
            return mtpa_table_Id[i] + t * (mtpa_table_Id[i+1] - mtpa_table_Id[i]);
        }
    }
    return 0;
}

// MTPA 解析公式法(适合在线计算)
float mtpa_Id_formula(float Iq, float Psi_m, float Ld, float Lq) {
    float delta_L = Lq - Ld;
    if (delta_L < 1e-6) return 0;  // 表贴式,无 MTPA 效益

    float k = Psi_m / (2.0f * delta_L);
    float Id = -k + sqrtf(k * k + Iq * Iq);
    return -Id;  // Id 必须为负(去磁)
}
```

---

## 弱磁控制

### 原理

当转速超过基速时,反电动势 E > Vdc,电压饱和。弱磁通过增加 Id(去磁电流)来降低有效磁链,从而在恒功率区扩展转速。

```
电压极限椭圆(d-q 平面):
Vd² + Vq² ≤ Vdc² / 2   (SVPWM线性调制区最大输出)

反电动势约束:
V = ω_e × (Ψm - Ld×Id)  ≈ ω_e × Ψm_eff

弱磁的本质:在电压极限椭圆内重新分配 Id、Iq
```

### 弱磁深度等级

| 等级 | Id 比例 | 适用转速范围 | 特性 |
|------|---------|------------|------|
| 轻度弱磁 | -0.3×Imax | 1~1.5× 基速 | 转矩下降少 |
| 中度弱磁 | -0.5×Imax | 1.5~2× 基速 | 恒功率区主力 |
| 深度弱磁 | -0.7×Imax | 2~3× 基速 | 转矩大幅下降 |
| 六步方波 | 全部去磁 | >3× 基速 | 最大转速,扭矩波动大 |

### 弱磁控制器实现

```c
typedef enum {
    MTPA_MODE,         // 最大转矩电流比
    FW_MODE,            // 弱磁模式
    SIXSTEP_MODE        // 六步方波
} FluxMode;

typedef struct {
    float Vdc;          // 母线电压
    float V_lim;        // 电压极限(Vdc/sqrt(2))
    float V_th;         // 弱磁启动阈值(建议 0.9×V_lim)
    float Id_fw_min;    // 最大去磁电流(负值)
    float gamma;         // 弱磁PI积分系数
    float Kp_fw;        // 弱磁比例增益
    float Ki_fw;        // 弱磁积分增益
} FluxWeaken_Handle;

void flux_weaken_update(FluxWeaken_Handle *h,
                        float V_mag, float Id_ref,
                        float *Id_fw_out) {
    // V_mag = sqrt(Vd² + Vq²)
    // Id_ref = MTPA 给定的 Id

    static float integral = 0;
    float error = V_mag - h->V_lim * 0.95;  // 提前 5% 介入

    if (error > 0) {
        // 电压饱和,启动弱磁
        integral += h->gamma * error;
        integral = fminf(integral, 0);  // Id_fw 为负,积分限幅
        *Id_fw_out = h->Id_fw