3. 位置数据处理:编码器计数与角度换算、零点校准与寻零逻辑、多圈位置累加与防溢出
各位同学,咱们今天聊点实在的。位置环要跑得准,第一步就是得把编码器的原始数据伺候好。说白了,你算法写得再漂亮,位置数据一塌糊涂,电机照样抖成筛子。我这些年踩过的坑,十有八九都出在数据处理的细节上。
3.1 编码器计数与角度换算
编码器输出的原始值,通常是一个脉冲计数值。比如增量式编码器,每转一圈输出 N 个脉冲。那问题来了:怎么把这个计数值变成我们控制算法里用的角度?
公式其实很简单:
角度(度) = (编码器计数值 / 单圈总脉冲数) * 360
但这里有个坑——分辨率。我见过有人直接用整型除法,结果角度永远是 0。你想想看,计数值 100,单圈 1024 脉冲,100/1024 在整型里就是 0。所以一定要用浮点运算,或者先乘后除。
核心要点:
- 单圈脉冲数 = 编码器物理线数 × 4(如果是正交解码)
- 角度范围:0 ~ 360 度,或者 -180 ~ 180 度,看你的习惯
- 数据类型:建议用 float,精度够用,STM32 的 FPU 跑起来也不慢
我个人习惯把角度归一化到 0~360 度。为什么?因为后面做位置环 PID 时,误差计算更直观。你想想,目标 350 度,当前 10 度,误差是 -20 度还是 340 度?归一化之后,我们就能用简单的取模运算搞定。
3.2 零点校准与寻零逻辑
编码器上电时,位置是随机的。你得告诉系统:哪里是机械零点。
零点校准有两种常见做法:
| 方法 | 原理 | 适用场景 |
|---|---|---|
| 硬件限位开关 | 电机撞到限位后,记录当前位置为零点 | 有物理限位的系统,如 3D 打印机 |
| 软件寻零(Z 信号) | 编码器每圈输出一个 Z 脉冲,检测到后清零 | 增量式编码器,需要绝对参考点 |
| 上电自动校准 | 电机主动转动到预设位置,记录零点 | 无传感器或低成本方案 |
我在项目中遇到过一个问题:用 Z 信号寻零时,电机刚上电就高速旋转,结果 Z 脉冲太快没抓到。后来我加了个逻辑——先低速寻零,再切回正常速度。嗯,这里要注意,寻零速度不能太快,否则容易丢脉冲。
我的经验:
寻零逻辑最好做成状态机。比如:
- 状态1:等待寻零指令
- 状态2:低速正向旋转,等待 Z 信号
- 状态3:检测到 Z 信号,记录位置,停止
- 状态4:回退一小段,消除机械间隙
- 状态5:确认零点,进入正常运行
这样做的好处是——每个步骤都可控,出了问题也好排查。
3.3 多圈位置累加与防溢出
单圈角度只能表示 0~360 度。但很多应用需要多圈位置,比如机械臂、转台。这时候就要做多圈累加。
累加逻辑其实不复杂:
// 伪代码示例
int32_t multi_turn_position = 0;
float last_angle = 0.0f;
void update_position(float current_angle) {
float delta = current_angle - last_angle;
// 处理过零点
if (delta > 180.0f) {
delta -= 360.0f;
} else if (delta < -180.0f) {
delta += 360.0f;
}
multi_turn_position += (int32_t)(delta * 1000); // 放大1000倍,保留精度
last_angle = current_angle;
}
这段代码里,最关键的是过零点处理。你想想,从 359 度变到 1 度,实际只转了 2 度,但如果不处理,delta 就是 -358 度,位置直接跳变。所以我们要判断:如果 delta 绝对值大于 180 度,说明它跨过了零点,需要修正。
防溢出警告:
多圈位置累加用的是 int32_t,最大约 21 亿。如果你放大 1000 倍,那就是 21 亿 / 1000 = 210 万圈。听起来很多,但如果你电机转速 3000 RPM,跑 700 分钟就溢出了。
我曾经在一个自动化产线上吃过这个亏——设备连续运行三天后,位置突然跳变,差点把机械臂撞坏。从那以后,我养成了两个习惯:
- 定期做位置快照,保存到非易失存储器
- 溢出时做饱和处理,而不是直接归零
防溢出的另一种思路是使用浮点数累加。float 的精度虽然有限,但范围大得多。不过要注意,浮点数累加久了会有累积误差。我一般会在每次寻零后重置累加值,这样误差就不会累积。
3.4 本章知识体系
下面这张图,是我自己总结的位置数据处理流程。你看一眼,基本就明白整个链路了。
这张图把整个流程串起来了。从编码器原始数据开始,经过角度换算、零点校准、多圈累加,最后输出给位置环。中间还有防溢出和寻零逻辑两个分支。你写代码的时候,就按这个顺序来,基本不会乱。
一个小技巧:
调试阶段,我习惯把每一步的中间结果都打印出来。比如编码器原始值、换算后的角度、多圈累加值。这样一旦位置出问题,一眼就能看出是哪一步算错了。别嫌麻烦,这能省你半天时间。
好了,位置数据处理这块就聊到这儿。记住一句话:数据不准,算法白费。把编码器伺候好了,后面的位置环才能跑得稳。
公众号:蓝海资料掘金营,微信deep3321