3、Clark变换与Park变换:三相坐标系与两相坐标系
好,咱们今天聊点硬核的。Clark变换和Park变换,说白了就是无感FOC的数学基石。你想想看,电机里跑的是三相正弦电流,但我们要控制的是转矩和磁通——这俩东西在静止的三相坐标系里根本没法直接解耦。怎么办?换个坐标系看问题。
我刚开始做FOC时,对着公式看了半天,总觉得这俩变换就是一堆矩阵乘法。后来踩过坑才明白:Clark是把三相变两相,Park是把静止变旋转。搞懂这个,后面的控制逻辑就顺了。
3.1 为什么要把三相变成两相?
三相电机有三根线,电流分别是Ia、Ib、Ic。它们之间差120度,互相耦合。你想想看,要同时控制三个变量,还要让它们产生恒定的转矩,这多麻烦?
其实,三相系统有个特点:Ia + Ib + Ic = 0(星形接法,中线不引出)。这意味着三个变量里只有两个是独立的。那我们能不能用两个正交的轴来描述它?
这就是Clark变换的出发点。把三相(a, b, c)投影到两相静止坐标系(α, β)上。α轴和a轴重合,β轴超前α轴90度。这样一来,三个互相依赖的变量,变成了两个正交独立的变量。
核心思想: 三相交流量 → 两相交流量。频率不变,幅值不变(等幅值变换下)。
3.2 Clark变换公式推导
咱们直接上公式。假设三相电流为Ia、Ib、Ic,且满足Ia + Ib + Ic = 0。
Clark变换(等幅值变换)为:
Iα = Ia
Iβ = (Ia + 2*Ib) / √3
或者写成矩阵形式:
[ Iα ] [ 1, -1/2, -1/2 ] [ Ia ]
[ Iβ ] = [ 0, √3/2, -√3/2 ] [ Ib ]
[ I0 ] [ 1/2, 1/2, 1/2 ] [ Ic ]
注意,这里第三行是零序分量I0。对于平衡的三相系统,I0 = 0。但在实际项目中,我建议你保留I0的计算,用来检测电流传感器是否故障或者三相是否不平衡。
我的经验: 有一次在调试时,电机低速抖动,查了半天发现是某一相电流采样偏置出了问题。后来我在代码里加了I0的监控,一旦I0超过阈值就报警。这个习惯帮我避免了好几次炸板子。
逆Clark变换(从αβ回到abc)也很简单:
Ia = Iα
Ib = -Iα/2 + √3/2 * Iβ
Ic = -Iα/2 - √3/2 * Iβ
嗯,这里要注意:等幅值变换和等功率变换的系数不同。我习惯用等幅值变换,因为这样电流环的PI参数调起来更直观——你给1A的指令,电机里就是1A的电流。
3.3 Park变换公式推导
Clark变换之后,我们得到了αβ坐标系下的两相正弦量。但控制目标——转矩和磁通——还是耦合在一起的。怎么办?再转一次坐标系。
Park变换把静止的αβ坐标系,旋转到与转子磁极同步的dq坐标系。d轴指向转子磁极方向,q轴超前d轴90度。这样一来,正弦量变成了直流量。
公式如下:
Id = Iα * cos(θ) + Iβ * sin(θ)
Iq = -Iα * sin(θ) + Iβ * cos(θ)
其中θ是转子电角度。在无感FOC中,这个θ是通过观测器估算出来的,不是直接测量的。
逆Park变换:
Iα = Id * cos(θ) - Iq * sin(θ)
Iβ = Id * sin(θ) + Iq * cos(θ)
我曾经踩过的坑: 刚开始写代码时,我把Park变换里的正负号搞反了。结果电机转起来电流很大,但转矩就是出不来。后来对着公式一行一行对,才发现是sin项前面的符号错了。所以,建议你写完变换后,先用单位圆上的点验证一下。
3.4 仿真验证
光说不练假把式。咱们用Python做个简单的仿真,看看变换到底对不对。
import numpy as np
import matplotlib.pyplot as plt
# 生成三相电流(120度相位差)
t = np.linspace(0, 0.02, 1000)
f = 50 # 频率50Hz
Ia = 10 * np.sin(2 * np.pi * f * t)
Ib = 10 * np.sin(2 * np.pi * f * t - 2*np.pi/3)
Ic = 10 * np.sin(2 * np.pi * f * t + 2*np.pi/3)
# Clark变换(等幅值)
Ialpha = Ia
Ibeta = (Ia + 2*Ib) / np.sqrt(3)
# 验证:Ialpha^2 + Ibeta^2 应该等于 1.5 * Ia^2(等幅值下)
amplitude_check = np.sqrt(Ialpha**2 + Ibeta**2)
print(f"Clark变换后幅值: {np.max(amplitude_check):.2f}") # 应该接近10
# Park变换(假设转子匀速旋转)
theta = 2 * np.pi * f * t # 电角度与电流同步
Id = Ialpha * np.cos(theta) + Ibeta * np.sin(theta)
Iq = -Ialpha * np.sin(theta) + Ibeta * np.cos(theta)
print(f"Id均值: {np.mean(Id):.2f}") # 应该接近0(纯正弦电流)
print(f"Iq均值: {np.mean(Iq):.2f}") # 应该接近10(幅值)
# 画图验证
plt.figure(figsize=(10, 6))
plt.subplot(3,1,1)
plt.plot(t*1000, Ia, label='Ia')
plt.plot(t*1000, Ib, label='Ib')
plt.plot(t*1000, Ic, label='Ic')
plt.ylabel('电流 (A)')
plt.title('三相电流')
plt.legend()
plt.grid(True)
plt.subplot(3,1,2)
plt.plot(t*1000, Ialpha, label='Iα')
plt.plot(t*1000, Ibeta, label='Iβ')
plt.ylabel('电流 (A)')
plt.title('Clark变换后 - αβ坐标系')
plt.legend()
plt.grid(True)
plt.subplot(3,1,3)
plt.plot(t*1000, Id, label='Id')
plt.plot(t*1000, Iq, label='Iq')
plt.xlabel('时间 (ms)')
plt.ylabel('电流 (A)')
plt.title('Park变换后 - dq坐标系')
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()
运行这段代码,你会看到:
- 三相电流是三个相差120度的正弦波
- Clark变换后,αβ坐标系下还是正弦波,但只有两个分量
- Park变换后,dq坐标系下变成了直流量——Id接近0,Iq接近幅值10A
关键结论: 当转子电角度θ与电流频率同步时,Park变换能把交流量变成直流量。这就是FOC能实现精确控制的原因——我们可以用PI控制器去控制直流量的Id和Iq,从而独立控制磁通和转矩。
3.5 实际工程中的注意事项
| 项目 | 说明 |
|---|---|
| 变换系数 | 等幅值变换(系数1) vs 等功率变换(系数√(2/3))。我推荐等幅值,PI参数更直观。 |
| 角度精度 | Park变换对θ的精度很敏感。角度误差1度,转矩误差约1.7%。无感FOC中,观测器的角度精度至少要达到0.5度以内。 |
| 零序分量 | 虽然理论上I0=0,但实际采样总有误差。建议在代码里计算I0,作为故障诊断的依据。 |
| 浮点运算 | MCU做三角函数和开方运算比较耗时。建议用查表法或CORDIC算法加速。我一般用预计算的正余弦表,精度0.1度,查表时间不到1us。 |
我的习惯: 在代码里把Clark和Park变换写成独立的函数,输入输出都用结构体。这样调试时可以直接打印αβ和dq的值,对照仿真结果验证。另外,记得在初始化时把角度归零,否则第一次变换出来的值可能是错的。
好了,Clark和Park变换就讲到这里。说白了,就是两次坐标旋转——先把三相掰成两相,再把静止的掰成旋转的。下一章咱们聊聊怎么用这些变换搭出完整的FOC电流环。