3、编码器零位标定:增量式编码器零位寻找、绝对式编码器零位读取、编码器安装偏差补偿
编码器零位标定,说白了就是让电机控制器知道「转子现在转到哪儿了」。这件事做不好,后面的电流环、速度环、位置环全是空中楼阁。我见过不少工程师在调试现场折腾一整天,最后发现是编码器零位偏了几度——嗯,这种坑踩过一次就忘不了。
这一章我们分三块来讲:增量式怎么找零位、绝对式怎么读零位、以及安装偏差怎么补偿。每种编码器脾气不一样,方法自然也不同。
3.1 增量式编码器零位寻找
增量式编码器本身不记忆位置。每次上电,控制器都不知道转子在哪儿。所以必须有一个「找零位」的过程。
我个人习惯把增量式编码器的零位寻找分成两种场景:有 Z 信号的和没有 Z 信号的。
3.1.1 利用 Z 信号(索引脉冲)
Z 信号是编码器每转一圈发出的一个脉冲。它对应编码器内部的一个固定机械位置。你想想看,只要找到这个脉冲,再结合 UVW 换相信号,就能确定电气零位。
具体步骤是这样的:
- 上电初始——控制器读取 UVW 信号,确定一个 60° 电气角的粗范围。
- 缓慢旋转——电机以极低速度(建议 10-30 rpm)朝一个方向转动。
- 捕获 Z 信号——当 Z 脉冲到来时,记录当前 UVW 状态和计数器值。
- 计算偏移——根据 UVW 状态与 Z 信号的相对位置,算出电气零位对应的编码器计数值。
- 写入参数——将这个偏移量存入非易失存储器,下次上电直接加载。
3.1.2 无 Z 信号时的替代方案
有些低成本的增量式编码器没有 Z 信号。怎么办?我曾在某款风机驱动器上遇到过这种情况。当时用了「电流注入法」来解决。
原理很简单:给电机通一个固定的 d 轴电流(Id),让转子自动转到与磁场对齐的位置。这个位置就是电气零位。
// 伪代码示例:电流注入法找零位
void find_zero_by_current_injection() {
// 1. 设置 Id = 额定电流的 30%,Iq = 0
set_current_reference(0.3 * I_rated, 0);
// 2. 等待转子稳定(通常 500ms - 2s)
delay(1000);
// 3. 读取当前编码器计数值
uint32_t raw_count = read_encoder();
// 4. 这个计数值就是电气零位
zero_offset = raw_count;
// 5. 保存到 EEPROM
save_to_nvm(zero_offset);
}
3.2 绝对式编码器零位读取
绝对式编码器就省心多了。它上电就能给出绝对位置。但省心不代表没坑——不同协议、不同分辨率、单圈还是多圈,处理方式都不一样。
3.2.1 单圈绝对式编码器
单圈编码器每圈有唯一的位置码。上电后直接读取数据,就能知道转子在 0-360° 机械角内的具体位置。
关键参数对照表:
| 分辨率(位) | 每圈脉冲数 | 电气角精度 | 适用场景 |
|---|---|---|---|
| 12 位 | 4096 | 0.088° | 通用伺服 |
| 14 位 | 16384 | 0.022° | 精密定位 |
| 17 位 | 131072 | 0.0027° | 高端数控 |
读取流程其实不复杂:
- 上电后等待编码器通信稳定(SSI/BiSS/EnDat 协议都需要几十微秒的建立时间)。
- 发送读取命令,获取原始位置数据。
- 根据极对数换算成电气角度:
θ_electrical = (θ_mechanical × 极对数) % 360°。 - 如果编码器安装时已经对齐了机械零位,这个值就是电气零位。
3.2.2 多圈绝对式编码器
多圈编码器内部有机械齿轮或者电子计数器,可以记录旋转圈数。上电后不仅能知道当前角度,还能知道转了多少圈。
这里有个容易忽略的问题:多圈计数器的溢出。我记得在某次项目中,客户反馈说设备运行一段时间后位置突然跳变——查了半天,发现是多圈编码器的 12 位计数器溢出了(最大 4096 圈),而控制器没有做溢出处理。
处理多圈数据时,我建议这样做:
- 读取时同时获取「圈数」和「圈内位置」两个字段。
- 在控制器内部维护一个 32 位或 64 位的扩展计数器。
- 每次读取后做差分校验,防止通信错误导致跳变。
- 零位标定时,记录的是「圈数 + 圈内位置」的组合值。
3.3 编码器安装偏差补偿
理论很丰满,现实很骨感。编码器装到电机上,总会有偏差。机械加工公差、安装时的对位误差、联轴器的弹性变形——这些都会导致编码器零位和电气零位对不上。
偏差补偿说白了就是:测出偏差量,然后在软件里把这个偏差减掉。
3.3.1 偏差来源分析
| 偏差类型 | 典型值 | 影响 | 补偿方式 |
|---|---|---|---|
| 编码器安装角度偏差 | ±1° ~ ±5° 机械角 | 转矩波动、效率下降 | 软件偏移量 |
| 联轴器扭转弹性变形 | ±0.1° ~ ±0.5° | 高频抖动 | 刚性联轴器或补偿表 |
| 磁极位置检测偏差 | ±3° ~ ±10° 电气角 | 启动失败、反转 | 重新标定 |
3.3.2 软件补偿方法
我个人最常用的方法是「反电动势过零法」。这个方法不需要额外硬件,只需要用示波器或者 ADC 采样电机相电压。
操作步骤:
- 让电机以恒定速度空转(建议 100-300 rpm)。
- 用示波器测量任意两相之间的反电动势波形。
- 找到反电动势过零点——这个点对应电气零位。
- 同时读取编码器位置值。
- 两者的差值就是安装偏差。
// 偏差补偿计算示例
float calculate_offset_compensation() {
// 反电动势过零时的编码器读数
uint32_t encoder_at_bemf_zero = 1024;
// 理论上的电气零位编码器值(假设编码器每圈 4096 线)
uint32_t theoretical_zero = 0;
// 偏差量(以编码器线数为单位)
int32_t offset = encoder_at_bemf_zero - theoretical_zero;
// 转换为电气角度(假设电机极对数为 4)
float offset_degree = (float)offset / 4096.0f * 360.0f / 4.0f;
return offset_degree;
}
3.3.3 补偿值验证
补偿值写进去之后,怎么验证对不对?我一般做两个测试:
- 静态测试:给电机通一个固定的 d 轴电流,转子应该停在某个固定位置。用编码器读这个位置,看是否与理论零位一致。
- 动态测试:让电机匀速旋转,用示波器观察电流波形。如果 Iq 波形平坦、没有明显的 2 倍频或 6 倍频波动,说明补偿到位了。
好了,编码器零位标定的核心内容就这些。增量式要会找 Z 信号、绝对式要会读数据、安装偏差要会测会补。这三件事做好了,你的伺服系统就有了一个可靠的起点。