前言
上一章我们通过 Clark 变换,把三相电流 Iu,Iv,Iw 变成了两相静止坐标系下的电流 Iα,Iβ。到这里,电机电流从 “三相耦合” 变成了 “两相正交”,计算简单了很多,但依然是交流量—— 大小随时间正弦变化,没法用简单的 PID 直接稳控。
FOC 之所以能把无刷电机变得像直流电机一样好控制,核心全靠 Park 变换。
本章我们一次性讲透:
- Park 变换到底在干什么
- d/q 轴分别代表什么物理意义
- 电角度 θ 从哪来、怎么算
- 完整公式推导 + 两种写法
- 浮点 / 定点代码直接可用
- 工程里 90% 的人都会踩的坑
读完这一章,你才算真正摸到 FOC 的核心逻辑。
1. Park 变换到底解决了什么问题?
先一句话总结:
Park 变换:把 αβ 静止坐标系,变换到 dq 旋转坐标系,让交流量变成直流量。
展开说:
- αβ 坐标系:固定在定子上,不动
- dq 坐标系:固定在转子上,跟着转子一起旋转
当你站在 “旋转的转子” 视角去看电流:
- 原来随时间正弦波动的 Iα,Iβ
- 会变成两个稳定不变的直流分量 Id,Iq
交流变直流意味着什么?
- 可以用普通 PI 调节器直接控制
- 可以做到完全解耦:磁场归磁场,力矩归力矩
- 控制简单、稳定、响应快、低速平滑
这就是 FOC 能吊打方波驱动的根本原因。
2. d 轴与 q 轴的物理意义
对表贴式永磁同步电机 PMSM(我们常用的 BLDC 绝大多数都是这种):
-
d 轴(direct axis)直轴与转子永磁体磁场方向一致对应:励磁分量
-
q 轴(quadrature axis)交轴超前 d 轴 90° 电角度对应:转矩分量
控制目标极其清晰:
- Id=0:弱磁控制以外,默认都让 d 轴电流为 0,不削弱磁场,效率最高
- Iq:想力气大就加大 Iq,想刹车就减小甚至反向
这就是经典的:
Id=0 FOC 控制策略
3. 电角度 θ 是整个变换的 “钥匙”
Park 变换本质是矢量旋转,旋转多少度,由电角度 θ 决定。
电角度怎么来?

θ 的作用:
它代表当前转子磁场指向的角度,决定了 dq 坐标系相对于 αβ 坐标系旋转了多少。
没有 θ,Park 变换无从谈起。θ 不准 → FOC 直接抖、啸叫、无力、发热。
4. Park 变换标准公式推导
4.1 变换关系
从 αβ 静止坐标系,逆时针旋转 θ,得到 dq 旋转坐标系:

5. 反 Park 变换(FOC 输出必备)
电流环计算完 Vd,Vq 之后,要变回 αβ 给 SVPWM 用,这就是反 Park。
公式:

6. 完整代码实现(浮点版)
6.1 Park 变换
#include "math.h"
/**
* @brief Park 变换: αβ → dq
* @param Iα, Iβ: 两相静止电流
* @param theta: 电角度(弧度)
* @param Id, Iq: 输出直流量
*/
void Park_Transform(float Ialpha, float Ibeta, float theta, float *Id, float *Iq)
{
float sin_theta = sinf(theta);
float cos_theta = cosf(theta);
*Id = Ialpha * cos_theta + Ibeta * sin_theta;
*Iq = -Ialpha * sin_theta + Ibeta * cos_theta;
}
6.2 反 Park 变换
/**
* @brief 反Park变换: dq → αβ
* @param Vd, Vq: 电压指令
* @param theta: 电角度(弧度)
* @param Valpha, Vbeta: 输出静止坐标系电压
*/
void Inv_Park(float Vd, float Vq, float theta, float *Valpha, float *Vbeta)
{
float sin_theta = sinf(theta);
float cos_theta = cosf(theta);
*Valpha = Vd * cos_theta – Vq * sin_theta;
*Vbeta = Vd * sin_theta + Vq * cos_theta;
}
7. 定点优化版(无 FPU 单片机适用)
对 STM32F103 等资源紧张的 MCU,可以用正弦余弦表 + Q15 定点:
// 正弦余弦表(θ:0~360°,精度1°), Q15格式
const int16_t sin_table[] = {
// 自行填入 0~359° 的 sin*32767
};
#define GET_SIN(deg) sin_table[deg%360]
#define GET_COS(deg) sin_table[(deg+90)%360]
void Park_Fixed(int16_t Ialpha, int16_t Ibeta, uint16_t theta_deg, int16_t *Id, int16_t *Iq)
{
int32_t sin_theta = GET_SIN(theta_deg);
int32_t cos_theta = GET_COS(theta_deg);
*Id = ((int32_t)Ialpha * cos_theta + (int32_t)Ibeta * sin_theta) >> 15;
*Iq = ((int32_t)-Ialpha * sin_theta + (int32_t)Ibeta * cos_theta) >> 15;
}
工程建议:
- 有 FPU(F4/F7/H7/G4)直接用浮点,简单好调
- 无 FPU 用查表法,速度极快
8. 为什么变换后 Id、Iq 是直流(最关键的理解)
举个直观例子:
- 你站在地面(αβ)看风车叶片,位置一直在变,是交流
- 你坐在风车转子上(dq)一起转,叶片相对你不动,是直流
对应到电机:
- 、 随电角度正弦波动
- 用 θ 同步旋转后,波动被 “抵消” 了
- 输出的 、 变成恒定直流
于是:
- 用 PI 控制器去稳 Id、Iq
- 就像控制简单直流电机一样轻松
这就是 FOC 的数学魔法。
9. 工程高频踩坑
9.1 θ 角度方向反了
现象:
- 电机一转就啸叫、抖动、电流巨大
- 改方向也没用
原因:
- 电角度 θ 递增方向与转子实际旋转方向相反
解决:
theta = -theta;
或反序 Hall 计算角度。
9.2 sin/cos 角度单位不统一
- 代码里用弧度,计算时用角度
- 结果完全错乱
统一规则:
- C 语言 math.h:sinf/cosf 一律用弧度
- 霍尔 / 编码器:先转弧度再传入
9.3 dq 轴定义反了
有些资料 / 电机库定义:Iq=Iαsinθ+Iβcosθ符号不一样,会导致:
- 力矩方向相反
- 电机飞车、失控
解决:整套 FOC 坐标系从头到尾保持一致,不要混用多家库公式。
9.4 角度延迟未补偿
编码器读取、ADC 采样、运算都需要时间θ 已经变了,你还用旧角度→ 电流环相位滞后 → 低速抖、高速弱
高端 FOC 都会做:角度前馈补偿 / 观测器相位补偿
9.5 Id 没有置 0
表贴式电机默认 Id=0如果你给 Id 一个随机初始值会出现:
- 力矩小
- 电流大
- 发热严重
- 效率极低
10. 完整 FOC 电流环结构
完整的电流环流程:
- Idref=0
- Iqref 为力矩指令
这就是标准 Id=0 FOC 控制架构。
11. 本章总结
Park 变换是 FOC 真正的灵魂,核心就 4 点:
- Id:励磁,默认 0
- Iq:转矩,控制力气
到这里,FOC 最难的数学部分已经全部结束。
网硕互联帮助中心![第5章,[Win32 章节] :边框绘制函数(二)-网硕互联帮助中心](https://www.wsisp.com/helps/wp-content/uploads/2026/08/20260811231700-6a7bad6c42588-220x150.png)






评论前必须登录!
注册