旋转编码器的使用
什么是旋转编码器
它通过光电转换或其它方式,将旋转轴的角位移、角速度等机械量转换成相应的电脉冲或数字量输出。通俗来讲就是我们可以通过判别旋转编码器的A、B输出信号的相位差来去获取此时编码器旋转方向。
如何编程
这里仅分享我个人的思路,如上图所示 我们可以发现当旋转的方向不同的时候 输出的波形也是不一样的,所以我们可以通过连续收集几个不同的波形转化成对应的数组形式存储起来再来与标准的输出表格进行对比,这样我们就能得到左旋或者右旋。
获取对应数组
这里虽然我们可以通过阅读数据手册 来得到对应的波形 但是这里还是建议各位亲自去试试 这样印象也更加深刻,理解起来也更加容易。这里我们选取四段数据,因为后面都是重复的,首先来看到A向的第前四段 对应的是{1 1 0 0} 、{1 0 0 1} 、{0 0 1 1} 、{0 1 1 0};同理B向对应的是{1 0 0 1}、{0 0 1 1}、{0 1 1 0}、 {1 1 0 0};此上 我们就得到了标准的逆时针输出的4个点(A、B各四个),同理顺时针也是一样的。但是这里我选择将他们翻转一下,因为我们在接收信号的时候是从它后端去获取的所以反向一下更好处理。OK,一下是我得到的四个点位。
u8 g_RA_Clockwise_Arrary[4] = {0x03,0x09,0x0C,0x06};
u8 g_RB_Clockwise_Arrary[4] = {0x06,0x03,0x09,0x0C};
u8 g_RA_Anticlockwise_Arrary[4] = {0x09,0x0C,0x06,0x03};
u8 g_RB_Anticlockwise_Arrary[4] = {0x0C,0x06,0x03,0x09};
定时器获取IO口数据
我看有的博主是使用中断进行操作的,我这里使用的是定时器,效果也还行,这里我的周期给的是1ms一次已经足够使用了。以下是具体代码。
void Encoder_Updata(void)
{
static u16 Clear_Rec = 0;
static u32 Temp_Arrary_Num = 0;
static u8 filter = 0;
static u16 Time = 0;
/*快旋标志*/
Time++;
if(Time == 300)
{
if(g_Set_Cnt > 3)
{
g_High_Speed = 1;
}
g_Set_Cnt = 0;
Time = 0;
}
Clear_Rec++;
/*当状态改变时 进行判别*/
if((g_RA != RA || g_RB != RB) && (!g_Trans_Over))
{
g_Clear_Flag = 1;
filter++;
g_RA = RA;
g_RB = RB;
Clear_Rec = 0;
/*前两位数据过滤*/
if(filter > 2)
{
if(Temp_Arrary_Num < 4)
{
{
g_RA_Arrary |= (g_RA<<Temp_Arrary_Num);
g_RB_Arrary |= (g_RB<<Temp_Arrary_Num);
}
}
else
{
/*采集到一组有效位后*/
g_Set_Cnt++;
g_Trans_Over = 1;
g_RA_Arrary >>= 1;
g_RA_Arrary |= (g_RA << 3);
g_RB_Arrary >>= 1;
g_RB_Arrary |= (g_RB << 3);
}
Temp_Arrary_Num++;
if(Temp_Arrary_Num == 4)
{
g_Trans_Over = 1;
}
}
}
/*定时无操作清楚*/
if(Clear_Rec > Clear_Time)
{
g_High_Speed = 0;
g_Clear_Flag = 0;
Temp_Arrary_Num = 0;
g_RA_Arrary = 0x0;
g_RB_Arrary = 0x0;
filter = 0;
}
}
以上这段代码是放到中断去进行执行的,这样我们就可以不断获取数据。
主循环判别方位
在获取到有效数据之后 我们在主循环不断进行判断,如对比到正确的数值就返回一个标志告诉单片机此时编码器的状态。
Encoder_SatteType Encoder_Run(void)
{
if(g_Trans_Over)
{
g_Trans_Over = 0;
if((g_RA_Arrary == g_RA_Clockwise_Arrary[0] && g_RB_Arrary == g_RB_Clockwise_Arrary[0]) || \
(g_RA_Arrary == g_RA_Clockwise_Arrary[1] && g_RB_Arrary == g_RB_Clockwise_Arrary[1]) || \
(g_RA_Arrary == g_RA_Clockwise_Arrary[2] && g_RB_Arrary == g_RB_Clockwise_Arrary[2]) || \
(g_RA_Arrary == g_RA_Clockwise_Arrary[3] && g_RB_Arrary == g_RB_Clockwise_Arrary[3]))
{
if(g_High_Speed)
{
g_High_Speed = 0;
g_Set_Cnt = 0;
return Encoder_Clockwise_High_STATE;
}
else
return Encoder_Clockwise_STATE;
}
else if((g_RA_Arrary == g_RA_Anticlockwise_Arrary[0] && g_RB_Arrary == g_RB_Anticlockwise_Arrary[0]) || \
(g_RA_Arrary == g_RA_Anticlockwise_Arrary[1] && g_RB_Arrary == g_RB_Anticlockwise_Arrary[1]) || \
(g_RA_Arrary == g_RA_Anticlockwise_Arrary[2] && g_RB_Arrary == g_RB_Anticlockwise_Arrary[2]) || \
(g_RA_Arrary == g_RA_Anticlockwise_Arrary[3] && g_RB_Arrary == g_RB_Anticlockwise_Arrary[3]))
{
if(g_High_Speed)
{
g_High_Speed = 0;
g_Set_Cnt = 0;
return Encoder_Anticlockwise_High_STATE;
}
else
return Encoder_Anticlockwise_STATE;
}
else
{
return Encoder_IDLE_STATE;
}
}
else
{
return Encoder_IDLE_STATE;
}
}
该段代码放入主循环当中进行判别,我这里因为项目需要还加了快旋的标志判别。思路也很简单,就是在一定时间内获取的有效数据(旋转次数)超过设置的阈值就判定为快旋。
总结
以上就是大致的使用过程,在调试过程中可以一步一步进行查看,最后再组合起来去获取一个想要的效果。