文章目录
- 1.正交编码器
- 1.1 参数特性
- 1.2 应用范围
- 2.正交编码器使用
- 2.1 溢出问题
- 2.2 中断模式
- 2.3 循环模式
- 延伸
1.正交编码器
正交编码器一般指的是增量式光栅(磁栅)编码器,通常有三路输出信号,A相、B相、Z相,俗称ABZ编码器。所谓正交,即是A相信号和B相信号相位相差90°,根据AB相位的前后,即可判断旋转机构正转还是反转。Z相信号,是旋转一圈后输出的信号,也称为零点信号。
1.1 参数特性
- 线数,旋转一圈的脉冲数,如1024线、2500线、10000线
- 工作电压,3.3V、5V
- 差分信号,工业应用,为了增加抗干扰能力,ABZ信号通常以差分信号输出
- 无Z相信号,一些编码器无Z相信号
1.2 应用范围
- 与电机结合应用,组成伺服电机,直流电机、交流电机、步进电机等
- 转速测量
- 多媒体音量调节
- 鼠标滚轮
- 游戏手柄
2.正交编码器使用
- 使用GPIO模拟,适合低速场合,如鼠标滚轮、多媒体音量调节
- 专用编码器接口,基本上主流的MCU、MPU都支持,适合高速场合使用
一般情况下使用专门的编码器接口,即是支持正交计数的定时器,由CPU硬件上实现脉冲计数和方向判断,用户只需从定时器寄存器获取脉冲计数和方向,相比使用GPIO模拟效率和精度高。定时器接口还支持边缘采集,可以实现2倍频、4倍频信号;例如5000线编码器,通过4倍频后,单圈实现20000脉冲,最低识别精度为360/20000°。
2.1 溢出问题
正交编码器接口定时器计数,与定时器位数密切关联;通常定时器有8位、6位、32位;目前主流ARM处理定时器以16位为主,高端处理器支持32位。对于8位计数器,溢出大小为2^8=255;16位计数器溢出大小为2 ^16=65535;32位计数器溢出大小为2 ^32=4294967294。
以50000线编码为例,经过4倍频后,单圈为20000脉冲;如果是8位计数器,单圈则溢出78次;16位计数器,3圈后溢出。对于高速场景,是不允许的。
- 如果使能溢出中断,则中断频率过高,影响CPU其他任务
- 如果未使能中断,CPU运算能力需要在单圈溢出前获取计数值
以主流16位定时器为例,分别实现以上两个方式溢出处理。
2.2 中断模式
如果速度不高,或者中断频率容忍度在设计范围,不影响其他任务的正常执行,则可以开启溢出中断,增加一个圈数计算变量,实现起来是非常方便的。实现步骤如下:
- 初始正交编码器接口,复位计数值为0
- 重新溢出中断,正转时圈数值减1,反转时圈数加1
- 实际位置脉冲值=圈数编码器线数4+当前计数值(未满一圈)
伪代码
int64_t count = 0;
/* init encoder timer */
/* reset encoder timer count */
/* IRQ handler */
void irq_handler(void)
{
if (direct == CCW)
{
count--;
}
else
{
count++;
}
}
/* read real pos */
int64_t read_real_pos(void)
{
int64_t pos= 0;
temp = count*(2^16 + 1) + (int64_t)__HAL_TIM_GET_COUNTER(&timer);
return pos;
}
注意有符号数运算,初始值为0;正转时易于理解。对于反正:初始值计数为0,翻转值65530,产生溢出中断一次,实际值为-36636+65530=-6。
2.3 循环模式
对于高速场景,高频中断占用大量CPU资源,导致其他任务未能及时执行,这是不允许的。定时器计数溢出后归零,在未开启溢出中断时,用户无法感知溢出多少次。因此,我们只需保证处理周期内最多允许一次溢出,处理周期依赖于实际软件复杂度、编码器线数、最大转速。先上伪代码。
#define MAX_COUNT (50000*4)
#define TURN_COUNT (MAX_COUNT/2)
int64_t pos_fun(void)
{
static int64_t last_pos = 0;
int64_t temp_pos = 0;
int64_t real_pos = 0;
int64_t current_pos = timer_read_pos();
temp_pos = current_pos - last_pos;
if (temp_pos >= MAX_COUNT)
{
temp_pos -= TURN_COUNT;
}
else if (temp_pos < -MAX_COUNT)
{
temp_pos += TURN_COUNT;
}
last_pos = current_pos;
real_pos += temp_pos;
return real_pos;
}
实现原理:
MAX_COUNT
为单圈计数值TURN_COUNT
为一个计算临界值,通常取单圈数值的一半- 处理时,当前计数值与上一次值比较,如果差值大于TURN_COUNT ,说明发生反转溢出,则减去单圈值;如果差值小于-TURN_COUNT ,说明发生正转溢出,则加上单圈值
- 处理周期,取决于软件设计和最大转速,确保这个周期内最多发生一次溢出
延伸
实质上,该方式也适用于一些绝对式编码器场景;如单圈绝对式编码器,该类编码器以数字接口(SSI、CAN、BISS、并口)输出位置信息,最大支持记录一圈的绝对位置,超出单圈位置后归零。