电机控制方案
登录
直播中
李梅
7年用户
1318经验值
私信
关注
[问答]
单片机读取光栅编码器角度的方法是什么?
开启该帖子的消息推送
编码器
光电
增量式编码器工作原理是什么?
增量式编码器的结构是由哪些部分组成的?
光电旋转编码器使用方法是什么?
单片机
读取光栅编码器角度的方法是什么?
回帖
(1)
杨思
2021-6-30 16:01:44
增量式光栅编码器结构:
增量式编码器工作原理:
编码器码盘上刻有A、B窄缝,彼此错开1/4节距,使得A、B两相在转动过程中,输出的电信号相位错开90°。如下图所示:
网上程序错误解析:
程序算法是A/B中的其中一项接外部中断(以A接中断、上升沿触发举例),当A上升沿触发中断时,读取B相的电位,如果B是高电位,则判定为正转,角度加1;如果B是低电位,则判定为反转,转角减1。
利用这种算法经常出现角度跳变,或者圈数转多之后出现积累误差。下面举个例子来解释一下这种算法错误的地方。
在编码器转动过程中,尤其在启动/转向/停止过程中,会出现编码器正好在一个上升沿中断处反复震荡的情况,如下图所示,在震荡过程中:
从a到b的过程,A相上升沿触发中断,此时B相为低电位,角度减去一个单位;
从b到c的过程,A相下降沿,无任何动作;
从c到d的过程,A相上升沿触发中断,此时B相为低电位,角度减去一个单位;
从d到e的过程,A相下降沿,无任何动作;
从e到f的过程,A相上升沿触发中断,此时B相为低电位,角度减去一个单位;
……
编码器实际角度一直停留在蓝虚线处,也就是实际角度其实是没有变化的。但在反复震荡的过程当中,程序会判定角度在一直在减少,导致实际角度与程序计算的角度产生偏差。这就是程序造成的光栅编码器丢失角度的原因。
本程序算法:
硬件清单:
1、单片机最小系统一个(ATmega16芯片)
2、4位数码管一只(595芯片模块)
3、光栅编码器一只(360线)
实现功能:转动编码器,读取编码器转动角度,并显示在数码管上
原理图:
实物连线图:
程序算法介绍:
光栅编码器A相连接单片机外部中断0,B相连接外部中断1。中断触发方式均为任意电平变化触发中断。那么在一个周期内会触发4次中断,如图所示。
以编码器是360线举例,那么每次中断转动的角度是360/360/4=0.25°,即360线编码器分辨率可以达到0.25°,以此类推720线编码器分辨率是360/720/4=0.125°……。
每次中断触发后,判断另一相电位,如上图蓝色虚线所示:
a处触发中断 A相1,B相0
b处触发中断 A相1,B相1
c处触发中断 A相0,B相1
d处触发中断 A相0,B相0
e处触发中断 与a处相同,进入下一个循环
把A/B相看作是一个二进制数,那么:
a处,(AB)10=2
b处,(AB)11=3
c处,(AB)01=1
d处,(AB)00=0
e处,……
可以看出,正转对应的是2310……2310……,反转对应的是2013……2013……。
在程序中保存前一中断位置数值,在本次中断中进行对比。符合正转数值排序,则角度加0.25°,反之减去0.25°。该方法测试下来非常准确,解决了之前老是丢步的问题。
核心部分程序如下:
unsigned char encoder_A;//encoder_A需要初始化 encoder_A=(PIND&0x0c)/4;unsigned angle;//编码器角度变量void encoder(unsigned int X)//X为编码器线数。编码器AB值判断函数{ unsigned char B; CLI(); B=encoder_A;//保存上一次中断数值 encoder_A=(PIND&0x0c)/4;//读取本次中断数值 if((B==0 && encoder_A==1)||(B==1 && encoder_A==3)||(B==3 && encoder_A==2)||(B==2 && encoder_A==0)) //正方向判断 { angle=angle+9000/X;//角度加一个分辨率 if(angle==36000)angle=0;//角度超过360°则变为0° } else if ((B==0 && encoder_A==2)||(B==2 && encoder_A==3)||(B==3 && encoder_A==1)||(B==1 && encoder_A==0)) //反方向判断 { if(angle==0)angle=36000; //角度小于0°则变为360° angle=angle-9000/X; //角度减一个分辨率 } else ; SEI();} #pragma interrupt_handler int0_isr:iv_INT0//中断0服务程序void int0_isr(void){ encoder(360);}#pragma interrupt_handler int1_isr:iv_INT1//中断1服务程序void int1_isr(void){ encoder(360);} 程序源码下载地址:https://download.csdn.net/download/ludantongxue/11287703
增量式光栅编码器结构:
增量式编码器工作原理:
编码器码盘上刻有A、B窄缝,彼此错开1/4节距,使得A、B两相在转动过程中,输出的电信号相位错开90°。如下图所示:
网上程序错误解析:
程序算法是A/B中的其中一项接外部中断(以A接中断、上升沿触发举例),当A上升沿触发中断时,读取B相的电位,如果B是高电位,则判定为正转,角度加1;如果B是低电位,则判定为反转,转角减1。
利用这种算法经常出现角度跳变,或者圈数转多之后出现积累误差。下面举个例子来解释一下这种算法错误的地方。
在编码器转动过程中,尤其在启动/转向/停止过程中,会出现编码器正好在一个上升沿中断处反复震荡的情况,如下图所示,在震荡过程中:
从a到b的过程,A相上升沿触发中断,此时B相为低电位,角度减去一个单位;
从b到c的过程,A相下降沿,无任何动作;
从c到d的过程,A相上升沿触发中断,此时B相为低电位,角度减去一个单位;
从d到e的过程,A相下降沿,无任何动作;
从e到f的过程,A相上升沿触发中断,此时B相为低电位,角度减去一个单位;
……
编码器实际角度一直停留在蓝虚线处,也就是实际角度其实是没有变化的。但在反复震荡的过程当中,程序会判定角度在一直在减少,导致实际角度与程序计算的角度产生偏差。这就是程序造成的光栅编码器丢失角度的原因。
本程序算法:
硬件清单:
1、单片机最小系统一个(ATmega16芯片)
2、4位数码管一只(595芯片模块)
3、光栅编码器一只(360线)
实现功能:转动编码器,读取编码器转动角度,并显示在数码管上
原理图:
实物连线图:
程序算法介绍:
光栅编码器A相连接单片机外部中断0,B相连接外部中断1。中断触发方式均为任意电平变化触发中断。那么在一个周期内会触发4次中断,如图所示。
以编码器是360线举例,那么每次中断转动的角度是360/360/4=0.25°,即360线编码器分辨率可以达到0.25°,以此类推720线编码器分辨率是360/720/4=0.125°……。
每次中断触发后,判断另一相电位,如上图蓝色虚线所示:
a处触发中断 A相1,B相0
b处触发中断 A相1,B相1
c处触发中断 A相0,B相1
d处触发中断 A相0,B相0
e处触发中断 与a处相同,进入下一个循环
把A/B相看作是一个二进制数,那么:
a处,(AB)10=2
b处,(AB)11=3
c处,(AB)01=1
d处,(AB)00=0
e处,……
可以看出,正转对应的是2310……2310……,反转对应的是2013……2013……。
在程序中保存前一中断位置数值,在本次中断中进行对比。符合正转数值排序,则角度加0.25°,反之减去0.25°。该方法测试下来非常准确,解决了之前老是丢步的问题。
核心部分程序如下:
unsigned char encoder_A;//encoder_A需要初始化 encoder_A=(PIND&0x0c)/4;unsigned angle;//编码器角度变量void encoder(unsigned int X)//X为编码器线数。编码器AB值判断函数{ unsigned char B; CLI(); B=encoder_A;//保存上一次中断数值 encoder_A=(PIND&0x0c)/4;//读取本次中断数值 if((B==0 && encoder_A==1)||(B==1 && encoder_A==3)||(B==3 && encoder_A==2)||(B==2 && encoder_A==0)) //正方向判断 { angle=angle+9000/X;//角度加一个分辨率 if(angle==36000)angle=0;//角度超过360°则变为0° } else if ((B==0 && encoder_A==2)||(B==2 && encoder_A==3)||(B==3 && encoder_A==1)||(B==1 && encoder_A==0)) //反方向判断 { if(angle==0)angle=36000; //角度小于0°则变为360° angle=angle-9000/X; //角度减一个分辨率 } else ; SEI();} #pragma interrupt_handler int0_isr:iv_INT0//中断0服务程序void int0_isr(void){ encoder(360);}#pragma interrupt_handler int1_isr:iv_INT1//中断1服务程序void int1_isr(void){ encoder(360);} 程序源码下载地址:https://download.csdn.net/download/ludantongxue/11287703
举报
更多回帖
rotate(-90deg);
回复
相关问答
编码器
光电
为什么STM32
单片机
的定时
器
PWM输入捕获模式无法
读取
编码器
呢
2022-01-21
1563
关于51
单片机
与,绝对式
编码器
的连接使用
2016-12-30
14730
请问怎样去设计一种
单片机
与旋转
编码器
的接口?
2021-04-15
1326
光栅
编码器
有什么分类?
2019-10-18
2638
求教51
单片机
读
编码器
脉冲问题???
2017-08-17
9916
编码器
光栅
画法
2016-11-14
3139
编码器
测速使用的
单片机
和模块有哪些
2022-01-18
1402
51
单片机
如何控制磁
编码器
?
2023-10-27
277
单片机
与
编码器
连接
2017-02-26
6692
请问
单片机
如何模拟
编码器
ABZ脉冲?
2023-09-26
239
发帖
登录/注册
20万+
工程师都在用,
免费
PCB检查工具
无需安装、支持浏览器和手机在线查看、实时共享
查看
点击登录
登录更多精彩功能!
英国威廉希尔公司网站
william hill官网 版块
小组
免费开发板试用
ebook
直播
搜索
登录
×
20
完善资料,
赚取积分