坐标变换代码实现

← 返回 FOC MOC | ← 返回主页


一、坐标变换在FOC中的核心地位

在磁场定向控制(FOC)中,坐标变换是连接三相交流系统与直流控制系统的数学桥梁。通过坐标变换,我们可以将复杂的时变交流量转换为易于控制的直流量。

变换流程总览

三相静止坐标系 (ABC) → 两相静止坐标系 (αβ) → 两相旋转坐标系 (dq) → 控制输出 → 逆变换

二、数学原理回顾

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

将三相电流(, , )转换为两相静止坐标系(α, β):

对于平衡系统(),常用简化形式:

2.2 Park变换 (静止→旋转)

将静止坐标系(α, β)转换为旋转坐标系(d, q),其中 是转子电角度:

i_d &= i_\alpha \cos\theta + i_\beta \sin\theta \\ i_q &= -i_\alpha \sin\theta + i_\beta \cos\theta \end{aligned}$$ ### 2.3 反Park变换 (旋转→静止) 将旋转坐标系(d, q)转换回静止坐标系(α, β): $$\begin{aligned} v_\alpha &= v_d \cos\theta - v_q \sin\theta \\ v_\beta &= v_d \sin\theta + v_q \cos\theta \end{aligned}$$ | 变换类型 | 输入 | 输出 | 关键参数 | 物理意义 | | --- | --- | --- | --- | --- | | Clarke变换 | $I_a$, $I_b$, $I_c$ | $I_\alpha$, $I_\beta$ | 无 | 三相→两相,减少变量 | | Park变换 | $I_\alpha$, $I_\beta$ | $I_d$, $I_q$ | 电角度 $\theta$ | 静止→旋转,交流变直流 | | 反Park变换 | $V_d$, $V_q$ | $V_\alpha$, $V_\beta$ | 电角度 $\theta$ | 旋转→静止,准备PWM调制 | ## 三、C语言代码实现 **注意:**以下代码针对嵌入式系统优化,使用浮点运算。在实际嵌入式应用中,可能需要使用定点数或Q格式以提高效率。 ### 3.1 数据结构定义 ```c #include <math.h> /* 三相电流结构体 */ typedef struct { float a; /* A相电流 */ float b; /* B相电流 */ float c; /* C相电流 */ } ThreePhaseCurrent; /* 两相静止坐标系(αβ)结构体 */ typedef struct { float alpha; /* α轴分量 */ float beta; /* β轴分量 */ } AlphaBeta; /* 两相旋转坐标系(dq)结构体 */ typedef struct { float d; /* d轴分量(励磁分量) */ float q; /* q轴分量(转矩分量) */ } DQ; ``` ### 3.2 Clarke变换实现 ```c /** * Clarke变换:三相静止ABC → 两相静止αβ * @param i_abc 三相电流输入 * @return 两相静止坐标系输出 */ AlphaBeta clarke_transform(ThreePhaseCurrent i_abc) { AlphaBeta i_alphabeta; /* 标准Clarke变换公式 */ i_alphabeta.alpha = i_abc.a; /* Iα = Ia */ /* Iβ = (Ia + 2Ib) / √3 */ i_alphabeta.beta = (i_abc.a + 2.0f * i_abc.b) * (1.0f / sqrtf(3.0f)); /* 注:假设三相平衡,即 Ia + Ib + Ic = 0,因此 Ic = -Ia - Ib */ return i_alphabeta; } /** * Clarke变换(简化版,假设三相平衡) * 更高效的实现,减少计算量 */ AlphaBeta clarke_transform_simple(ThreePhaseCurrent i_abc) { AlphaBeta i_alphabeta; i_alphabeta.alpha = i_abc.a; /* 使用预计算的1/√3常量,避免重复计算 */ const float ONE_BY_SQRT3 = 0.57735026919f; /* 1/√3 ≈ 0.57735 */ i_alphabeta.beta = (i_abc.a + 2.0f * i_abc.b) * ONE_BY_SQRT3; return i_alphabeta; } ``` ### 3.3 Park变换实现 ```c /** * Park变换:两相静止αβ → 两相旋转dq * @param i_alphabeta 两相静止输入 * @param theta 电角度(弧度) * @return 两相旋转坐标系输出 */ DQ park_transform(AlphaBeta i_alphabeta, float theta) { DQ i_dq; float cos_theta, sin_theta; /* 预计算三角函数值 */ cos_theta = cosf(theta); sin_theta = sinf(theta); /* Park变换公式 */ i_dq.d = i_alphabeta.alpha * cos_theta + i_alphabeta.beta * sin_theta; i_dq.q = -i_alphabeta.alpha * sin_theta + i_alphabeta.beta * cos_theta; return i_dq; } /** * Park变换(查表法优化) * 适用于资源受限的嵌入式系统,避免实时三角函数计算 */ DQ park_transform_lut(AlphaBeta i_alphabeta, float theta, const float* sin_table, const float* cos_table, int table_size) { DQ i_dq; int index; float cos_theta, sin_theta; /* 将角度映射到查表索引 */ index = (int)(theta * table_size / (2 * M_PI)) % table_size; /* 获取三角函数值 */ cos_theta = cos_table[index]; sin_theta = sin_table[index]; /* Park变换 */ i_dq.d = i_alphabeta.alpha * cos_theta + i_alphabeta.beta * sin_theta; i_dq.q = -i_alphabeta.alpha * sin_theta + i_alphabeta.beta * cos_theta; return i_dq; } ``` ### 3.4 反Park变换实现 ```c /** * 反Park变换:两相旋转dq → 两相静止αβ * @param v_dq 两相旋转输入(控制电压) * @param theta 电角度(弧度) * @return 两相静止坐标系输出 */ AlphaBeta inverse_park_transform(DQ v_dq, float theta) { AlphaBeta v_alphabeta; float cos_theta, sin_theta; /* 预计算三角函数值 */ cos_theta = cosf(theta); sin_theta = sinf(theta); /* 反Park变换公式 */ v_alphabeta.alpha = v_dq.d * cos_theta - v_dq.q * sin_theta; v_alphabeta.beta = v_dq.d * sin_theta + v_dq.q * cos_theta; return v_alphabeta; } ``` ### 3.5 完整变换示例 ```c /** * 完整的FOC坐标变换流程示例 */ void foc_coordinate_transform_example(void) { ThreePhaseCurrent i_abc; AlphaBeta i_alphabeta, v_alphabeta; DQ i_dq, v_dq; float theta; /* 电角度(弧度) */ float speed_ref; /* 速度参考值 */ float current_ref; /* 电流参考值 */ /* 1. 读取三相电流(实际从ADC获取) */ i_abc.a = 1.0f; /* 示例值:A相电流 */ i_abc.b = -0.5f; /* 示例值:B相电流 */ i_abc.c = -0.5f; /* 示例值:C相电流(由平衡条件得出) */ /* 2. 读取电角度(实际从编码器获取) */ theta = 0.7854f; /* 示例值:π/4 = 45° */ /* 3. Clarke变换:ABC → αβ */ i_alphabeta = clarke_transform(i_abc); /* 4. Park变换:αβ → dq */ i_dq = park_transform(i_alphabeta, theta); /* 5. FOC控制算法(简化示例) */ speed_ref = 100.0f; /* 目标转速 */ current_ref = 2.0f; /* 目标电流 */ /* 简单的PI控制器(实际应用需要完整的PI控制器) */ v_dq.d = 0.0f; /* 通常控制Id=0(最大转矩控制) */ v_dq.q = current_ref; /* 根据速度误差计算Vq */ /* 6. 反Park变换:dq → αβ */ v_alphabeta = inverse_park_transform(v_dq, theta); /* 7. 输出结果(实际会送入SVPWM模块) */ printf("Clarke变换结果: Iα=%.3f, Iβ=%.3f\n", i_alphabeta.alpha, i_alphabeta.beta); printf("Park变换结果: Id=%.3f, Iq=%.3f\n", i_dq.d, i_dq.q); printf("反Park变换结果: Vα=%.3f, Vβ=%.3f\n", v_alphabeta.alpha, v_alphabeta.beta); } ``` ## 四、Python代码实现 **注意:**Python实现更适合仿真、算法验证和教学演示,具有更好的可读性。 ### 4.1 面向对象的实现 ```c import numpy as np import math class CoordinateTransformer: """坐标变换器类""" def __init__(self): """初始化变换器""" self.ONE_BY_SQRT3 = 1.0 / math.sqrt(3) # 预计算常量 def clarke_transform(self, ia, ib, ic=None): """ Clarke变换 Args: ia, ib, ic: 三相电流 ic: 如果为None,则假设三相平衡(ia+ib+ic=0) Returns: i_alpha, i_beta: 两相静止坐标系电流 """ i_alpha = ia if ic is None: # 假设三相平衡,计算ic ic = -ia - ib # Clarke变换公式 i_beta = self.ONE_BY_SQRT3 * ia + 2 * self.ONE_BY_SQRT3 * ib return i_alpha, i_beta def park_transform(self, i_alpha, i_beta, theta): """ Park变换 Args: i_alpha, i_beta: 两相静止坐标系电流 theta: 电角度(弧度) Returns: i_d, i_q: 两相旋转坐标系电流 """ cos_theta = math.cos(theta) sin_theta = math.sin(theta) # Park变换公式 i_d = i_alpha * cos_theta + i_beta * sin_theta i_q = -i_alpha * sin_theta + i_beta * cos_theta return i_d, i_q def inverse_park_transform(self, v_d, v_q, theta): """ 反Park变换 Args: v_d, v_q: 两相旋转坐标系电压 theta: 电角度(弧度) Returns: v_alpha, v_beta: 两相静止坐标系电压 """ cos_theta = math.cos(theta) sin_theta = math.sin(theta) # 反Park变换公式 v_alpha = v_d * cos_theta - v_q * sin_theta v_beta = v_d * sin_theta + v_q * cos_theta return v_alpha, v_beta def foc_full_transform(self, ia, ib, theta, v_d_ref=0, v_q_ref=1): """ 完整的FOC坐标变换流程 Args: ia, ib: 两相电流(假设三相平衡) theta: 电角度 v_d_ref, v_q_ref: dq轴参考电压 Returns: 所有变换结果 """ # Clarke变换 i_alpha, i_beta = self.clarke_transform(ia, ib) # Park变换 i_d, i_q = self.park_transform(i_alpha, i_beta, theta) # 反Park变换(使用参考电压) v_alpha, v_beta = self.inverse_park_transform(v_d_ref, v_q_ref, theta) return { 'i_alpha': i_alpha, 'i_beta': i_beta, 'i_d': i_d, 'i_q': i_q, 'v_alpha': v_alpha, 'v_beta': v_beta } # 使用示例 if __name__ == "__main__": # 创建变换器实例 transformer = CoordinateTransformer() # 测试数据 ia = 1.0 # A相电流 ib = -0.5 # B相电流 theta = math.pi / 4 # 45度 # 执行完整变换 results = transformer.foc_full_transform(ia, ib, theta) # 打印结果 print("=== FOC坐标变换结果 ===") print(f"输入: Ia={ia}, Ib={ib}, θ={theta:.3f} rad ({theta*180/math.pi:.1f}°)") print(f"Clarke变换: Iα={results['i_alpha']:.3f}, Iβ={results['i_beta']:.3f}") print(f"Park变换: Id={results['i_d']:.3f}, Iq={results['i_q']:.3f}") print(f"反Park变换: Vα={results['v_alpha']:.3f}, Vβ={results['v_beta']:.3f}") ``` ### 4.2 向量化实现(适合批量处理) ```c import numpy as np class VectorizedTransformer: """向量化坐标变换器,适合批量数据处理""" def __init__(self): self.ONE_BY_SQRT3 = 1.0 / np.sqrt(3) def clarke_transform_batch(self, ia_array, ib_array): """ 批量Clarke变换 Args: ia_array, ib_array: 电流数组 Returns: i_alpha_array, i_beta_array """ i_alpha_array = ia_array i_beta_array = self.ONE_BY_SQRT3 * ia_array + 2 * self.ONE_BY_SQRT3 * ib_array return i_alpha_array, i_beta_array def park_transform_batch(self, i_alpha_array, i_beta_array, theta_array): """ 批量Park变换 Args: i_alpha_array, i_beta_array: αβ电流数组 theta_array: 角度数组 Returns: i_d_array, i_q_array """ cos_theta = np.cos(theta_array) sin_theta = np.sin(theta_array) i_d_array = i_alpha_array * cos_theta + i_beta_array * sin_theta i_q_array = -i_alpha_array * sin_theta + i_beta_array * cos_theta return i_d_array, i_q_array def inverse_park_transform_batch(self, v_d_array, v_q_array, theta_array): """ 批量反Park变换 Args: v_d_array, v_q_array: dq电压数组 theta_array: 角度数组 Returns: v_alpha_array, v_beta_array """ cos_theta = np.cos(theta_array) sin_theta = np.sin(theta_array) v_alpha_array = v_d_array * cos_theta - v_q_array * sin_theta v_beta_array = v_d_array * sin_theta + v_q_array * cos_theta return v_alpha_array, v_beta_array # 批量处理示例 def batch_processing_example(): """批量处理示例""" transformer = VectorizedTransformer() # 生成测试数据(100个点) n_samples = 100 time = np.linspace(0, 0.1, n_samples) # 0.1秒内的100个点 # 生成三相电流(正弦波,相位差120°) freq = 50 # 50Hz ia_array = np.sin(2 * np.pi * freq * time) ib_array = np.sin(2 * np.pi * freq * time - 2 * np.pi / 3) # 生成角度(模拟电机旋转) rotor_speed = 3000 # RPM theta_array = 2 * np.pi * rotor_speed / 60 * time # 机械角度 # 批量变换 i_alpha_array, i_beta_array = transformer.clarke_transform_batch(ia_array, ib_array) i_d_array, i_q_array = transformer.park_transform_batch(i_alpha_array, i_beta_array, theta_array) # 控制参考(简化) v_d_ref_array = np.zeros(n_samples) v_q_ref_array = np.ones(n_samples) * 0.5 # 反变换 v_alpha_array, v_beta_array = transformer.inverse_park_transform_batch( v_d_ref_array, v_q_ref_array, theta_array ) print(f"批量处理完成,共{n_samples}个数据点") print(f"Iα均值: {np.mean(i_alpha_array):.3f}, Iβ均值: {np.mean(i_beta_array):.3f}") print(f"Id均值: {np.mean(i_d_array):.3f}, Iq均值: {np.mean(i_q_array):.3f}") return { 'time': time, 'i_d': i_d_array, 'i_q': i_q_array, 'v_alpha': v_alpha_array, 'v_beta': v_beta_array } ``` ## 五、优化技巧与注意事项 ### 5.1 嵌入式系统优化 - 查表法(LUT) :预计算sin/cos值,避免实时计算 - 定点数运算 :使用Q格式代替浮点数,提高速度 - 常量预计算 :如 $1/\sqrt{3}$ 等常量预先计算好 - 避免除法 :用乘法代替除法运算 ### 5.2 数值稳定性 - 角度归一化:确保 $\theta$ 在 $[0, 2\pi)$ 范围内 - 防止溢出:合理选择数据范围和精度 - 滤波处理:对变换结果进行低通滤波 ### 5.3 实际应用考虑 | 考虑因素 | C语言实现 | Python实现 | 建议 | | --- | --- | --- | --- | | 实时性要求 | 高(微秒级) | 低(毫秒级) | 嵌入式用C,仿真用Python | | 计算精度 | 单精度/定点数 | 双精度浮点 | 根据需求选择精度 | | 内存占用 | 小(KB级) | 大(MB级) | 嵌入式注意内存优化 | | 开发效率 | 较低 | 较高 | 原型用Python,产品用C | ### 软件架构建议