4. 开环对齐法(编码器):原理讲解、操作步骤、代码实现(C语言)、验证方法
开环对齐法,说白了就是给电机定子通一个固定的直流电压矢量,让转子自己乖乖转到某个已知的电气角度位置。这时候你读到的编码器位置,就是零度电角度对应的机械位置。
我最早接触这个方法是在一个伺服项目上,当时编码器刚焊好,还没标定。我心想,这玩意儿转起来到底准不准?后来发现,开环对齐是最快、最直观的验证手段。你不需要复杂的观测器,也不需要转台,一根示波器、一个电源就能搞定。
4.1 原理讲解
原理其实很简单。你给电机通一个固定的电压矢量,比如让 U_d = 0,U_q = 一个很小的正电压。这时候定子磁场会指向 q 轴方向。转子是永磁体,它会被定子磁场拉着转,直到转子磁极和定子磁场方向对齐。
对齐之后,转子 d 轴就和定子 q 轴重合了。换句话说,此时电角度就是 90°(电气角度)。你读一下编码器的计数值,记下来。这个计数值对应的就是 90° 电角度。
核心思想: 开环给一个固定方向的电压矢量,让转子被动对齐到已知电角度位置,从而标定编码器零位。
为什么会这样?因为永磁同步电机的转矩公式是:
T_e = 1.5 * p * [ψ_f * i_q + (L_d - L_q) * i_d * i_q]
当 i_d = 0 时,转矩只和 i_q 有关。你给一个固定的 i_q,转子就会转到 q 轴方向。对齐后,转子 d 轴和定子 q 轴夹角为 0,电角度就是 90°。
嗯,这里要注意:你给的电压不能太大,否则转子会冲过头;也不能太小,否则摩擦力会吃掉转矩。我一般给额定电流的 5%~10%。
4.2 操作步骤
操作步骤我总结成 6 步,你照着做就行。
- 断电确认:确保电机和驱动器断电,编码器线缆连接正常。
- 上电初始化:给驱动器上电,初始化编码器,读取当前计数值。
- 开环给电压:在 dq 坐标系下,设置
V_d = 0,V_q = 一个很小的正电压(比如 0.5V~1V,视电机额定电压而定)。 - 等待对齐:转子会慢慢转动,直到停稳。这个过程通常需要 1~3 秒。
- 记录位置:转子停稳后,读取编码器计数值,记为
enc_offset。 - 断电释放:切断电压,转子恢复自由状态。
小技巧: 如果转子转起来有抖动,说明电压给得太大了。试着减小 V_q,或者加一个斜坡启动。我习惯用 0.2V 起步,慢慢往上加,直到转子平稳转动。
4.3 代码实现(C语言)
代码实现分两部分:开环对齐函数和编码器偏移量计算。我直接贴一个我项目里用过的片段。
// 开环对齐函数
// 参数:Vq_ref - q轴电压参考值(0.0 ~ 1.0,标幺值)
// 返回:编码器偏移量(计数值)
uint32_t open_loop_alignment(float Vq_ref)
{
uint32_t enc_offset = 0;
float Vd_ref = 0.0f;
float theta_elec = 0.0f; // 电角度,开环时我们直接给固定值
// 1. 初始化PWM和编码器
pwm_init();
encoder_init();
// 2. 设置电流环为开环模式(不使能电流PI)
current_loop_disable();
// 3. 给一个固定的电角度 90°(电气角度)
// 对应 dq 变换中的 theta = PI/2
theta_elec = PI / 2.0f;
// 4. 执行 Park 变换和 SVPWM
// 这里简化处理,直接调用底层接口
svpwm_set_voltage(Vd_ref, Vq_ref, theta_elec);
// 5. 等待转子对齐(延时 2 秒)
delay_ms(2000);
// 6. 读取编码器计数值
enc_offset = encoder_get_count();
// 7. 关闭PWM输出
pwm_stop();
return enc_offset;
}
// 编码器偏移量计算
// 注意:对齐时电角度为 90°,所以编码器偏移量需要减去 90° 对应的计数值
uint32_t calculate_encoder_offset(uint32_t raw_offset)
{
uint32_t enc_counts_per_rev = encoder_get_counts_per_rev();
uint32_t elec_degree_90_counts;
// 计算 90° 电气角度对应的编码器计数值
// 假设电机极对数为 pole_pairs
elec_degree_90_counts = (enc_counts_per_rev / (360 * pole_pairs)) * 90;
// 偏移量 = 原始读数 - 90° 对应的计数值
// 注意处理溢出
if (raw_offset >= elec_degree_90_counts)
{
return raw_offset - elec_degree_90_counts;
}
else
{
return enc_counts_per_rev - (elec_degree_90_counts - raw_offset);
}
}
注意: 开环对齐时,电流环必须处于开环状态。如果电流环还在闭环,它会试图调节电流,导致转子抖动。我曾经犯过这个错,折腾了半小时才发现是电流环没关掉。
4.4 验证方法
验证方法很简单:你用手转动转子,看看编码器读数和电角度是否对应。
具体做法:
- 用手缓慢转动转子一圈,同时用示波器观察编码器 A/B 相和电角度计算值。
- 如果对齐正确,电角度应该从 0° 到 360° 线性变化,且和编码器位置一一对应。
- 如果不对,你会看到电角度跳变或者非线性。
我一般还会做一个交叉验证:用另一个已知好的编码器或者磁编码器做对比。如果两个偏移量差在 1° 以内,就算通过。
下面这张图是开环对齐法的完整流程,我画了个 SVG 方便你理解。
验证通过后,你就可以把这个偏移量写进 EEPROM 或者 Flash,以后每次上电直接读取。这样编码器零位就标定好了。
我的经验: 开环对齐法虽然简单,但精度受限于负载和摩擦力。如果电机带负载,建议多测几次取平均值。我一般测 5 次,去掉最大最小值,然后取平均。这样偏移量误差能控制在 0.5° 以内。